Concernant une vulnérabilité dans…

Concernant une vulnérabilité dans…

Il y a un an, le 21 mars 2019, le programme de bug bounty de Mail.Ru sur HackerOne a présenté un très bon rapport de bogue à partir de maxarr. Lors de l'implémentation d'un octet nul (ASCII 0) dans le paramètre POST d'une des requêtes API de la messagerie web, qui retournait une redirection HTTP, des morceaux de mémoire non initialisée apparaissaient dans les données de redirection, où l'on trouvait fréquemment des fragments des paramètres GET et des en-têtes d'autres requêtes vers le même serveur.

C'est une vulnérabilité critique, car les requêtes contiennent également des cookies de session. Quelques heures plus tard, un correctif temporaire a été appliqué, filtrant l'octet nul (comme il s'est avéré, cela n'était pas suffisant, car il restait la possibilité d'injection CRLF / ASCII 13, 10, ce qui permet de manipuler les en-têtes et les données de la réponse HTTP, c'est moins critique, mais reste désagréable). En même temps, le problème a été transmis aux analystes de sécurité et aux développeurs pour identifier et corriger les causes du bug.

La messagerie Mail.ru est une application très complexe, de nombreux composants front-end/back-end peuvent participer à la formation de la réponse, qu'ils soient open source (un grand merci à tous les développeurs de logiciels libres) ou développés en interne. Nous avons pu exclure tous les composants sauf nginx et openresty et localiser le problème jusqu'à l'appel de ngx.req.set_uri() dans un script OpenResty, qui ne se comportait pas comme prévu (il n'étais pas possible d'insérer un octet nul ou un saut de ligne via des paramètres GET avec le rewrite dans ngx_http_rewrite_module, qui, selon la documentation, est utilisé et devrait, semble-t-il, fonctionner exactement de la même manière). Les conséquences possibles ont été éliminées, un filtrage le plus strict possible a été ajouté et il a été vérifié que le filtrage supprimait tous les vecteurs possibles. Mais le mécanisme qui a conduit à la fuite de contenu mémoire demeurait un mystère. Un mois plus tard, le rapport de bug a été clôturé comme résolu, tandis que l'analyse des causes de l'apparition du bug a été remise à des temps meilleurs.

OpenResty est un plugin très populaire qui permet d'écrire des scripts Lua à l'intérieur de nginx, et il est utilisé dans plusieurs projets Mail.ru, c'est pourquoi le problème n'était pas considéré comme résolu. Et après un certain temps, il a été nécessaire de revenir sur cette question afin de comprendre les vraies raisons, les conséquences possibles et de formuler des recommandations aux développeurs. Dans l'exploration du code source, ont participé Denis Denisov et Nikolai Ermishkin. Il s'est avéré que :

  • Dans nginx, en utilisant le rewrite avec des données utilisateur, il existe une possibilité de traversée de répertoire (et probablement SSRF) dans certaines configurations, mais c'est un fait connu, et cela doit être détecté par des analyseurs statiques de configurations dans Nginx Amplify et Gixy de Yandex (oui, nous l'utilisons aussi, merci). Lors de l'utilisation d'OpenResty, cette possibilité peut être facilement négligée, mais cela ne concernait pas notre configuration.

    exemple de configuration :

    location ~ /rewrite {
        rewrite ^.*$ $arg_x;
    }
    
    location / {
        root html;
        index index.html index.htm;
    }

    résultat

    curl localhost:8337/rewrite?x=/..../..../..../..../..../..../etc/passwd
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    ...

  • Il y a une erreur dans nginx qui entraîne une fuite de contenu de mémoire si la chaîne de rewrite contient un octet nul. Lors de la remise d'une redirection, nginx alloue un nouveau tampon mémoire correspondant à la longueur totale de la chaîne, mais la copie se fait via une fonction de chaîne où l'octet nul est le terminateur de chaîne, donc la chaîne est copiée uniquement jusqu'à l'octet nul, le reste du tampon contient des données non initialisées. Un examen détaillé peut être trouvé ici.

    exemple de configuration (^@ octet nul)

    
    location ~ /memleak {
        rewrite ^.*$ "^@asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdasdf";
    }
    
    location / {
        root html;
        index index.html index.htm;
    }

    résultat
    curl localhost:8337/secret -vv
    ...
    curl localhost:8337/memleak -vv
    ...
    Location: http://localhost:8337/secret
    ...

  • Nginx protège les paramètres GET contre l'injection de caractères spéciaux et permet d'utiliser dans le rewrite uniquement les paramètres GET. Par conséquent, il n'est pas possible d'exploiter l'injection via des paramètres contrôlés par l'utilisateur dans nginx. Les paramètres POST ne sont pas protégés. OpenResty permet de travailler à la fois avec les paramètres GET et POST, donc en utilisant des paramètres POST via OpenResty, il existe une possibilité d'injection de caractères spéciaux.

    exemple de configuration :

    location ~ /memleak {
        rewrite_by_lua_block {
            ngx.req.read_body();
            local args, err = ngx.req.get_post_args();
            ngx.req.set_uri( args["url"], true );
        }
    }
    
    location / {
        root html;
        index index.html index.htm;
    }
    

    résultat :

    curl localhost:8337 -d "url=secret" -vv
    ...
    curl localhost:8337 -d "url=asdfasdfasdfasdfasdfasdfasdfasdf" -vv
    ...
    Location: http://localhost:8337/{...peut contenir secret...}
    ...

Réaction ultérieure

Le problème a été signalé aux développeurs de nginx et OpenResty, les développeurs ne considèrent pas le problème comme une erreur de sécurité dans nginx, car il n'y a pas de possibilité d'exploitation de l'erreur via l'injection de caractères spéciaux, la correction de la fuite de contenu de mémoire a été publiée le 16 décembre. Quatre mois après le rapport, il n'y a eu aucun changement dans OpenResty non plus, même s'il était compris qu'une version sûre de la fonction ngx.req.set_uri() était nécessaire. Le 18 mars 2020, nous avons publié des informations, le 21 mars OpenResty a sorti la version 1.15.8.3, qui ajoute une vérification de l'URI.

Portswigger a déclaré un bon article et a pris des commentaires d'OpenResty et de Nginx (en fait, le commentaire selon lequel seule une petite partie de la mémoire est révélée est incorrect et peut prêter à confusion, cela dépend de la longueur de la chaîne suivante après le byte nul et, en l'absence de restrictions explicites sur la longueur, cela peut être contrôlé par l'attaquant).

Quelle était l'erreur et que faire pour l'éviter ?

L'erreur était-elle dans nginx ? Oui, c'était le cas, car une fuite de contenu de mémoire est de toute façon une erreur.

Y avait-il une erreur dans OpenResty ? Oui, au minimum, la question de la sécurité de la fonctionnalité proposée par OpenResty n'a pas été explorée ni documentée.

Y avait-il une erreur de configuration / d'utilisation d'OpenResty ? Oui, car en l'absence d'une indication explicite, une hypothèse non vérifiée sur la sécurité de la fonctionnalité utilisée a été faite.

Laquelle de ces erreurs constitue une vulnérabilité de sécurité avec une récompense de $10000 ? Pour nous, cela n'a pas vraiment d'importance. Dans tout logiciel, surtout à l'intersection de plusieurs composants, surtout fournis par différents projets et développeurs, personne ne peut garantir que toutes les caractéristiques de leur fonctionnement sont connues et documentées et qu'il n'y a pas d'erreurs. Par conséquent, toute vulnérabilité de sécurité se produit justement là où elle impacte la sécurité.

Dans tous les cas, il est de bonne pratique de normaliser ou de limiter au maximum / filtrer les données entrantes qui vont dans n'importe quel module / API externe, s'il n'y a pas d'indications explicites et d'une compréhension claire que cela n'est pas nécessaire.

Errata

D'après l'expérience de l'article précédent, pour préserver la pureté de la langue :

bug bounty — concours de chasse aux erreurs
rapport de bogue — notification d'erreur
redirection — redirection
open source — à code ouvert
errata — travail sur les erreurs

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster