首页 > 代码库 > 重现Struts1的操纵classLoader漏洞

重现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