游客发表
2017年9月,程命Apache官方发布了一个Tomcat的令执安全公告,编号CVE-2017-12615。行漏这个漏洞影响Tomcat 7.0.0到7.0.79版本,程命在Windows环境下尤为致命——攻击者可以通过一个精心构造的令执PUT请求,往服务器上写入任意JSP文件,行漏然后访问它,程命直接拿到服务器权限。令执说白了,行漏就是程命把webshell塞进了你的Tomcat目录里。
问题的令执根源出在Tomcat对HTTP方法的处理上。Tomcat的行漏DefaultServlet默认配置里,readonly参数被设为false时,程命允许PUT方法上传文件。令执但真正要命的行漏是过滤逻辑的缺陷。当请求的URL以/结尾时,比如PUT /shell.jsp/,Tomcat在路径规范化过程中会把这个尾部斜杠去掉,最终写入的文件名变成了shell.jsp。而Tomcat对JSP文件的访问控制检查,又恰好被这个尾部斜杠绕过了。一个斜杠,两道防线全废。
我实际在测试环境里复现过这个漏洞。用curl发一个PUT请求:
curl -X PUT "http://target:8080/shell.jsp/" -d "<% Runtime.getRuntime().exec(request.getParameter(\"cmd\")); %>" 返回201 Created。然后浏览器访问http://target:8080/shell.jsp?cmd=whoami,命令就执行了。整个过程不需要任何认证,不需要任何交互,只要目标开了PUT并且跑在Windows上。Linux环境下因为文件系统对文件名中特殊字符的处理不同,利用条件更苛刻,但并非完全不可能。
为什么Windows上特别容易中招?Windows文件系统对尾部斜杠和点的处理比较宽松,shell.jsp/在保存时会被系统自动截断为shell.jsp。Linux下则不会,尾部斜杠会被当作目录分隔符处理,写入直接失败。这个差异让很多运维人员产生了错觉——以为自己的Linux服务器安全,实际上只是攻击成本更高而已。
修复方式其实很直接。升级到Tomcat 7.0.81或更高版本,官方在DefaultServlet的路径处理上加了更严格的校验。如果暂时不能升级,把conf/web.xml里DefaultServlet的readonly参数显式设为true,禁用PUT和DELETE方法。另一个办法是在前端反向代理层拦截非GET/POST请求。我见过不少生产环境图省事,直接让Tomcat裸奔在公网上,连最基本的method过滤都没做。
这个漏洞的CVSS评分是8.1,高危。但它的利用门槛低得离谱——一个curl命令的事。2017年漏洞公开后,互联网上出现了大量扫描器批量探测/shell.jsp/路径的流量。很多人直到服务器被挖矿了才发现中招。Tomcat的日志里会留下PUT请求的记录,但如果没有专门的监控告警,这些日志就是一堆沉默的证据。
说到底,这个漏洞暴露的不只是Tomcat的代码问题,更是运维习惯的问题。默认配置不等于安全配置,PUT方法在Web服务器上本来就不该随便开着。一个尾部斜杠能绕过两层检查,这种事听起来离谱,但在真实代码里就是发生了。每次看到有人把Tomcat直接暴露在公网还开着默认配置,我都觉得这跟把家门钥匙插在锁上没区别。
友情链接