[ssrf] Server Side Request Forgery¤
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).
How can I find it?¤
There are two types of errors that make a server vulnerable: - lack of the internal directive. It is used to point out a location that can be used for internal requests only; - unsafe internal redirection.
Lack of the internal directive¤
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.
Unsafe internal redirection¤
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;
}
What can I do?¤
There are several rules you better follow when writing such configurations:
- use only "internal locations" for proxying;
- if possible, forbid user data transmission;
- protect proxied server's address:
* if the quantity of proxied hosts is limited (when you have S3 or smth), you better hardcode them and choose them with map
or do it some other way;
* if you can' list all possible hosts to proxy, you should sign the address.