服务器端请求伪造(SSRF)¶
Gixy Check ID: ssrf
服务器端请求伪造是一类攻击,诱使服务器(在本项目中为 Nginx)代表攻击者发起任意请求。
当攻击者可以控制被代理服务器的地址(proxy_pass 指令的第二个参数)时,即有可能发生。
如何发现?¶
使服务器暴露于 SSRF 的常见两类错误:
- 缺少 internal 指令。该指令用于标记某个 location 仅允许内部请求访问;
- 不安全的内部重定向。
缺少 internal 指令¶
以下为典型的错误配置,因缺少 internal 指令而导致 SSRF:
location ~ /proxy/(.*)/(.*)/(.*)$ {
proxy_pass $1://$2/$3;
}
不安全的内部重定向¶
假设你的配置中有一个仅用于内部访问的 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;
}
- 由 error_page、index、random_index 和 try_files 指令触发的重定向;
- 上游服务器通过 “X-Accel-Redirect” 响应头触发的重定向;
- 由
ngx_http_ssi_module模块的 “include virtual” 命令以及ngx_http_addition_module模块的指令形成的子请求;- 由 rewrite 指令改变的请求。
因此,任何不安全的 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;
}
如何规避?¶
编写此类配置时建议遵循以下规则:
- 仅通过“内部位置(internal location)”进行代理;
- 尽可能避免传递用户可控的数据;
- 保护被代理服务器地址:
* 若可代理的主机集合有限(例如仅 S3 等),应将其硬编码并通过 map 等方式选择;
* 若无法枚举所有可能主机,应对地址进行签名校验。
加固 NGINX,使用维护的 RPM
使用 GetPageSpeed 提供的 NGINX Extras 在 RHEL/CentOS/Alma/Rocky 上获取持续更新的 NGINX 与模块。 了解更多.