历史漏洞复现
CVE-2017-12615 (PUT 方法任意文件上传)
在tomcat的conf/web.xml里面有一个参数readonly 根据注释可以知道这个参数就是开启是否接受delete和put请求
false就等于允许

我们在DefaultServlet中添加这个参数

复现
本地启动tomcat 使用jpda这个javaagent 使得idea可以远程调试tomcat
1 | catalina.bat jpda start |

在idea中打断点

bp发包

可以看到idea停在断点上了

一开始就判断readonly的值 因为为false所以跳过

后续就是获取路径path 然后判断是否存在文件

获取请求输入流 在通过请求输入流获取到请求体
后面会进入到resources.bind(path, newResource)
这里就是sink点

跟进dirContext.bind()

继续跟进

来到FileDirContext的bind方法中
创建一个File对象 然后判断是否存在
继续跟进下面的rebind()

前面是一些判断语句
也是创建一个file对象 判断obj对象类型
因为obj对象是resource类 所以is获取obj的请求体数据
重点在后面

创建一个FileOutputStream os 然后将file对象传入FileOutputStream 中
用上面的输入流is读取数据
最后os在写入file对象中 此时文件就成功写入了

可以成功访问

在发送数据包的时候发的是
PUT /1.jsp%20
如果不加%20 他会使用jsp的Servlet 所以需要加入空格的url编码 使得是DefaultServlet去处理这个请求
修复建议
不要使用readonly参数 默认也没有使用
manager弱口令导致任意war包上传rce
在conf/tomcat-user.xml中 写入这些用户配置 即可打开/manager

如果在配置的时候 配置了弱密码就可能有rce风险
复现

输入账号密码

有一个可以上传war包的地方

上传war包

显示ok就可以了
访问http://127.0.0.1:8080/3/3.jsp
我们war包名为3 他就会在webapp里面创建一个3的目录夹 并且有3.jsp

CVE 2020-1938 (webapp/ROOT下的任意文件读取)
ajp协议是用于Web服务器与Servlet容器间的高效通信 ajp用来请求一些资源 并且传输二进制数据 效率比http协议高
一般情况下客户端没法直接使用ajp协议去访问tomcat 一般都是走http
ajp协议并没有做一些权限控制 导致只需要构造一些恶意的请求 tomcat就会返回数据
ajp协议在tomcat中默认启动在8009端口上

主要的触发方式是通过构造指定的数据包 触发指定资源的请求 依此读取文件
复现
使用exp脚本来触发漏洞
1 | #!/usr/bin/env python |
继续远程调试tomcat
在AbstractAjpProcessor的prepareRequest()打断点


在这个request.setAttribute里面共设置了3个参数值
javax.servlet.include.request_uri /
javax.servlet.include.path_info WEB-INF/web.xml
javax.servlet.include.servlet_path /
这里设置3个参数值 使得后续tomcat会去请求响应相应资源并返回
此时request的参数已经设置好了

来到service这里 调用adapter的service
之后又会进入DefaultServlet的doGet处


跟进getRelativePath

根据之前的参数值 最终返回了请求路径/WEB-INF/web.xml
之后就是返回路径中的内容了

脚本里面请求路径改成/asdf.jsp即可实现文件包含 此时对应的Servlet就会是jspServlet去处理请求的资源 会解析文件内容为jsp

http的Process遇到/WEB-INF会自动检测到 如何不返回内容
说些什么吧!