CVE-2018-11776: Apache Struts OGNL沙箱绕过
本文讲述如何构建CVE-2018-11776的漏洞利用。
Struts OGNL利用史
首先介绍一些背景和概念以帮助理解OGNL利用的过程。首先介绍下OGNL的基本概念。
OGNL执行环境
在Struts的中,OGNL可以使用#符号访问全局对象。本文介绍一些可以访问的对象,其中列出的对象中有两个对构建exp非常关键。第一个对象是 _memberAccess,这是用来控制OGNL 行为的SecurityMemberAccess对象,另一个是context,这是允许访问更多的其他对象的context图。获取对 _memberAccess的访问权限可以轻易地修改SecurityMemberAccess 的安全设置。比如:
#_memberAccess['allowStaticMethodAccess']=true会修改_memberAccess中的设置。
@java.lang.Runtime@getRuntime().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).(@java.lang.Runtime@getRuntime().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就可以了。
#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(@java.lang.Runtime@getRuntime().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(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.excludedClasses.clear()).(#ognlUtil.excludedPackageNames.clear()).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(@java.lang.Runtime@getRuntime().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是一样的。
本文讲述如何构建CVE-2018-11776的漏洞利用。
Struts OGNL利用史
首先介绍一些背景和概念以帮助理解OGNL利用的过程。首先介绍下OGNL的基本概念。
OGNL执行环境
在Struts的中,OGNL可以使用#符号访问全局对象。本文介绍一些可以访问的对象,其中列出的对象中有两个对构建exp非常关键。第一个对象是 _memberAccess,这是用来控制OGNL 行为的SecurityMemberAccess对象,另一个是context,这是允许访问更多的其他对象的context图。获取对 _memberAccess的访问权限可以轻易地修改SecurityMemberAccess 的安全设置。比如:
#_memberAccess['allowStaticMethodAccess']=true会修改_memberAccess中的设置。
@java.lang.Runtime@getRuntime().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).(@java.lang.Runtime@getRuntime().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就可以了。
#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(@java.lang.Runtime@getRuntime().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(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.excludedClasses.clear()).(#ognlUtil.excludedPackageNames.clear()).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(@java.lang.Runtime@getRuntime().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是一样的。
本文来自无奈人生安全网