[JAVA] Attaquons la vulnérabilité (1) injection de commande OS (injection de type OGNL)

introduction

** La meilleure façon de comprendre une vulnérabilité est de l'attaquer. ** **

Cependant, trouvons un site potentiellement vulnérable et attaquons-le! Je ne dis pas ça. C'est une bonne idée d'exécuter une application vulnérable sur une machine virtuelle que vous utilisez uniquement et d'essayer de l'attaquer.

De nombreuses vulnérabilités ont été implémentées dans l '[application Web pleine de bogues] précédemment introduite (http://qiita.com/tamura__246/items/7275c7406706fb0057e8). Téléchargez l'application Web depuis ici et démarrez-la avec la commande suivante.

java -jar easybuggy.jar

Cette application Web implémente actuellement les vulnérabilités suivantes:

--XSS (Cross Site Scripting) --Injection SQL

Cette fois, je voudrais attaquer ** "injection de commande OS" ** (plus précisément, "injection de type OGNL") parmi celles-ci et causer des dommages fatals au serveur: smiley:

Qu'est-ce que l'injection de commandes OS?

L'injection de commande OS fait référence à une attaque qui exécute la commande OS d'un serveur via une application Web ou autre.

oscmdinjct.png

Par exemple, supposons qu'une application Web transmette certains paramètres de requête non vérifiés comme arguments à une commande du système d'exploitation et les exécute. Ce n'est peut-être pas un problème car les utilisateurs ordinaires ne l'utilisent que normalement, mais les utilisateurs malveillants utilisent une chaîne de caractères telle que "rm -fr /" avec un délimiteur tel que "; " (point-virgule). Vous pouvez envoyer les paramètres ajoutés et supprimer tous les fichiers sur le serveur.

Attaquons

Attaquons maintenant la vulnérabilité d'injection de commande du système d'exploitation.

Téléchargez l'application Web à partir d'ici (https://github.com/k-tamura/easybuggy/releases) et lancez-la avec java -jar easybuggy.jar. Cette fois, je suis connecté à CentOS 6 avec SELinux désactivé en tant qu'utilisateur root qui a la permission d'exécuter des commandes.

* La version 1.3.2 est utilisée dans cet article. Le comportement peut changer dans les versions futures.

Après le démarrage, accédez à [http: // localhost: 8080](http: // localhost: 8080). Il y a une section intitulée «Vulnérabilité» au milieu de l'écran ci-dessous.

main.png

Le cinquième lien à partir du haut est "Injection de commande du système d'exploitation", alors cliquez dessus.

Lorsque vous cliquez dessus, l'écran suivant s'affiche.

ognl1.png

C'est une fonction simple qui affiche la réponse lorsque vous entrez une formule. Vous pouvez utiliser java.lang.Math pour la formule.

Tout d'abord, essayez d'entrer une formule simple telle que «1 + 2» ou «Math.sqrt (5)». Vous devriez obtenir la bonne réponse. Entrez ensuite une valeur non valide sous forme de formule telle que «abc». Un message d'erreur s'affiche.

err1.png

À première vue, cette fonctionnalité semble fonctionner correctement.

Cependant, comme décrit dansInfo.jpg en bas de l'écran. Entrez @ Runtime @ getRuntime (). Exec ('rm -fr / your-important-dir /') dans, et cliquez sur le bouton de calcul, le répertoire sur le serveur (/ your-important-dir /) Sera supprimé.

* Remarque: `/ your-important-dir /` doit être un chemin absolu vers un répertoire sur le serveur que vous pouvez supprimer, ou avant de supprimer Veuillez faire une sauvegarde. Aussi, pour Windows, utilisez le mand `rmdir / s / q` au lieu de la commande` rm -fr`.

Essayons-le réellement. Le répertoire cible doit être / etc. Si vous vérifiez la structure actuelle des répertoires sous / avec la commande ll ( ls -la), ce sera comme suit.

$ ll /
102 au total
dr-xr-xr-x.2 racine racine 4096 23 avril 03:46 2017 bin
dr-xr-xr-x.5 racine racine 5120 26 avril 21:53 2017 boot
drwxr-xr-x.20 racine racine 3820 1 juin 22:57 2017 dev
drwxr-xr-x.119 racine racine 12288 1 juin 22:57 2017 etc
drwxr-xr-x.4 racine racine 4096 2 avril 00:41 2016 home
dr-xr-xr-x.11 racine racine 4096 19 avril 21:20 2017 lib
dr-xr-xr-x.10 racine racine 12288 23 avril 03:46 2017 lib64
drwx------.2 racine racine 16384 8 août 01:21 2015 lost+found
drwxr-xr-x.2 racine racine 4096 18 mars 20:24 2017 media
drwxr-xr-x.4 racine racine 4096 15 novembre 18:00 2015 mnt
drwxr-xr-x.8 racine racine 4096 1er avril 21:49 2017 opt
dr-xr-xr-x.277 racine racine 0 1 juin 22:56 2017 proc
dr-xr-x---.78 racine racine 4096 2 juin 07:39 2017 root
dr-xr-xr-x.2 racine racine 12288 20 avril 03:27 2017 sbin
drwxr-xr-x.7 racine racine 0 1 juin 22:56 2017 selinux
drwxr-xr-x.2 racine racine 4096 23 septembre 20:50 2011 srv
drwxr-xr-x 13 racine racine 0 1 juin 22:56 2017 sys
drwxrwxrwx.3 racine racine 4096 2 juin 07:41 2017 tmp
drwxr-xr-x.14 racine racine 4096 23 septembre 08:32 2016 usr
drwxr-xr-x.23 racine racine 4096 5 octobre 17:12 2016 var

Faites une sauvegarde avant de démarrer.

$ cp -pr /etc etc_bk

Entrez @ Runtime @ getRuntime (). Exec ('rm -fr / etc') et cliquez sur le bouton Calculer.

rmetc1.png

Ensuite, exécutez à nouveau la commande ll.

$ ll /
90 au total
dr-xr-xr-x.2 0 0 4096 22 avril 18:46 2017 bin
dr-xr-xr-x.5 0 0 5120 26 avril 12:53 2017 boot
drwxr-xr-x.20 0 0 3820 1 juin 13:57 2017 dev
drwxr-xr-x.4 0 0 4096 1er avril 15:41 2016 home
dr-xr-xr-x.11 0 0 4096 19 avril 12:20 2017 lib
dr-xr-xr-x.10 0 0 12288 22 avril 18:46 2017 lib64
drwx------.2 0 0 16384 7 août 16:21 2015 lost+found
drwxr-xr-x.2 0 0 4096 18 mars 11:24 2017 media
drwxr-xr-x.4 0 0 4096 15 novembre 09:00 2015 mnt
drwxr-xr-x.8 0 0 4096 1 avril 12:49 2017 opt
dr-xr-xr-x.296 0 0 0 1 juin 13:56 2017 proc
dr-xr-x---.78 0 0 4096 9 juin 14:09 2017 root
dr-xr-xr-x.2 0 0 12288 19 avril 18:27 2017 sbin
drwxr-xr-x.7 0 0 0 1 juin 13:56 2017 selinux
drwxr-xr-x.2 0 0 4096 23 septembre 11:50 2011 srv
drwxr-xr-x 13 0 0 0 1 juin 13:56 2017 sys
drwxrwxrwx.8 0 0 4096 8 juin 14:31 2017 tmp
drwxr-xr-x.14 0 0 4096 22 septembre 23:32 2016 usr
drwxr-xr-x.23 0 0 4096 5 octobre 08:12 2016 var

Le répertoire / etc a disparu. Il s'agit d'une injection de commande du système d'exploitation. J'ai supprimé / etc ici, mais ** Bien sûr, vous pouvez supprimer d'autres répertoires, et vous pouvez utiliser des commandes autres que la commande rm. Puisque vous pouvez manipuler les commandes du système d'exploitation, diverses attaques sont possibles. ** **

Comment les attaquants trouvent les vulnérabilités

Vous pourriez penser, "Mais l'attaquant ne peut pas connaître la chaîne qui cause le problème (@ Runtime @ ...) ??" Dans cette application, la méthode d'attaque de la vulnérabilité est intentionnellement décrite à l'écran, mais bien sûr, il n'y a rien de tel dans une application normale. Comment les attaquants trouvent-ils les vulnérabilités?

** Les astuces sont dans le message d'erreur. ** Les messages d'erreur peuvent également être une source de conjectures pour l'implémentation d'une application par un attaquant.

Affichons un message d'erreur avec différents types de valeurs d'entrée invalides. Par exemple, si vous entrez Math.sqrt (5x) sur cet écran et cliquez sur le bouton de calcul, vous verrez l'erreur suivante:

sqrt5x.png

Un message en anglais suit "Formule illégale". Si vous avez de l'expérience dans le développement d'applications, vous pouvez deviner que le message d'erreur renvoyé par une bibliothèque est concaténé tel qu'il est après "Formule illégale".

Ensuite, laissez'Mathêtre le nom complet de la classe, entrezjava.lang.Math.sqrt (5)` et cliquez sur le bouton de calcul.

javalangMathsqrt5.png

Un message d'erreur a été émis indiquant que "@" (à la marque) qui n'aurait pas dû être entré a été entré. "@" Semble avoir un sens.

En outre, entrez sqrt (5) sans Math. et cliquez sur le bouton de calcul. Vous verrez une erreur similaire à la suivante:

sqrt5.png

Cette fois, le mot-clé "ʻognl.OgnlContext`" que je n'ai pas entré est apparu. En regardant cela, si vous êtes une personne bien informée, vous pouvez deviner que c'est la technologie appelée "** OGNL **" qui réalise cette fonction. OGNL est une bibliothèque de langages d'expression avec une grammaire de type Java.

En regardant Spécifications OGNL, il y a la description suivante.

Calling Static Methods You can call a static method using the syntax @class@method(args).

Il semble que les appels de méthodes statiques peuvent être réalisés avec @ class @ method (args).

"Cela signifie ... dans l'application, vous pouvez simplement remplacer Math. dans la valeur d'entrée par@ Math @et l'exécuter en tant qu'expression OGNL:" Vous pouvez deviner.

Math.sqrt (5) → Remplacer par @ Math @ sqrt (5) → Exécuter en tant qu'expression OGNL

Pour vous assurer que cette hypothèse est correcte, essayez de taper @ System @ currentTimeMillis ().

@ System @ currentTimeMillis ()@ System @ currentTimeMillis () reste (non remplacé) → Exécuter en tant qu'expression OGNL

Si c'est correct, vous devriez pouvoir obtenir le temps écoulé en millisecondes depuis le 1er janvier 1970 à minuit.

sct.png

Comme le montrent les résultats, nous pouvons déterminer que la supposition est probablement correcte.

À ce stade, vous pouvez imaginer taper "@ System @ exit (0)" pour arrêter le processus d'application Web, ou avant cela ...: lunettes de soleil:.

Quel genre de mise en œuvre

De quel type de mise en œuvre s'agit-il réellement? Jetez un œil au code source (https://github.com/k-tamura/easybuggy/blob/master/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OGNLExpressionInjectionServlet.java). Les parties importantes sont:

try {
    Object expr = Ognl.parseExpression(expression.replaceAll("Math\\.", "@Math@"));
    value = Ognl.getValue(expr, ctx);
} catch (OgnlException e) {
    isValid = false;
    if (e.getReason() != null) {
        errMessage = e.getReason().getMessage();
    }

Comme vous pouvez le deviner, nous remplaçons simplement Math. par` @ Math @ ʻet l'exécutons comme une expression OGNL.

Au fait, cette fois, j'ai exécuté l'injection de commande OS, mais comme je peux aussi exécuter du code Java, je peux aussi dire "** injection de code ". De plus, on peut dire qu'il s'agit d'une « injection de type OGNL **» lorsqu'il est classé plus en détail.

À propos de l'injection de type OGNL

Le nom de l'injection de style OGNL a été popularisé par "** Struts 2 **", qui est un framework bien connu pour les applications Web. En mars de cette année, une vulnérabilité dans l'injection de type OGNL a été découverte dans Struts 2, causant des dommages tels que des fuites d'informations sur plusieurs sites Web. Selon certaines rumeurs, un grand nombre de demandes frauduleuses ont été envoyées à des serveurs japonais depuis l'étranger. J'ai en fait essayé cette vulnérabilité (dans l'application Struts locale, bien sûr), mais c'est ** une attaque très facile et dangereuse **.

C'est cette vulnérabilité qui représente une part importante des vulnérabilités Struts 2 signalées. Les expressions OGNL sont utilisées dans diverses parties de Struts 2 et les expressions régulières sont utilisées pour vérifier la validité des expressions afin que l'injection d'expressions OGNL ne se produise pas dans chaque partie. Cependant, même si une expression régulière qui corrige la vulnérabilité est publiée, une méthode d'attaque avec une nouvelle chaîne de caractères qui la contourne a été trouvée, et la situation actuelle est qu'elle n'a pas encore atteint une solution fondamentale.

Contre-mesures pour l'injection de commande / code du système d'exploitation

Alors, quel genre de mesures faut-il prendre? Les éléments suivants peuvent être considérés comme des contre-mesures.

  • En premier lieu, nous ne créerons pas une fonction qui inclut un tel risque (rejetée au stade de la conception)
  • Envisagez une autre méthode de mise en œuvre
  • Ne pas renvoyer un message d'erreur spécifique à l'implémentation à l'utilisateur
  • Effectuer un contrôle de validation de la valeur d'entrée
  • Exécutez des applications Web avec les privilèges d'utilisateur appropriés (tels que les privilèges d'utilisateur Tomcat) --Protéger avec les fonctionnalités du système d'exploitation (Unix chroot jail, AppArmor, SELinux, etc.)
  • Sécurisé avec les fonctionnalités JVM (Security Manager)

Faisons en fait certains d'entre eux.

Exécuter avec les privilèges d'utilisateur appropriés

Que faire si j'exécute une application Web autre que l'utilisateur root? Passons à l'utilisateur tomcat et vérifions.

$ su tomcat

Après avoir lancé l'application Web, tapez @ Runtime @ getRuntime (). Exec ('rm -fr / etc') et cliquez sur le bouton Calculer. Aucune erreur n'a été affichée. Qu'est-il arrivé?

$ ll /
102 au total
dr-xr-xr-x.2 racine racine 4096 23 avril 03:46 2017 bin
dr-xr-xr-x.5 racine racine 5120 26 avril 21:53 2017 boot
drwxr-xr-x.20 racine racine 3820 1 juin 22:57 2017 dev
drwxr-xr-x.119 racine racine 12288 1 juin 22:57 2017 etc
drwxr-xr-x.4 racine racine 4096 2 avril 00:41 2016 home
dr-xr-xr-x.11 racine racine 4096 19 avril 21:20 2017 lib
dr-xr-xr-x.10 racine racine 12288 23 avril 03:46 2017 lib64
drwx------.2 racine racine 16384 8 août 01:21 2015 lost+found
drwxr-xr-x.2 racine racine 4096 18 mars 20:24 2017 media
drwxr-xr-x.4 racine racine 4096 15 novembre 18:00 2015 mnt
drwxr-xr-x.8 racine racine 4096 1er avril 21:49 2017 opt
dr-xr-xr-x.296 racine racine 0 1 juin 22:56 2017 proc
dr-xr-x---.78 racine racine 4096 9 juin 23:09 2017 root
dr-xr-xr-x.2 racine racine 12288 20 avril 03:27 2017 sbin
drwxr-xr-x.7 racine racine 0 1 juin 22:56 2017 selinux
drwxr-xr-x.2 racine racine 4096 23 septembre 20:50 2011 srv
drwxr-xr-x 13 racine racine 0 1 juin 22:56 2017 sys
drwxrwxrwx.8 racine racine 4096 9 juin 23:11 2017 tmp
drwxr-xr-x.14 racine racine 4096 23 septembre 08:32 2016 usr
drwxr-xr-x.23 racine racine 4096 5 octobre 17:12 2016 var

Comme vous pouvez le voir, / etc n'a pas été supprimé. Cela dit, les commandes qui peuvent être exécutées par l'utilisateur exécutant l'application Web (comme rm -fr / home / tomcat / anydir) peuvent également être exécutées par cette attaque. Cependant, cela seul peut être considéré comme une mesure assez efficace.

Protéger avec les fonctions du système d'exploitation (SELinux)

Si SELinux est activé, supprimera-t-il l'injection de commande du système d'exploitation? Passez à nouveau à l'utilisateur root pour activer SELinux.

$ vi /etc/selinux/config
# SELINUX=disabled
SELINUX=enforcing

Après avoir apporté des modifications, redémarrez CentOS. Après avoir lancé l'application Web, tapez @ Runtime @ getRuntime (). Exec ('rm -fr / etc') et cliquez sur le bouton Calculer.

$ ll /
90 au total
dr-xr-xr-x.2 0 0 4096 22 avril 18:46 2017 bin
dr-xr-xr-x.5 0 0 5120 26 avril 12:53 2017 boot
drwxr-xr-x.20 0 0 3820 1 juin 13:57 2017 dev
drwxr-xr-x.4 0 0 4096 1er avril 15:41 2016 home
dr-xr-xr-x.11 0 0 4096 19 avril 12:20 2017 lib
dr-xr-xr-x.10 0 0 12288 22 avril 18:46 2017 lib64
drwx------.2 0 0 16384 7 août 16:21 2015 lost+found
drwxr-xr-x.2 0 0 4096 18 mars 11:24 2017 media
drwxr-xr-x.4 0 0 4096 15 novembre 09:00 2015 mnt
drwxr-xr-x.8 0 0 4096 1 avril 12:49 2017 opt
dr-xr-xr-x.296 0 0 0 1 juin 13:56 2017 proc
dr-xr-x---.78 0 0 4096 9 juin 14:09 2017 root
dr-xr-xr-x.2 0 0 12288 19 avril 18:27 2017 sbin
drwxr-xr-x.7 0 0 0 1 juin 13:56 2017 selinux
drwxr-xr-x.2 0 0 4096 23 septembre 11:50 2011 srv
drwxr-xr-x 13 0 0 0 1 juin 13:56 2017 sys
drwxrwxrwx.8 0 0 4096 8 juin 14:31 2017 tmp
drwxr-xr-x.14 0 0 4096 22 septembre 23:32 2016 usr
drwxr-xr-x.23 0 0 4096 5 octobre 08:12 2016 var

C'est parti ... Il ne semble pas protéger autre chose que les répertoires que SELinux protège par défaut (par exemple / selinux). Au moins lorsque SELinux, qui est le paramètre par défaut, est activé, il semble qu'il n'y ait aucun effet sur l'injection de commande du système d'exploitation.

Protéger avec les fonctionnalités JVM (Security Manager)

Java possède une fonctionnalité appelée «** Security Manager **» qui protège les opérations JVM des utilisateurs malveillants. Et si j'avais cela activé?

Pour activer SecurityManager, ajoutez ce qui suit aux options lors du démarrage d'easybuggy.jar.

-Djava.security.manager -Djava.security.policy=catalina.policy
* Lors du démarrage d'EasyBuggy avec la commande `mvn`, décommentez la ligne suivante dans pom.xml.
<!-- <argument>-Djava.security.manager</argument>
<argument>-Djava.security.policy=catalina.policy</argument> -->

Veuillez télécharger «catalina.policy» depuis ici. Ce fichier n'empêche pas l'injection de commande du système d'exploitation par défaut, mais vous pouvez l'empêcher en apportant les modifications suivantes.

** ・ Pour Linux (CentOS 6.3) **

grant {
    //N'autorisez pas toutes les opérations sur tous les fichiers, n'autorisez que ce dont vous avez besoin
    // permission java.io.FilePermission "<<ALL FILES>>", "write, read, execute, delete";
    permission java.io.FilePermission "-", "write, read, execute, delete";
    permission java.io.FilePermission "/usr/java/-", "write, read, execute";
    permission java.io.FilePermission "/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.79.x86_64/-", "write, read, execute";
・ ・ ・

** Pour les fenêtres **

grant {
    //N'autorisez pas toutes les opérations sur tous les fichiers, n'autorisez que ce dont vous avez besoin
    // permission java.io.FilePermission "<<ALL FILES>>", "write, read, execute, delete";
    permission java.io.FilePermission "-", "write, read, execute, delete";
    permission java.io.FilePermission "C:/Program Files/Java/-", "write, read, execute";
    permission java.io.FilePermission "C:/Windows/Sun/Java/-", "write, read, execute";
・ ・ ・

(* Les paramètres varient en fonction de l'environnement)

Une fois les modifications terminées, lancez l'application Web avec l'option d'activer Security Manager. Tapez ensuite @ Runtime @ getRuntime (). Exec ('rm -fr / etc') et cliquez sur le bouton Calculer.

smrmetc.png

L'injection de commande du système d'exploitation a échoué en raison de SecurityManager.

$ ll /
102 au total
dr-xr-xr-x.2 racine racine 4096 23 avril 03:46 2017 bin
dr-xr-xr-x.5 racine racine 5120 26 avril 21:53 2017 boot
drwxr-xr-x.20 racine racine 3820 1 juin 22:57 2017 dev
drwxr-xr-x.119 racine racine 12288 1 juin 22:57 2017 etc
drwxr-xr-x.4 racine racine 4096 2 avril 00:41 2016 home
dr-xr-xr-x.11 racine racine 4096 19 avril 21:20 2017 lib
dr-xr-xr-x.10 racine racine 12288 23 avril 03:46 2017 lib64
drwx------.2 racine racine 16384 8 août 01:21 2015 lost+found
drwxr-xr-x.2 racine racine 4096 18 mars 20:24 2017 media
drwxr-xr-x.4 racine racine 4096 15 novembre 18:00 2015 mnt
drwxr-xr-x.8 racine racine 4096 1er avril 21:49 2017 opt
dr-xr-xr-x.296 racine racine 0 1 juin 22:56 2017 proc
dr-xr-x---.78 racine racine 4096 9 juin 23:09 2017 root
dr-xr-xr-x.2 racine racine 12288 20 avril 03:27 2017 sbin
drwxr-xr-x.7 racine racine 0 1 juin 22:56 2017 selinux
drwxr-xr-x.2 racine racine 4096 23 septembre 20:50 2011 srv
drwxr-xr-x 13 racine racine 0 1 juin 22:56 2017 sys
drwxrwxrwx.8 racine racine 4096 9 juin 23:11 2017 tmp
drwxr-xr-x.14 racine racine 4096 23 septembre 08:32 2016 usr
drwxr-xr-x.23 racine racine 4096 5 octobre 17:12 2016 var

Vous pouvez également rejeter System.exit (n) en commentant la ligne suivant catalina.policy.

permission java.lang.RuntimePermission "exitVM";

Après avoir commenté et redémarré EasyBuggy, tapez «@ System @ exit (0)» et cliquez sur le bouton Calculer.

exitvm.png

De cette manière, vous pouvez également empêcher l'arrêt de la JVM. SecurityManager n'est pas intuitivement facile à comprendre, vous devez donc bien le comprendre et l'utiliser, mais il peut être considéré comme une contre-mesure efficace pour l'injection de commandes du système d'exploitation et l'injection de code.

référence