|
Nginx 的洞修漏洞修复,很多时候不是洞修“升级一下就好”那么简单。我见过一台跑了三年没重启的洞修边缘节点,版本停在 1.18.0,洞修运维觉得“没出过事就是洞修没事”。直到扫描器报出 CVE-2021-23017,洞修DNS 解析器里的洞修一个 off-by-one 堆溢出,攻击者能直接打穿 resolver 模块。洞修这种漏洞不会因为你的洞修服务器“看起来稳”就绕道走。 先搞清楚你面对的洞修是哪类问题。Nginx 的洞修漏洞大致分三种:一是像上面那种内存破坏型,多出现在 resolver、洞修HTTP/2、洞修MP4 模块;二是洞修配置逻辑缺陷,比如 alias 路径穿越(CVE-2021-23017 之外的洞修经典案例),跟二进制版本无关,改 conf 才能堵;三是第三方模块拖进来的,比如 lua-nginx-module 历史上出过多次栈溢出。很多人一上来就 apt upgrade nginx,结果发现漏洞在模块里,主程序升了也白升。 判断版本是否受影响,别只看 nginx -v。打开官方 security advisories 页面,对照你编译时启用的模块列表。用 nginx -V 看完整编译参数,重点盯 --with-http_v2_module、--with-http_mp4_module、--with-stream 这些。举个例子,CVE-2019-9511 影响 HTTP/2 的 DATA 帧处理,如果你编译时压根没加 v2 模块,这个漏洞跟你无关。反过来,有些发行版默认打包了 mp4 模块,你根本没用,但漏洞面已经敞开了。 修复动作要分场景。能重启服务的,直接换二进制。从 nginx.org 下对应分支的最新包,或者用发行版 backport 的安全版本。注意:Debian/Ubuntu 的 nginx-full 和 nginx-light 模块集不同,别装错。不能重启的,比如承载长连接的网关,考虑用 nginx -s reload 配合热升级——先起新 master,再逐步切 worker。但热升级对 resolver 这类模块级漏洞无效,因为旧 worker 还在跑旧代码。这时候只能上临时缓解:WAF 规则拦特定 payload,或者 iptables 限制源 IP。 配置层面的修复经常被忽略。alias 目录穿越那个老问题,官方建议改用 root 加 try_files,但很多人直接写 location /static { alias /data/static/; },如果 location 没加斜杠结尾,/static../etc/passwd 就能读到系统文件。这种修复不需要动二进制,改一行配置重载即可。我习惯在改完后用 curl --path-as-is 手动测一遍,扫描器不一定覆盖所有变体。 第三方模块的修复更麻烦。比如 lua-nginx-module 的 CVE-2022-28805,需要同时升级 nginx 和模块,还要重新编译。如果用的是 OpenResty,直接换它的新版本更省事。编译前确认 ./configure 参数和旧版一致,否则可能引入新问题。我见过有人升级后忘了加 --with-http_ssl_module,结果 HTTPS 全挂,回滚花了两小时。 最后说个实际教训。某次修复 CVE-2021-23017,运维只升级了主程序,没检查 resolver 配置里的 resolver 8.8.8.8; 是否还在用有漏洞的解析路径。升级后漏洞仍在,因为旧配置触发了新版本里另一个边界条件。修复完必须做验证:用 nginx -t 确认语法,用 strace 或 gdb 跟一下 resolver 调用,或者直接跑 PoC 脚本。别信“升级即安全”这种话,Nginx 的漏洞修复,验证环节省不得。 |