重現Struts1的操縱classLoader漏洞
2014年4月29日爆出的struts的可操縱classLoader的漏洞, 橫跨struts1和struts2的所有版本。 影響面和問題的嚴重性幾乎可以和heartbleed相媲美。 struts2要嚴重一些,對於struts1,只是說在特定條件下可執行特殊操作。
因為專案中用的是struts1,所以主要精力集中在struts1上。既然要修復漏洞,首先得找出POC給老闆看,這類漏洞一般網上不會給出直接的POC,於是就動手搗鼓一番。建立一個簡單的struts1專案,包含一個Action和ActionForm即可。 啟用debug模式部署專案到tomcat等容器。然後在action的任意位置加一個斷點,然後通過瀏覽器訪問該action。既然說是"操縱classLoader",我馬上想到的是struts自動封裝表單用到反射,在斷點附近尋找ActionForm的class的classLoader的屬性列表,看看有誰的名字聽起來是可操縱的。最初我就發現了這個:clearReferencesHttpClientKeepAliveThread
.於是有如下的url和截圖:
http://localhost:8080/Struts1/helloWorld.do?class.classLoader.clearReferencesHttpClientKeepAliveThread=false
http://localhost:8080/Struts1/helloWorld.do?class.classLoader.clearReferencesHttpClientKeepAliveThread=true
至此classLoader操作成功, 儘管clearReferencesHttpClientKeepAliveThread是一個暫時看起來不太危險的classLoader屬性。
我看到部分資料說該漏洞在jetty7 下可關閉jetty伺服器, 我也試了, 可以, 你可以把專案部署到jett7, 然後用如下url:
http://localhost:8080/Struts1/helloWorld.do?class.classloader.context.shutdown=true
一旦class.classloader.context.shutdown被輸入,則後續的所有請求都只能收到404,要想恢復的唯一辦法就是重啟jetty。
如圖:
還有更多的其他的POC比如在tomcat8下可下載任意檔案,在其他情況下可執行code等待,我就沒有一一證明。
因為struts1在該漏洞發出後, apache宣佈struts1即將EOL, 所以我們也不打算花太多精力搞個威猛的方案出來,用了一個filter來檢查請求引數是否包含“class.*”完事。程式碼片段如下:
public static final String classLoaderManipulatorParamReg = "(class\\.)|(class.classLoader\\.)" ; public static final Pattern classLoaderManipulatorParamPattern = Pattern.compile(classLoaderManipulatorParamReg); Enumeration<String> params = request.getParameterNames(); while(params.hasMoreElements()){ String key = params.nextElement(); Matcher matcher = classLoaderManipulatorParamPattern.matcher(key); if(matcher.find()){ System.out.println("suspicious parameters: " + key + ", removed from the parameter list."); req.setAttribute("msg", key+"=" + req.getParameter(key)); request.getRequestDispatcher("unsafeRequest.jsp").forward(req, response); //logger.warn(this, "suspicious parameter: " + key); // 需替換尖括號以防止反射型的XSS漏洞 String kvPair = (key+"=" + req.getParameter(key)).replaceAll("<", "& lt;").replaceAll(">","& gt;"); /* * 這裡需要注意:如果用以下方式重定向到出錯頁面, 極有可能導致遞迴的filter呼叫從而進入死迴圈。 * request.getRequestDispatcher("unsafeRequest.jsp").forward(req, response); * 如果你想走到一個單獨的出錯頁面來顯示錯誤資訊, 需要謹慎處理。 * 我們這裡就簡單的直接輸出出錯資訊到response. */ response.getWriter().write("Malicious parameter detected: " + kvPair); response.getWriter().flush(); return; } }
你可以在這裡下載struts1樣例程式: http://download.csdn.net/detail/sunxing007/7350433。如要重現POC, 請先把web.xml中SecurityFilter去掉。
轉載請註明來自: http://blog.csdn.net/sunxing007