郑国祥:大家好,来自安恒信息技术有限公司。在这里我会介绍通过某种方式如何挖掘这种严重性的漏洞。首先是关于我自己的介绍,我在安恒做Web安全研究,包括一些Web的突破,还有一些代码审计的问题。兴趣爱好的话就是搞一些软件破解一下Burp Suite Pro、Mac Office等等。在2015年拿过腾讯的TSRC漏洞之王,2016年拿了御洞圣杰,包括我之前挖掘的一些S2-029、S2-032、S2-045、S2-046,这是我的一些相关信息。
我们之前的步骤仅仅只是找到了那些可以利用的一些输入点。比如说Struts2里面默认有一个Security Member Access,就算你拿到了一个执行的权限,比如执行一些系统命令,这些是有Security Member Access的保护,我们要突破这些防护。这里是做了一个黑名单,包括哪些Class是无法加载的,OGNL里面的一些内容,下面OGNL的一些Access,包括在S2-032的时候,因为利用了Bypass的技术,就加入了白名单里面了。还有黑名单的一些包名,包括一些Java的一些,还有几个类可以Bypass之前的一个黑名单的防护,这些都加进去了。但是我们看了这些黑名单之后,就必须要想办法去突破这些黑名单的防护。
首先我们可以来关注一下OGNL表达式里面用的最多的就是一个OGNL Context。这个里面有好几个Map里面,OGNL Context里面就是一个Map,有好几个属性,像一些字符串等等。这些字符串我们拿来根本就没法用,没法修改,比如像Context里面的一些属性,我们可以看到有一个属性可以控制。但是这个Context是属于第9个属性,这个属性在OGNL表达式里面,Context维护了所有的Struts2的一个框架的类。我们可以看一下,这边就是一些黑名单的类,Context没有在黑名单的那些包里面或者类里面。我们可以看一下什么是Context,翻译成中文的意思就是一个容器,通常来讲,它支持了Struts2的一些运行环境,包括哪个类需要哪些属性,或者哪个类需要哪些对象,可以通过Container注射进去,可以写一个标签一样的东西,包括还包含了一些第一例的条件控制,包括Struts2运行起来是否是DEV的模式,包括像Security Member Access初始化限制的一些类,就是之前在这个PPT里面介绍的这些,都是通过Context的方式注册进去的。我们可以看到,这边就是一个Context Build简单的构造,包括Struts DEV很多的属性,也会加载Struts里面的一些默认的属性,包括哪些类可以加载,哪些类不可以加载,都是在Container的一个容器里面。
了解了Container之后,我们了解一下Security Member Access的初始化过程。我们可以看到,所有的表达式通过工厂模式来创建的。我们可以看到,比如这里有一个方法,OGNL Value Stack,可以把一些属性注册到Container里面去,包括还有一个把Allow Static Method Acess的属性,注册过来,有这样一个标签一样的内容。这边是OGNL Value Stack的一个类,会构建一个防护。我们可以看到,在过程当中的一些内容,包括设置一个黑名单,就是Security Member Access黑名单设置一些属性,包括哪些类或者哪些包下载一些类,都不允许调用的,这个属性值都是通过OGNL这个类里面获取的。
我们可以看到,这边是一个OGNL Util里面,Struts-Default.xml里面,就是一个单域模型,表示只有一个OGNL Util的识别,我们只要控制这个,就可以控制Security Member Access里面的一些包括黑名单的包名,黑名单的一系列东西。因为Container又提供了不在黑名单里面的,我们可以通过操控Container,获取OGNL Util的对象,通过这个对于,我们可以把里面的一些东西设置为空,这样的话,Security Member Access这些黑名单属性就相当于是空的。我们所有的一些限制类,包括像Java、反射的一些属性都是可以绕过,可以直接去调用的。
这边Security Member Access的EXP,是绕过防护限制的。首先会定义一个Default Member的Access,一种是老版本里面的Struts2,有一个Security Member,我们只需要去覆盖Security Member Access就可以,这是老版本里面的情况。还有一种就是在新版本里面,在OGNL Container里面没有这个对象的应用,所以说我们需要通过刚才讲的那种方式,通过Container去获取OGNL Until之后,再把这个OGNL Unitl里面的一些黑名单、包名抹掉,再设置回去。然后再通过Security Member Access去覆盖原始的Security Member Access。这样的话,Defaul Member就是为了允许方法的调用,可以直接调用Jave里面其执行一些系统的命令。这里就是兼容了老版本跟新版本的一个情况。