标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2024-1738] 作者: ecawen 发表于: [2018-08-25] [2018-08-25]被用户:ecawen 修改过
本文共 [355] 位读者顶过
漏洞公告北京时间8月22日13时,Apache官方发布通告公布了Struts2中一个远程代码执行漏洞(CVE-2018-11776)。该漏洞在两种情况下存在,第一,在xml配置中未设置namespace值,且上层动作配置(upper action(s) configurations)中未设置或用通配符namespace值。第二,使用未设置 value和action值的url标签,且上层动作配置(upper action(s) configurations)中未设置或用通配符namespace值。 [出自:jiwo.org] 补丁对比如图所示,补丁主要添加了cleanNamespaceName方法,该方法通过白名单的方式来验证namespace是否合法,从官方描述和漏洞修复方式来看,该漏洞应该是一个Ognl的表达式注入漏洞
动态分析漏洞发布几个小时之后,漏洞发现作者公布了整个发现过程,并且详细分析了一种漏洞情形:https://lgtm.com/blog/apachestrutsCVE-2018-11776 按照该博客的说法,拉取struts2-showcase项目作为示例,修改struts-actionchaining.xml,具体如下:
在这种情况下,所有到actionChain1.action的请求的返回结果都会指向register2,并且执行链会到ServletActionRedirectResult.execute方法中,具体如下:
从上图可以看出,通过namespace字段,污染了tmpLocation字典,并且设置为了预期的执行的PoC,这也是补丁中为什么要净化namespace的原因,继续跟踪namespace的去向,执行链会到ServletActionRedirectResult的父类的父类StrutsResultSupport.execute方法中,具体如下图
这里有个conditionParse方法,这个方式就是使用Ognl表达式来计算数据值,在系统中用得非常多,而且在一些历史漏洞中,也应该由它来背锅,当然最大的锅还是struts官方,每次漏洞出在哪就修在哪,典型的头痛医头,脚痛医脚。方法实现如下图所示
在这个方法中会使用到TextParseUtil.translateVariables方法,继续跟踪,调用栈进入OgnlTextParser中的evaluate方法,首先会判断传入的表达式是否合法,比如是否能找到${}或者%{}对,接着调用evaluator.evaluate求值,求值过程非常复杂,总得来说就是链式执行过程,具体如下调用栈:
从上图也可以看出最顶层就是通过反射的方式来调用ProcessBuilder的构造函数,中间部分就是链式执行过程中牵涉到一些操作。 我们可以看下求值过程中参数的一些情况。来查看Ognl安全加固的一些变化,具体如下图:
主要是黑名单上又添加了一些类,分别是 classognl.DefaultMemberAccessclasscom.opensymphony.xwork2.ognl.SecurityMemberAccessclassjava.lang.ProcessBuilder 分析就结束了,计算器还是要弹的,如下图:
PoC 构造这块是最难的,也是最不好调试的,利用showcase项目很早就能执行${(1+1)}=2的效果,但是要弹出计算器,并不容易,其实就是新的沙箱的绕过,当时在调试的时候就发现,每次的返回结果都是空,没办法,只能耐着性子,将原先的PoC进行拆分,一个单元的一个单元的测试。测试获取#context的时候总为空,后来发现导致无法获取OgnlUtil的实例,怎么获取context,有多种方式,从代码结构来看可以从ognl表达式一些固有表达式来获取,如#root,#request等。 |