CVE-2020-1938漏洞技术原理解析
绿盟云针对Apache Tomcat文件包含漏洞的在线检测正式上线
在网络安全领域,CVE-2020-1938这个编号代表着一个相当经典的协议层漏洞——Tomcat AJP文件包含漏洞,圈内人更习惯叫它“幽灵猫”。这个漏洞的巧妙之处,或者说危险之处,在于它绕开了常规的HTTP防线,直接利用了一个被许多人遗忘在角落的后门通道。
被忽视的“内网信使”:AJP协议
要想搞懂这个漏洞,得先明白Tomcat里不只有HTTP服务在忙活。除了默认的8080端口,Tomcat通常还会开启一个8009端口,用来跑AJP(Apache JServ Protocol)协议。这协议设计之初是干嘛的?说白了,它是个“内部通讯专员”。在经典的架构里,Apache HTTPD作为前端代理处理静态文件和负载均衡,动态请求则通过AJP这个高效、二进制的协议转发给后端的Tomcat容器去处理。因为默认认为AJP端口只对内网(比如前端Apache)开放,所以它的安全校验,天生就比暴露在公网的HTTP服务要宽松得多。
信任的裂痕:可控的请求属性
漏洞的核心,就藏在这个基于信任的“宽松”里。AJP协议在传递请求时,会携带一系列“请求属性”(request attributes),这些属性相当于HTTP请求头在AJP世界里的映射,但功能更强大。问题出在,Tomcat在处理某些特定的请求属性时,比如 javax.servlet.include.request_uri 和 javax.servlet.include.path_info,会直接信任客户端(也就是发送AJP请求的那一方)传来的值。
想象一下这个场景:一个本应只转发合法请求的“信使”(AJP客户端),突然递过来一张纸条,上面写着“请把隔壁保密室(Web应用目录)里名为‘config.properties’的文件内容拿给我”。由于Tomcat完全信任这个“信使”的身份,它没有去核实这张纸条的合法性,而是忠实地执行了指令。攻击者要做的,就是伪装成这个被信任的“信使”,向8009端口发送一个精心构造的AJP请求包,在里面设置好这些指向目标文件的请求属性。
从文件读取到代码执行的关键一跃
光能读文件,危害已经不小,配置文件、数据库密码、源代码都可能泄露。但幽灵猫的危险性远不止于此。它的另一个可怕特性在于,在某些特定条件下,这个文件包含是“动态”的。如果被读取的文件本身包含可执行的JSP代码,Tomcat的JSPServlet会去解析并执行它。
这就打开了一扇危险的大门。假设目标服务器恰好有一个文件上传功能,但限制了只能上传图片。攻击者可以先上传一个包含恶意JSP代码的图片文件,然后利用CVE-2020-1938,通过AJP协议去“包含”这个刚上传的图片文件。Tomcat在处理这个“包含”请求时,并不会检查文件后缀,而是根据文件内容去识别。当它发现文件里含有JSP代码片段,就会照样执行,从而让攻击者在服务器上获得一个命令执行的WebShell。从信息泄露到系统沦陷,链条就这样被打通了。
修复的逻辑:收紧信任边界
Apache官方的修复方案清晰而直接:既然漏洞源于对客户端传入的路径属性无条件信任,那么就在关键位置加上校验的锁。在修补后的版本中,Tomcat在处理这些用于包含的请求属性时,不会再简单地采用客户端提供的值,而是会对其进行规范化处理,并严格检查其指向的路径是否在允许的范围内,从根本上杜绝了路径穿越和任意文件包含的可能性。
回过头看,幽灵猫漏洞给架构师和运维人员提了个醒:任何基于内网信任的假设,在边界模糊的云时代都可能成为突破口。那个默认为“内部使用”的8009端口,一旦不小心暴露在公网,沉睡的协议缺陷便会立刻变成攻击者手中锋利的匕首。

参与讨论
8009端口居然默认开?我之前扫内网真见过好几台没关的
AJP协议不是早该淘汰了吗,怎么还有人用啊🤔
刚翻了下老项目,还好我们当年把AJP关了,吓出冷汗
这种信任内网的假设现在真的太危险了,云环境哪有内外网
上传图片变shell也太骚了吧,后缀检查形同虚设啊
求问:如果只监听127.0.0.1的8009还算安全不?
之前搞过Tomcat调优,完全没注意AJP这块,踩坑了
又是那种“理论上安全,实际一暴露就炸”的典型
文件包含还能执行JSP?这逻辑漏洞有点离谱了
修复方案听着简单,但多少老系统根本不敢升级啊
hhhh 所以别乱开非必要端口,血泪教训
幽灵猫这名字真贴切,悄无声息就捅穿防线了
感觉很多运维到现在都不知道AJP是干啥的
那个javax.servlet.include.path_info居然能被控,太致命了
AJP默认对内网就放松警惕,这坑埋得够深
以前公司服务器真中过这招,密码全漏了。