STRUTS2的的getClassLoader漏洞利用漏洞利用
0x00 摘要
我在《攻击JAVA WEB》,文中提多关于“classLoader导致特定环境下的DOS漏洞”,当时并没有更加深入的说明,这几天
struts官方修补了这个漏洞,本文是对这个漏洞的深入研究。
0x01 正文
这一切,得从我们控制了classLoader说起,曾经写过一篇文章,提到了一个小小的技术细节,非常不起眼的一个鸡肋。 引用
《Spring framework(cve-2010-1622)漏洞利用指南》:
Struts2其实也本该是个导致远程代码执行漏洞才对,只是因为它的字段映射问题,只映射基础类型,默认不负责映射其他类
型,所以当攻击者直接提交URLs[0]=xxx时,直接爆字段类型转换错误,结果才侥幸逃过一劫罢了。
tomcat8.0出来后,这个问题爆发了,这是一个鸡肋漏洞的逆袭。
在struts2任何一个action运行之前,一旦接受到用户提交参数xx=zzzzz时,就由Ognl负责调用对应的当前action的setXxx方
法,至于set方法到底是干什么的,其实不重要,里面的逻辑也不重要,我们只关注这个方法调用了,参数传递了。这种对属
性的改变,有时候是可以很大程度的影响后续复杂逻辑。
普及一点基础
Object是java的基础类,所有的class生成的对象,都会继承Object的所有属性和方法,因此当前action无论是什么代码,必须
有Object自带的getClass方法,这个方法会返回一个Class对象,Class对象又一定会有getClassLoader方法,最终在每个
action都可以
getClass().getClassLoader()
我研究这个问题,在几年前了,这个东西理解起来不容易,尤其是各个web容器不一致,刚巧当时有个阿里巴巴内部《tomcat
等容器的classLoader加载原理》培训,收获匪浅。本文篇幅有限,简单的讲一下。
在JRE启动中,每个Class都会有自己的ClassLoader。web容器,为了方便的管理启动过程,通常都有实现自定义的
ClassLoader。《Spring framework》的漏洞的利用场景真的非常幸运,利用了web容器的特性getURLs方法,所有容器的
servlet的ClassLoader都会通过继承父类UrlClassLoader得到getURLs这个方法,所以这个漏洞可以不受容器影响。事实上,
每个容器的ClassLoader都是自己实现的,环境必然会有所不同,那次struts2侥幸逃过一劫,所以我的一个关注点,一都放在
几大web容器的ClassLoader代码变化上,哪天看到tomcat8居然把resources放进ClassLoader上,而ServletContext刚巧挂在
resources上,顿时知道肉戏来了。
上传webshell的可能性研究
多次的远程代码执行漏洞洗礼,我一直在脑海里模拟“ServletContext被控制了,这次能干什么”,究竟有哪些路线,可以通往
代码执行的领域。
比如:Struts2会去servletContext里取到一个值,然后把它作为Ognl执行掉。这个太简单了,我自己都不信。
Ognl的Context树形结构:
servletContext被转换成Map,变成了图中的application子项,这个位址很尴尬,如果是上一层Node,从上到下找到value
Stack,确实有实现这个思路的可能,但现在看来,这条路断了,它不支持找到父节点。经过多次找寻后,确认Ognl出局,只
能从web容器本身入手。
运行在Tomcat8下的struts,在随便哪个action代码中,插入这段,下断点,
this.getClass().getClassLoader();