通用Tomcat InvokerServlet RCE攻击链挖掘
strangej 发表于 北京 历史精选 2689浏览 · 2024-05-30 18:16

一、 背景

最近在对公司使用的某外购OA系统(非知名)进行代码审计时,发现该OA系统使用了比较早期的servlet技术,就是tomcat的InvokerServlet做路由,在成功绕过waf完成RCE之后发现tomcat在该配置下可以挖掘出通用利用链作为黑盒payload,以及配合一些该配置特征可以利用在黑盒渗透当中,上网搜索后发现该部分资料稀少,遂做此总结,本文只作抛砖引玉,供各位参考,如有错误望不吝指正

二、InvokerServlet

2.1 什么是InvokerServlet

InvokerServlet出自org.apache.catalina.servlets.InvokerServlet,简单来讲就是可以在web.xml中声明以此为路由,之后无需再次在web.xml中声明其他servlet,就可以通过包名加类名的方式去访问其他servlet。
举例来讲在InvokerServlet的配置下,可以通过访问url:
/servlet/com.xxx.XxxServlet
直接调用到对应Servlet。

2.2 限制

  • 官方文档描述:

    简单来讲就是调用的类得实现Servlet类,有可以调用的正常处理http请求的方法。
  • 版本需求:

    借用如上描述,就是tomcat6及以前支持,7.0及以后因为不安全不支持了。

2.3 环境搭建

我这里用的是Servlet应用 + tomcat6.0.13
pom.xml(bsh和axis是之后利用链用的):

Servlet类:

web.xml(剩下那个servlet是axis用的):

成功访问(我这里偷懒给HelloServlet放在顶层了,没有包):

2.4 源码分析

截取主要片段:


省流版:
通过获取到请求的path字符串去匹配第一个/后面的字符串变量,并根据该变量找到对应Servlet去处理请求(上面截的不是很全感兴趣的小伙伴可以去catalina.jar里看一下)。
如刚才我们请求的/InvokerServlet/servlet/HelloServlet取到的就是/HelloServlet然后就直接去找HelloServlet对应的类了。

2.5 攻击思路

到这里思路已经很明显了,找到可以利用的Servlet,然后直接调用对应Servlet完成攻击。有一些项目引入的依赖会自带脆弱的Servlet,而往往开发人员会选择不把它们映射出去来避免安全问题,而当使用InvokerServlet时我们就可以挖出来这些访问不到的Servlet加以利用。当时第一反应是找到tomcat后台登录的Servlet爆破密码,然后文件上传对应的Servlet完成war包部署rce。
先看一下对应的org.apache.catalina.ManagerServlet

然后再回头看一下上面InvokerServlet的源码,很可惜判断了org.apache.catalina开头的直接返回404。这条路不通了。于是挖掘了如下两条实用的REC利用链(beanshellaxis2),肯定还有其他各种利用链,这里抛砖引玉大家可以自行发挥。

三、BeanShell

这条利用链逻辑简单,之前那个OA也是通过这个直接RCE。

3.1 什么是Beanshell

作为拿shell的常客相信各位师傅已经对BeanShell很熟悉了,这里就简单介绍一下。BeanShell是一种完全符合java语法并且又拥有自己的一些语法和方法的基于java的脚本语言,大概可以理解为类似js。并且提供默认页面可以测试语句执行。
主要利用函数:exec
可以通过exec("xxx")直接执行系统命令。

3.2 找到Servlet

翻源码直接找到测试页面对应的Servlet类,bsh.servlet.BshServlet

可见通过bsh.script变量直接执行代码,包名结合InvokerServlet直接RCE:

3.3 BeanShell绕waf

测试的时候payload被某云waf无情拦截,于是结合语言特性完成绕过。这里不直接放payload了,但是简述一下思路就是,可以直接写java做一些String的处理完成系统命令洗白,然后exec可以通过编码注释之类的洗白。

四、Axis2

InvokerServlet一般出现在比较老的系统上,根据经验而比较老的系统很多会使用WebService通讯,于是挖掘了这条利用链,被测OA上也能打。payload不复杂但逻辑复杂一些。

4.1 什么是Axis2

Axis2是目前比较流行的WebService引擎。WebService被应用在很多不同的场景。例如,可以使用WebService来发布服务端 Java类的方法,以便使用不同的客户端进行调用。这样可以有效地集成多种不同的技术来完成应用系统。
这些也不太重要,主要的是Axis2和tomcat一样都有控制台,都能登录部署应用然后rce,不同就是tomcat部署war包。Axis部署aar包。还有一点非常有利的是,一般都不会去改默认账密,大部分为了避免安全问题,就直接选择不映射控制台出去或者控制台只可以本地访问,而这些方法对我们都不会产生影响。

4.2 Axis2复现RCE

先搭建一个普通的axis2环境,走一遍rce流程,抓取关键报文,为InvokerServlet下rce做准备。

4.2.1 恶意aar准备

编写java类如下:

编写services.xml如下:

java类编译一下然后如下目录层级:
/包名结构/恶意类.class
/META-INF/services.xml和打包生成的清单文件
然后俩文件夹一起压缩成zip再改名aar就行了。

4.2.2 环境搭建

官网下载axis1.6.3.war,直接扔在tomcat6下启动。
通过默认账密admin/axis2登录并访问/axis2/axis2-admin页面,通过左侧Upload Service上传恶意aar包:

然后访问对应恶意类service地址,成功弹出计算器:

其中主要的两个请求:

  • /axis2/axis2-admin/login负责登录,登录后SESSION就有效了,可以直接进后台:
  • /axis2/axis2-admin/upload负责上传,上传aar并部署:

    ## 4.3 找到Servlet并分析源代码
    找到org.apache.axis2.webapp.AxisAdminServlet:

    可以看到请求都交给了一个agent去处理,最终跟到了org.apache.axis2.transport.http.AbstractAgent类,接下来根据逻辑是什么决定我们传入什么:

    省流版:
    取url中的请求路径前面加上process就是对应的方法名(类似图中的processIndex),如/axis2/axis2-admin/login,对应的就是调用processLogin方法处理登录请求。
    看到这,简单总结一下,InvokerServlet是根据url值去找对应Servlet类,AxisAdminServlet又是通过url去决定调用哪个方法,那么这不是全乱套了。首先控制台不对外暴露/axis2/axis2-admin找不到。访问/servlet/org.apache.axis2.webapp.AxisAdminServlet最终找不到名叫processOrg.apache.axis2.webapp.AxisAdminServlet的方法。请求/servlet/login又找不到叫login的Servlet。
    ## 4.4 柳暗花明
    仔细看一下上图对应的处理逻辑,lastIndexOf(47),取的就是最后一个/后面的值,前面的无影响。
    而再回顾一下InvokerServlet的处理逻辑,取第一个/后面的值作为Servlet类的寻找依据。这样的话可以互不影响。
    用之前写的HelloServlet求证一下,访问/InvokerServlet/servlet/HelloServlet/upload成功获取HelloServlet的response:

    这也就代表着我们在/xxx.xxx.xxxServlet后面随便添加/abc既不影响Servlet路由,又不影响AxisAdminServlet的方法调用
    ## 4.5 完成RCE
  • 通过/InvokerServlet/servlet/org.apache.axis2.webapp.AxisAdminServlet/login接口获取可上传aar的合法session:
  • 通过/InvokerServlet/servlet/org.apache.axis2.webapp.AxisAdminServlet/upload接口上传aar:

  • 访问/InvokerServlet/services/Calc完成RCE:

五、总结与思考

5.1 综上总结

对于使用了tomcat6及以前的InvokerServlet应用,如果项目引进了bsh,可以直接RCE。对于引入axis2控制台且没有更改默认账号密码(改了就爆破),但是因为安全考虑没有把控制台映射出去导致无法访问控制台的情况可以通过InvokerServlet绕过限制直接操作Servlet上传aar完成RCE。这里只是抛砖引玉给出两条利用链,相信肯定还有其他利用方式,大家具体情况具体分析。

5.2 发散思考

至此可以形成黑盒测试经验,遇到路径中含有/xxx.xxx.xxxServlet的应用,可以怀疑使用了InvokerServlet,可以直接掏出上述两个利用链打(不要直接奔着RCE去,先不带参数请求Servlet看看在不在)。更上一层,InvokerServlet可以认为是早期tomcat给的一种语法糖,可能有一些系统会自己实现自己的"InvokerServlet"类,见到相似特征,可以考虑用相似思路进行渗透(如用友NC的/servlet/~ic/bsh.servlet.BshServlet导致RCE,看着是不是一模一样)。
最后,感谢阅览此文,望不吝指正

0 条评论
某人
表情
可输入 255