跳转至

HTTP 拆分

Gixy Check ID: http_splitting

HTTP 拆分是由于输入校验不当而导致的一类攻击。它通常针对位于 Nginx 之后的 Web 应用(HTTP Request Splitting),或针对其用户(HTTP Response Splitting)。

当攻击者能够将换行符 \n\r 注入到请求,或由 Nginx 生成的响应中时,就会产生此漏洞。

如何发现?

应始终关注: - 用于构造请求的指令中所用到的变量(这些变量可能包含 CRLF),例如 rewritereturnadd_headerproxy_set_headerproxy_pass; - $uri$document_uri 变量,以及它们被用于哪些指令,因为它们包含“已解码”的 URL 值; - 由排除型范围(exclusive range)提取出的变量,例如 (?P<myvar>[^.]+)

包含由排除型范围提取变量的错误配置示例:

server {
    listen 80 default;

    location ~ /v1/((?<action>[^.]*)\.json)?$ {
        add_header X-Action $action;
        return 200 "OK";
    }
}

漏洞利用示例:

GET /v1/see%20below%0d%0ax-crlf-header:injected.json HTTP/1.0
Host: localhost

HTTP/1.1 200 OK
Server: nginx/1.11.10
Date: Mon, 13 Mar 2017 21:21:29 GMT
Content-Type: application/octet-stream
Content-Length: 2
Connection: close
X-Action: see below
x-crlf-header:injected

OK

如上所示,攻击者成功向响应中添加了 x-crlf-header: injected。这是因为: - add_header 并不会对传入的值进行编码或校验,默认假定编写者知晓后果; - 路径在进入位置匹配前已被规范化; - $action 的值来自一个包含排除范围的正则:[^.]*; - 因而 $action 实际值可等于 see below\r\nx-crlf-header:injected,在被用于生成响应头时,产生了注入。

如何规避?

  • 尽量使用更安全的变量,例如使用 $request_uri 替代 $uri
  • 在排除范围中禁止换行符,例如使用 /some/(?<action>[^/\s]+) 替代 /some/(?<action>[^/]+
  • 也可以考虑对 $uri 进行校验(仅在你明确了解其影响时)。

加固 NGINX,使用维护的 RPM

使用 GetPageSpeed 提供的 NGINX Extras 在 RHEL/CentOS/Alma/Rocky 上获取持续更新的 NGINX 与模块。 了解更多.