Server Side Request Forgery - уязвимость, позволяющая выполнять различного рода запросы от имени веб-приложения (в нашем случае от имени Nginx).
Возникает, когда атакующий может контролировать адрес проксируемого сервера (второй аргумент директивы proxy_pass
).
Наиболее распространенно два класса ошибок конфигурации, которые приводят к этой проблеме:
Классический пример уязвимости типа SSRF в виду отсутствия директивы internal
выглядит следующим образом:
location ~ /proxy/(.*)/(.*)/(.*)$ {
proxy_pass $1://$2/$3;
}
Злоумышленник, полностью контролируя адрес проксируемого сервера, может выполнять произвольные запросы от имени Nginx.
Подразумевается, что в вашей конфигурации есть internal location, которые использует какие-либо данные из запроса в качестве адреса проксируемого сервера.
Например:
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;
}
Согласно документации Nginx внутренними запросами являются:
- запросы, перенаправленные директивами error_page, index, random_index и try_files;
- запросы, перенаправленные с помощью поля “X-Accel-Redirect” заголовка ответа вышестоящего сервера;
- подзапросы, формируемые командой “include virtual” модуля ngx_http_ssi_module и директивами модуля ngx_http_addition_module;
- запросы, изменённые директивой rewrite.]>
Соответственно, любой "неосторожный" реврайт позволит злоумышленнику сделать внутренний запрос и контролировать адрес проксируемого сервера.
Пример плохой конфигурации:
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;
}
Есть несколько правил, которых стоит придерживаться в подобного рода конфигурациях:
map
или иным удобным для вас образом;