Nous vérifions la vulnérabilité fermée et obtenons quatre nouveaux CVE

On m'a demandé de continuer la série d'articles sur la fermeture des vulnérabilités et sur la façon dont elles sont fermées (notre premier article peut être lu ici ). La dernière fois, nous avons découvert que même si le fabricant signale la fermeture de la vulnérabilité, alors en réalité, tout pourrait ne pas l'être.



Critères de sélection:


Les critères de sélection pour les vulnérabilités considérées cette fois étaient les mêmes (à l'exception que cette fois, je voulais examiner d'autres types de vulnérabilités):

  • il devrait y avoir un exploit - nous voulons voir qu'avant la mise à jour, tout était bien mal exploité , et après cela il est devenu bon;
  • la vulnérabilité doit être critique (idéalement RCE) et avoir un score élevé;
  • le produit doit être open source;
  • le produit ne doit pas être abandonné et utilisé activement;
  • la vulnérabilité devrait être relativement nouvelle;
  • comme toujours, l'essentiel est que nous-mêmes nous intéressions.

Quoi et comment j'ai choisi:


Je suis allé sur vulners.com et j'ai demandé à montrer tous les exploits avec exploit-db.com au cours des deux dernières semaines. Cette fois dans la catégorie Web, presque tous les exploits ont été créés par Ihsan Sencan, mais en raison du fait qu'ils concernent le plus souvent des injections SQL dans de vieilles applications et plugins non pris en charge, je les ai supprimés. Parmi les produits restants, seul l'outil de gestion de projet ProjeQtOr 7.2.5 avec la vulnérabilité CVE-2018-18924 est entré dans la catégorie «non abandonné et en développement actif».
Cette vulnérabilité répondait à tous les critères de sélection:

  • il y a un exploit ;
  • Vulnérabilité RCE (bien qu'elle nécessite l'autorisation de l'utilisateur);
  • le produit est assez open source;
  • le produit n'est pas abandonné, en 2018 il y avait 28 versions et seulement sourceforge.net il y avait 702 téléchargements (et la plupart des téléchargements de mise à jour résolvent le problème CVE, ce qui indique très probablement que les gens ont vu CVE et ont commencé à mettre à jour);
  • CVE du 4 novembre, un exploit du 25 octobre, cela répond aux exigences de nouveauté;
  • J'ai regardé le problème et sa solution, je me suis intéressé (plus à ce sujet plus tard).

Comprendre l'outil de gestion de projet ProjeQtOr


Nous lisons la description de l' exploit et la description CVE sur nist.gov , nous comprenons que la version 7.2.5 n'est vulnérable que pour un utilisateur autorisé. Et aussi que vous pouvez télécharger un fichier .shtml en tant qu'image, bien que le message d'erreur "Ce fichier n'est pas une image valide" sera affiché, mais le fichier sera toujours enregistré dans les images sur le serveur et accessible via un lien direct dans l' hôte / fichiers / images / nom_image .



L'accès via un lien direct est bon, mais ici vous devez encore deviner le nom avec lequel le fichier sera téléchargé. Nous avons de la chance, et ce n'est pas aléatoire, mais il est généré à partir de l'heure actuelle au format: année, mois, jour, heures, minutes, secondes. Le résultat est un tel numéro 20181114140320. Ensuite, l'ID utilisateur, puis le nom de fichier d'origine passent par le trait de soulignement. Il y a pas mal d'inconnues:

  • Fuseau horaire sur le serveur
  • si l'horloge du serveur est en panne;
  • ID utilisateur

Et encore une fois, nous avons de la chance: si vous téléchargez une image valide, tous ces paramètres nous seront signalés. Il n'est pas difficile de passer en revue plusieurs options de liens (plusieurs, car il y a des secondes, mais il est difficile de les entrer tout de suite).



En général, l'obtention du nom de fichier n'est pas un problème. Nous continuons. Et nous pensons, pourquoi ne pas simplement télécharger un script php? Nous essayons de le télécharger, la même fenêtre apparaît, mais le fichier n'apparaît pas dans le répertoire. Il est temps de regarder le code!

Le script uploadImage.php est responsable du téléchargement de l'image sur le serveur dans la version 7.2.5. Nous sommes intéressés par les lignes 100 à 117.

if (substr($ext,0,3)=='php' or substr($ext,0,4)=='phtm') { if(@!getimagesize($uploadedFile['tmp_name'])) { $error=i18n('errorNotAnImage'); } else { traceHack("Try to upload php file as image in CKEditor"); } } else { if ( ! move_uploaded_file($uploadedFile['tmp_name'], $uploadfile)) { $error = htmlGetErrorMessage(i18n('errorUploadFile','hacking ?')); errorLog(i18n('errorUploadFile','hacking ?')); } } } if (!$error) { if(@!getimagesize($uploadfile)) { $error=i18n('errorNotAnImage'); } } 

La ligne 100 est chargée de vérifier l'extension du fichier: s'il s'agit de php ou phtm, le fichier est rejeté et non enregistré. Par conséquent, les fichiers php n'apparaissent pas dans le répertoire "files / images /". La ligne 115 crée l'erreur que nous voyons, mais ne fait rien avec le fichier.

Eh bien, ne quittons pas l'exploit et téléchargeons le fichier avec l'extension .shtml. Ici, il vaut la peine de faire une petite digression et de dire ce qu'est le .shtml et avec quoi il est mangé.

SHTML et SSI


Définition Wikipédia:

SSI (Server Side includes - inclusion côté serveur) - un langage simple pour l '"assemblage" dynamique de pages Web sur le serveur à partir des composants individuels et la livraison du document HTML reçu au client. Implémenté dans le serveur Web Apache à l'aide du module mod_include. La fonctionnalité incluse dans les paramètres par défaut du serveur Web vous permet d'inclure des fichiers HTML, par conséquent, pour utiliser les instructions, le fichier doit se terminer par l'extension .shtml, .stm ou .shtm.

Dans vos propres mots:

SHTML est du HTML qui peut exécuter des jeux d'instructions côté serveur. De l'utile, il y a une fonction exec qui exécute des commandes arbitraires sur le serveur (oui, nous pouvons télécharger le fichier en utilisant le code HTML et l'exécuter).

Voici un exemple de code pour exécuter du code arbitraire:

 <!--#exec cmd=”ls” --> 

La bonne nouvelle est que cette fonctionnalité n'est pas activée par défaut sur le serveur Apache2, et pour l'activer, vous devez danser avec un tambourin. En quelques heures de sélection de la configuration, j'ai pu faire fonctionner le retour des variables d'environnement, mais pas la commande. Voici mon code SSI:

 <html> <head> <title>thegeekstuff.com</title> </head> <body> <p> Today is <!--#echo var="DATE_LOCAL" --> <!--#exec cmd="ls" --> </p> </body> </html>  : Today is Wednesday, 14-Nov-2018 17:29:14 MSK [an error occurred while processing this directive] 

Si quelqu'un vous dit quoi écrire dans la config pour qu'elle fonctionne correctement, j'adorerais la lire.

Exploiter la vulnérabilité


Si les étoiles convergent, vous pouvez télécharger le fichier shtml et exécuter des commandes arbitraires (ou, comme moi, voir l'heure sur le serveur).

Regarder le patch


La prochaine version est 7.2.6, mais il n'y a pas de changement concernant la vulnérabilité qui nous intéresse (nist.gov trompé à nouveau).

Nous regardons la version 7.2.7 et il semble que tout soit corrigé (les développeurs eux-mêmes disent que tout est corrigé juste dans cette version). Il y a deux changements clés:

1. Parmi les extensions interdites, "shtm" a été ajouté (si les 4 premiers caractères sont tels, shtml tombe également ici):

 if (substr($ext,0,3)=='php' or substr($ext,0,4)=='phtm' or substr($ext,0,4)=='shtm') { 


2. Les fichiers qui ne sont pas des images sont maintenant supprimés:

  if(@!getimagesize($uploadfile)) { $error=i18n('errorNotAnImage'); kill($uploadfile); } 

Il semblerait que vous pouvez diverger, car les non-images sont supprimées et shtml n'essaie même pas de persister. Mais je n’aimais pas toujours s’ils essayaient de résoudre un problème avec les listes noires. Par exemple, dans certains pays, les entreprises interdisent les réseaux sociaux. Cela conduit au fait que les utilisateurs commencent à utiliser les «miroirs» des réseaux sociaux, où leurs noms d'utilisateur et mots de passe sont volés. Leurs mots de passe coïncident avec les mots de passe d'entreprise, mais il peut alors y avoir des problèmes bien plus importants qu'un employé feuilletant un instagram autour d'une tasse de café.

Dans la programmation Web et sa sécurité, les listes noires sont également mauvaises.

Contournez la liste noire de ProjeQtOr


Eh bien, tout est simple. Tout d'abord, voyons quels fichiers Apache2 + PHP peut interpréter avec les paramètres par défaut (tout a été installé sur Ubuntu 16.04 avec un référentiel mis à jour). La directive «FilesMatch» est responsable de la capacité d'interpréter les fichiers. Nous effectuons une recherche avec la commande "grep -r" <FilesMatch "/ etc / apache2" et voici le résultat:

 /etc/apache2/mods-available/php7.0.conf:<FilesMatch ".+\.ph(p[3457]?|t|tml)$"> /etc/apache2/mods-available/php7.0.conf:<FilesMatch ".+\.phps$"> /etc/apache2/mods-available/php7.0.conf:<FilesMatch "^\.ph(p[3457]?|t|tml|ps)$"> /etc/apache2/sites-available/default-ssl.conf: <FilesMatch "\.(cgi|shtml|phtml|php)$"> /etc/apache2/apache2.conf:<FilesMatch "^\.ht"> 

Dans la configuration default-ssl.conf, toutes les extensions sont simplement listées dans leur intégralité; ce sont: cgi, shtml, phtml, php. Hélas, tout sauf cgi est filtré dans ProjeQtOr.

La configuration php7.0.conf est beaucoup plus intéressante, les extensions y sont définies par l'expression régulière. Nous obtenons:
ExtensionCe qui est filtré
phpsubstr ($ ext, 0,3) == 'php'
php3substr ($ ext, 0,3) == 'php'
php4substr ($ ext, 0,3) == 'php'
php5substr ($ ext, 0,3) == 'php'
php7substr ($ ext, 0,3) == 'php'
phtRIEN
phtml3substr ($ ext, 0.4) == 'phtm'

Génial, une extension de fichier non filtrée est trouvée. Nous vérifions qu'il est vraiment interprété.

Créez un fichier test.pht avec le contenu suivant:

 <?php phpinfo(); 

Nous allons à ce fichier dans le navigateur et voyons des informations sur le php installé. Remarquablement, la liste noire a été contournée, tandis que pour les paramètres non par défaut, pour une raison quelconque, d'autres extensions d'interprétation pourraient être autorisées.

Nous chargeons notre fichier de test dans l'outil de gestion de projet ProjeQtOr. Bien sûr, nous obtenons une erreur, car ce n'est pas une image (dans la version antérieure à 7.2.7, nous avons déjà l'exécution de code sur le serveur, car changer phpinfo en exécutant des commandes n'est pas difficile). Dans la version 7.2.7, le fichier est supprimé et le code n'est pas exécuté.

Mais nous ne sommes pas fâchés et ne contournons pas le contrôle de l'image.

Image PHP


La vérification si le fichier téléchargé est une image dans l'outil de gestion de projet ProjeQtOr est effectuée par la fonction getimagesize, qui regarde simplement l'en-tête du fichier transféré.

Profitant du fait qu'il peut y avoir des ordures dans le fichier php et que l'interprétation du code php ne commence qu'avec les caractères «<? Php», nous écrivons un petit code qui écrit d'abord l'image, puis le code php dont nous avons besoin. Comme image, nous enverrons une capture d'écran de la fenêtre d'erreur. 3 lignes de code python et vous avez terminé:

 data = open ('test.png','rb').read() data += open ('test.pht','rb').read() open ('new_pht_png.pht','wb').write(data) 

Vous pourriez probablement écrire un en-tête d'image valide au début du fichier, mais c'est plus facile, et plus encore, l'image est affichée dans tous les visualiseurs.

Nous téléchargeons cette création sur le serveur et, voilà, elle est chargée (et affichée dans la visionneuse sous forme d'image), et il est également agréable de voir le nom complet avec lequel ce fichier a été téléchargé.



Nous allons dans le fichier téléchargé localhost / files / images / 20181114171730_1_new_pht_png.pht et voyons l'image téléchargée sous forme de texte, et la sortie phpinfo en dessous. Il est clair que remplacer phpinfo par un simple shell web n'est pas difficile. Par exemple, ceci: <? Php system ($ _ GET ['cmd']);



Une fois que vous avez commencé à sélectionner les téléchargements de fichiers, vous devez terminer le travail et voir où il y a d'autre téléchargement de fichiers avec ou sans listes noires.

Un autre téléchargement de fichier


Nous regarderons dans la dernière version disponible. En supposant que vous utilisez la même fonction pour télécharger des fichiers comme auparavant, c'est-à-dire move_uploaded_file, nous le recherchons dans le répertoire du projet "grep -r" move_uploaded_file "./". Nous obtenons les 5 fichiers suivants:

./tool/uploadImage.php
./tool/saveDocumentVersion.php
./tool/uploadPlugin.php
./tool/import.php
./tool/saveAttachment.php

File uploadImage.php - déjà regardé.
File saveDocumentVersion.php - télécharge les versions des documents (comme son nom l'indique). Nous essayons de télécharger un document et de le regarder (pour commencer, nous chargerons toujours une image). Après le téléchargement, nous voyons que l'extension .1 est ajoutée au fichier. Nous regardons dans le code comment le nom est obtenu (cela se fait à la ligne 229):

 $uploadfile = $dv->getUploadFileName(); 

La fonction getUploadFileName est déclarée dans le fichier DocumentVersionMain.php. Là, à la ligne 227, nous voyons que «.» Est ajouté au nom renvoyé. et l'ID du document. Nous ne pouvons pas contourner même le point ajouté:

 return $uploaddir . $paramPathSeparator . $fileName . '.' . $this->id; 

Le fichier uploadPlugin.php n'est accessible qu'aux administrateurs et le fait que le plugin puisse avoir un mauvais code est très logique et difficile à éliminer sans avoir à entrer la validation du plugin (comme le font les CMS populaires). Bien sûr, lorsque vous essayez de télécharger quelque chose, il se charge avec succès, puis il est exécuté.

Le fichier import.php n'est également disponible que pour les administrateurs. Lors du téléchargement d'un fichier, on nous dit qu'il doit s'agir d'un fichier csv ou d'un fichier xlsx. Bien sûr, nous essayons de charger le fichier php et voyons une erreur:

ERREUR - Le type de fichier fourni et le format de fichier sélectionné ne correspondent pas


Importation abandonnée

Le problème est que, comme dans le bogue d'origine de CVE, le fichier n'est pas supprimé, mais reste disponible dans localhost / files / attach / import / test.php .

Le fichier saveAttachment est utilisé lors du chargement de pièces jointes (par exemple, lors du chargement de votre propre image). Le script PHP n'y rampe pas, car il y a une protection du formulaire:

 if (substr($ext,0,3)=='php' or substr($ext,0,4)=='phtm' or substr($ext,0,4)=='shtm') { $attachment→fileName.=".projeqtor"; 

il s'avère que les fichiers d'extension php *, phtm *, shtm * l'extension ".projeqtor" est ajoutée, c'est-à-dire, évidemment notre fichier pht y rampera (même sans explorer les images). Nous essayons, et nous obtenons tout à l'adresse localhost / files / attach / attachment_1 / test.pht .

Résultat total de cinq emplacements de téléchargement de fichiers rapidement trouvés:

  • réussi à charger le script php ou pht 4 fois;
  • la validation de la liste noire est en deux;
  • la validation de la liste blanche n'est nulle part;
  • une fois n'a pas réussi à télécharger le fichier (n'a pas pu télécharger, mais n'a pas pu s'exécuter), car l'expansion changeait

Conclusions sur l'outil de gestion de projet ProjeQtOr et CVE-2018-18924



  • la vulnérabilité signalée a été pratiquement éliminée;
  • il existe d'autres vulnérabilités dans le code (signalées aux développeurs, et ils ont même promis des listes blanches d'extensions);
  • une configuration correcte du serveur Apache2 pourrait nous sauver de tout (limiter les formats exécutables aux seuls nécessaires, interdire l'exécution de scripts dans les dossiers utilisateurs);
  • nist.gov ne contient pas la dernière version vulnérable.

Note de maîtresse


  • refuser les listes noires dans la mesure du possible (je ne sais pas où cela est impossible);
  • soyez prudent et attentif lors du traitement des fichiers téléchargés (il vaut mieux qu'ils soient au même endroit, et non répartis par 5);
  • un serveur Web correctement configuré évite de nombreux problèmes dans le code du projet (il est important d'écrire du code et de bien configurer le serveur).

Réponse détaillée des développeurs


La première réponse des développeurs était quelque chose comme «nous avons tout corrigé, alors voyez le code corrigé». J'ai dû peindre en détail où se trouvent certains problèmes et comment ils peuvent être exploités.

Il a ensuite reçu une réponse détaillée: «oui, il y a des problèmes, et ils seront corrigés dans la version 7.3.0. Des listes blanches seront également ajoutées pour les images à la fois pour xlslx et csv. » Ils ont également écrit qu'ils avaient recommandé d'ajouter les répertoires «pièces jointes» et «documents» en dehors de l'accès Web dans les instructions d'installation.

Les développeurs m'ont permis d'enregistrer CVE et d'écrire un article après la mise à jour (qui est sorti et est disponible en téléchargement ).

Conclusion


Comme je l'ai écrit au début, pas mal de gens ont téléchargé la mise à jour décidant CVE (plus de 500 téléchargements), et c'est cool que les gens mettent à jour leur logiciel vulnérable, mais c'est triste que le logiciel reste vulnérable.

En conséquence, quatre CVE m'ont été attribués ainsi qu'à notre entreprise: CVE-2018-19307, CVE-2018-19308, CVE-2018-19309, CVE-2018-19310.

Source: https://habr.com/ru/post/fr430408/


All Articles