Server Side Request Forgery - attack that forces a server to perform arbitrary requests (from Nginx in our case).
It's possible when an attacker controls the address of a proxied server (second argument of the proxy_pass
directive).
There are two types of errors that make a server vulnerable:
Classical misconfiguration, based on lack of the internal
directive, that makes SSRF possible:
location ~ /proxy/(.*)/(.*)/(.*)$ {
proxy_pass $1://$2/$3;
}
An attacker has complete control over the proxied address, that makes sending requests on behalf of Nginx possible.
Let's say you have internal location in your config and that location uses some request data as proxied server's address.
E.g.:
location ~* ^/internal-proxy/(?<proxy_proto>https?)/(?<proxy_host>.*?)/(?<proxy_path>.*)$ {
internal;
proxy_pass $proxy_proto://$proxy_host/$proxy_path ;
proxy_set_header Host $proxy_host;
}
According to Nginx docs, internal requests are the following:
- requests redirected by the error_page, index, random_index, and try_files directives;
- requests redirected by the “X-Accel-Redirect” response header field from an upstream server;
- subrequests formed by the “include virtual” command of the ngx_http_ssi_module module and by the ngx_http_addition_module module directives;
- requests changed by the rewrite directive
Accordingly, any unsafe rewrite allows an attacker to make an internal request and control a proxied server's address.
Misconfiguration example:
rewrite ^/(.*)/some$ /$1/ last;
location ~* ^/internal-proxy/(?<proxy_proto>https?)/(?<proxy_host>.*?)/(?<proxy_path>.*)$ {
internal;
proxy_pass $proxy_proto://$proxy_host/$proxy_path ;
proxy_set_header Host $proxy_host;
}
There are several rules you better follow when writing such configurations:
map
or do it some other way;