溫馨提示×

溫馨提示×

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

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

如何進行Spring全家桶中各類RCE漏洞淺析

發(fā)布時間:2021-12-18 18:25:02 來源:億速云 閱讀:206 作者:柒染 欄目:網(wǎng)絡管理

如何進行Spring全家桶中各類RCE漏洞淺析,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

Spring全家桶簡介

Spring發(fā)展到現(xiàn)在,全家桶所包含的內(nèi)容非常龐大,這里主要介紹其中關鍵的5個部分,分別是spring framework、 springboot、 spring cloud、spring security、spring mvc。其中的spring framework就是大家常常提到的spring, 這是所有spring內(nèi)容最基本的底層架構(gòu),其包含spring mvc、springboot、spring core、IOC和AOP等等。Spring mvc就是spring中的一個MVC框架,主要用來開發(fā)web應用和網(wǎng)絡接口,但是其使用之前需要配置大量的xml文件,比較繁瑣,所以出現(xiàn)springboot,其內(nèi)置tomcat并且內(nèi)置默認的XML配置信息,從而方便了用戶的使用。下圖就直觀表現(xiàn)了他們之間的關系。

如何進行Spring全家桶中各類RCE漏洞淺析而spring security主要是用來做鑒權,保證安全性的。Spring Cloud基于Spring Boot,簡化了分布式系統(tǒng)的開發(fā),集成了服務發(fā)現(xiàn)、配置管理、消息總線、負載均衡、斷路器、數(shù)據(jù)監(jiān)控等各種服務治理能力。

整個spring家族有四個重要的基本概念,分別是IOC、Context、Bean和AOP。 其中IOC指控制反轉(zhuǎn),在spring中的體現(xiàn)就是將對象屬性的創(chuàng)建權限回收,然后統(tǒng)一配置,實現(xiàn)解耦合,便于代碼的維護。在實際使用過程中可以通過autowired注解,不是直接指定某個類,將對象的真實類型放置在XML文件中的bean中聲明,具體例子如下:

<bean name="WelcomeService" class="XXX.XXX.XXX.service.impl.WelcomeServiceImpl"/>

public class WelcomeController {  

    @Autowired  

    private WelcomeService service;  

    @RequestMapping("/welcome")  

    public String welcome() {  

        return service.retrieveWelcomeMessage();  

    }  

}

Spring將所有創(chuàng)建或者管理的對象稱為bean,并放在context上下文中統(tǒng)一管理。至于AOP就是對各個MVC架構(gòu)的銜接層做統(tǒng)一處理,增強了代碼的魯棒性。下面這張圖就形象描述了上述基本概念。

如何進行Spring全家桶中各類RCE漏洞淺析

各子組件介紹

Spring發(fā)展至今,整個體系不斷壯大,子分類非常龐大,這里只對本次涉及的一些組件做簡單的介紹。

首先是Spring Websocket,Spring內(nèi)置簡單消息代理。這個代理處理來自客戶端的訂閱請求,將它們存儲在內(nèi)存中,并將消息廣播到具有匹配目標的連接客戶端。Spring Data是一個用于簡化數(shù)據(jù)庫訪問,并支持云服務的開源框架,其主要目標是使數(shù)據(jù)庫的訪問變得方便快捷。Spring Data Commons是Spring Data下所有子項目共享的基礎框架,Spring Data家族中的所有實現(xiàn)都是基于Spring Data Commons。簡單點說,Spring Data REST把我們需要編寫的大量REST模版接口做了自動化實現(xiàn),并符合HAL的規(guī)范。Spring Web Flow是Spring MVC的擴展,它支持開發(fā)基于流程的應用程序,可以將流程的定義和實現(xiàn)流程行為的類和視圖分離開來。

如何進行Spring全家桶中各類RCE漏洞淺析

使用量及使用分布

根據(jù)全網(wǎng)數(shù)據(jù)統(tǒng)計,使用Spring的網(wǎng)站多達80萬余,其中大部分集中在美國,中國的使用量排在第二位。其中香港、北京、上海、廣東四省市使用量最高。通過網(wǎng)絡空間搜索引擎的數(shù)據(jù)統(tǒng)計和柱狀圖表,如下圖所示。

如何進行Spring全家桶中各類RCE漏洞淺析

如何進行Spring全家桶中各類RCE漏洞淺析

漏洞背景介紹(SpEL使用)

0x10 SpEL是什么

SpEL是基于spring的一個表達式語言,類似于struts的OGNL,能夠在運行時動態(tài)執(zhí)行一些運算甚至一些指令,類似于Java的反射功能。就使用方法上來看,一共分為三類,分別是直接在注解中使用,在XML文件中使用和直接在代碼塊中使用。

0x20 SpEL能做什么

● 基本表達式

包括邏輯運算,三目運算和正則表達式等等。

● 類操作表達式

對象方法調(diào)用,對象屬性引用,自定義函數(shù)和類實例化等等。

● 集(平臺不讓發(fā)jihe)合操作表達式

字典的訪問,投影和修改等等。

● 其他表達式

模板表達式

0x30 SpEL demo

0x31 基于注解的SpEL

可以結(jié)合sping的@Value注解來使用,可以直接初始化Bean的屬性值

@RestController

class Sangfor {

    @Value(value = "${'aaa'.toUpperCase()}")

    private String test;

    public String getTest(){return test;}

    public void setTest(String value){this.test = value;}

}

在這種情況下可以直接將test的值初始化為AAA。

此外,還有很多其他注解的使用方式,可以結(jié)合上面提到的表達式的四種使用模式。

0x32 基于XML的SpEL

可以直接在XML文件中使用SpEL表達式如下:

public class SpEL {

    public static void main(String[] args){

        ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");

        String hello = ctx.getBean("hello", String.class);

        System.out.println(hello);

    }

}

上面的代碼將會輸出Hello World!,可以看到遞歸往下找到world的值,最終成功返回。

0x33 字符串操作

import org.springframework.expression.Expression;

import org.springframework.expression.ExpressionParser;

import org.springframework.expression.spel.standard.SpelExpressionParser;



public class SpEL {

    public static void main(String[] args){

        ExpressionParser parser = new SpelExpressionParser();

        // Expression exp = parser.parseExpression("'Hello '.concat('World')");

        Expression exp = parser.parseExpression("'Hello ' + 'World'");

        String message = (String) exp.getValue();

        System.out.println(message);

    }

}

注:類似的字符串操作比如toUpperCase(),substr()等等

0x34 類相關操作

使用T(class)來表示類的實例,除了java.lang的包,剩下的包需要指明。此外還可以訪問類的靜態(tài)方法和靜態(tài)字段,甚至實例化類。

public class SpEL {

    public static void main(String[] args){

        ExpressionParser parser = new SpelExpressionParser();

        Expression exp = parser.parseExpression("T(Runtime).getRuntime().exec('calc.exe')");

        Object message = exp.getValue();

        System.out.println(message);

    }

}

如上述操作,最終就可以執(zhí)行命令,彈出計算器。這也是后面SpEL RCE漏洞的利用形式。

0x35 集(平臺不讓發(fā)jihe)合相關操作

public class SpEL {

    public static void main(String[] args){

        ExpressionParser parser = new SpelExpressionParser();

        Expression exp = parser.parseExpression("{'sangfor', 'busyer', 'test'}");

        List<String> message = (List<String>) exp.getValue();

        System.out.println(message.get(1));  //busyer

    }

}

通過上面的操作,可以將字符串轉(zhuǎn)化成數(shù)組,最終可以輸出busyer。

SpEL原理

首先來了解幾個概念:

● 表達式

可以認為就是傳入的字符串內(nèi)容

● 解析器

將字符串解析為表達式內(nèi)容

● 上下文

表達式對象執(zhí)行的環(huán)境

● 根對象和活動上下文對象

根對象是默認的活動上下文對象,活動上下文對象表示了當前表達式操作的對象

具體的流程如下,其實就是編譯原理里面的詞法分析和句法分析:

如何進行Spring全家桶中各類RCE漏洞淺析

(1)首先給定表達式1+2

(2)然后給定SpelExpressionParser解析器,該解析器就實現(xiàn)了上圖中的分析

(3)定義上下文對象,這個是可選的,默認是StandardEvaluationContext

(4)使用表達式對象求值,例如getValue

具體代碼如下:

ExpressionParser parser = new SpelExpressionParser();

Expression exp = parser.parseExpression("{'sangfor', 'busyer', 'test'}");

//StandardEvaluationContext context = new StandardEvaluationContext();

String message = (String)exp.getValue(context, String.class);

root和this

SpEL中#root總是指的剛開始的表達式對象,而#this總是指的當前的表達式對象,用他們可以直接操作當前上下文。

SimpleEvaluationContext和StandardEvaluationContext

SimpleEvaluationContext: 不包含類相關的危險操作,比較安全

StandardEvaluationContext: 包含所有功能,存在風險

高危漏洞介紹

通過對Spring漏洞的收集和整理,過濾出其中影響較大的遠程代碼執(zhí)行高危漏洞,可以得出如下列表:

如何進行Spring全家桶中各類RCE漏洞淺析從上表可以看出,這些漏洞分布在Spring不同的子分類之間,且大多都是較低的版本,用戶只要及時升級高版本并及時關注新的漏洞信息即可輕松規(guī)避這些漏洞。盡管近期沒有出現(xiàn)相關漏洞,但是這些高風險漏洞依然不可忽視。這里面出現(xiàn)的漏洞大多不需要復雜的配置就可以直接攻擊成功,從而執(zhí)行任意代碼,危害較大。所以,開發(fā)者在使用Spring進行開發(fā)的過程中,一定要關注其歷史風險點,盡量規(guī)避高危漏洞,減少修改不必要的配置信息。

漏洞利用鏈

上述漏洞基本不依賴其他Spring漏洞即可直接獲取權限,下圖對其利用方式做了簡要概述:

高可利用漏洞分析

如何進行Spring全家桶中各類RCE漏洞淺析

1 CVE-2018-1270

1.1 威脅等級

嚴重

1.2 影響范圍

Spring Framework 5.0 - 5.0.5

Spring Framework 4.3 - 4.3.15

1.3 利用難度

簡單

1.4 漏洞描述

在上面描述的存在漏洞的Spring Framework版本中,允許應用程序通過spring-messaging模塊內(nèi)存中STOMP代理創(chuàng)建WebSocket。攻擊者可以向代理發(fā)送消息,從而導致遠程執(zhí)行代碼攻擊。

1.5 漏洞分析

點擊connect,首先將觸發(fā)DefaultSubscriptionRegistry.java中的addSubscriptionInternal方法,

如何進行Spring全家桶中各類RCE漏洞淺析第80行將首部的selector字段的值取出,就是我們之前傳入的惡意表達式,接著到83行,這一步就很熟悉了,使用解析器去解析表達式,顯然這個時候再有一個getValue方法觸發(fā)并且沒有使用simpleEvaluationContext就能夠直接執(zhí)行我們傳入的表達式了。

監(jiān)聽網(wǎng)絡流量,發(fā)現(xiàn)后面send信息的時候,將會將消息分發(fā)給不同的訂閱者,并且轉(zhuǎn)發(fā)的消息還會包含之前connect的上下文,即這里的expression將會包含在內(nèi)。

如何進行Spring全家桶中各類RCE漏洞淺析于是,嘗試隨便在文本框中輸入一些內(nèi)容,然后點擊Send,最終可以觸發(fā)SimpleBrokerMessageHandler.java中的sendMessageToSubscribers方法如下:

如何進行Spring全家桶中各類RCE漏洞淺析繼續(xù)進入findSubscriptions方法,并且不斷往下走,最終可以發(fā)現(xiàn)在DefaultSubscriptionRegistry.java中filterSubscriptions方法中對上下文中的expresion做了提取,并使用StandardEvaluationContext指定了上下文,也就是說這里面可以直接執(zhí)行代碼,沒有任何限制。并最終在第164行使用getValue方法觸發(fā)漏洞,彈出計算器。

如何進行Spring全家桶中各類RCE漏洞淺析1.6 補丁分析

補丁中直接將上面的StandardEvaluationContext替換成SimpleEvaluationContext,使用該方法能夠避免了惡意類的加載。

CVE-2018-1273

2.1 威脅等級

嚴重

2.2 影響范圍

Spring Data Commons 1.13 - 1.13.10 (Ingalls SR10)

Spring Data REST 2.6 - 2.6.10 (Ingalls SR10)

Spring Data Commons 2.0 to 2.0.5 (Kay SR5)

Spring Data REST 3.0 - 3.0.5 (Kay SR5)

2.3 利用難度

簡單

2.4 漏洞描述

Spring Data Commons組件中存在遠程代碼執(zhí)行漏洞,攻擊者可構(gòu)造包含有惡意代碼的SPEL表達式實現(xiàn)遠程代碼攻擊,直接獲取服務器控制權限。

2.5 漏洞分析

從上述/users入口,最終會調(diào)用到MapPropertyAccessor靜態(tài)類中對用戶名進行處理。而在該類中包含了進行SpEL注入需要滿足的條件如下:

● 首先創(chuàng)建解析器:

如何進行Spring全家桶中各類RCE漏洞淺析● 接著使用Standard上下文

如何進行Spring全家桶中各類RCE漏洞淺析● 然后包含待解析表達式

如何進行Spring全家桶中各類RCE漏洞淺析● 最后使用setValue觸發(fā)

如何進行Spring全家桶中各類RCE漏洞淺析

2.6 補丁分析

補丁依舊直接將上面的StandardEvaluationContext替換成SimpleEvaluationContext,使用該方法能夠避免了惡意類的加載。

CNVD-2016-04742

3.1 威脅等級

嚴重

3.2 影響范圍

Springboot 1.1.0-1.1.12

Springboot 1.2.0-1.2.7

Springboot 1.3.0

3.3 利用難度

簡單

3.4 漏洞描述

低版本的springboot在處理內(nèi)部500錯誤時,使用了spel表達式,并且遞歸向下解析嵌套的,其中message參數(shù)是從外部傳過來的,用戶就可以構(gòu)造一個spel表達式,達到遠程代碼執(zhí)行的效果。

3.5 漏洞分析

訪問上面的URL,可以進入到我們的控制器,并緊接著拋出異常如下:

如何進行Spring全家桶中各類RCE漏洞淺析進入異常的代碼,經(jīng)過冗長的代碼調(diào)試,最終可以來到關鍵點的render方法:

如何進行Spring全家桶中各類RCE漏洞淺析接著進入render方法查看,這里面的replacePlaceholders方法將會進行形如${}的spel表達式替換:

如何進行Spring全家桶中各類RCE漏洞淺析進入該方法查看,最后進入parseStringValue方法,該方法會循環(huán)將帶有${}的錯誤頁面的HTML字符串中的一個個${}的內(nèi)容進行替換,并且這里面的${message}是我們傳入的值。

如何進行Spring全家桶中各類RCE漏洞淺析于是可以就此構(gòu)造我們的payload,借助他的循環(huán),繼續(xù)解析spel,最終造成任意代碼執(zhí)行。其中,解析spel的代碼如下:

如何進行Spring全家桶中各類RCE漏洞淺析3.6 補丁分析

通過添加一個NonRecursivePropertyPlaceholderHelper類,對于二次解析的值進行限制:

如何進行Spring全家桶中各類RCE漏洞淺析

如何進行Spring全家桶中各類RCE漏洞淺析4 CVE-2017-8046

4.1 威脅等級

嚴重

4.2 影響范圍

Spring Data REST prior to 3.0.1 and Spring Boot versions prior to 1.5.9

Spring Data REST prior to 2.6.9 Spring Boot versions prior to 1.5.9

4.3 利用難度

簡單

4.4 漏洞描述

用戶在使用PATCH方法局部更新某個值的時候,其中的path參數(shù)會被傳入SpEL表達式,進而導致代碼執(zhí)行。

4.5 漏洞分析

執(zhí)行上述payload,定位到程序的入口如下:

如何進行Spring全家桶中各類RCE漏洞淺析

(注:這個類在springmvc里面,名字為JsonPatchHandler)

重點看這個三目運算,其中的判斷是看HTTP方法是否為PATCH和content-type是否為我們上面提到的那個,然后會進入this.applyPatch方法,接著根據(jù)我們指定的replace字段進入對應的處理器:

如何進行Spring全家桶中各類RCE漏洞淺析

然后實例化patchOperation,并初始化spel解析器:

如何進行Spring全家桶中各類RCE漏洞淺析

最后再調(diào)用setValue觸發(fā):

如何進行Spring全家桶中各類RCE漏洞淺析

4.6 補丁分析

這里用2.6.9中的修復方案舉例子,在perform中不是直接setvalue,而是先做一個參數(shù)合法性校驗(此處添加了SpelPath類),將path中的參數(shù)用'.'分割,然后依次判斷是否是類的屬性,只要有一個不是就直接報錯,從而解決了上述問題,部分補丁圖片如下:

如何進行Spring全家桶中各類RCE漏洞淺析

如何進行Spring全家桶中各類RCE漏洞淺析

如何進行Spring全家桶中各類RCE漏洞淺析

5 CVE-2017-4971

5.1 威脅等級

中危

5.2 影響范圍

Spring Web Flow 2.4.0 ~ 2.4.4

Spring Web Flow 2.4.4 ~ 2.4.8

5.3 利用難度

較高

5.4 漏洞描述

當用戶使用Spring Web Flow受影響的版本時,如果配置了view-state,但是沒有配置相應的binder,并且沒有更改useSpringBeanBinding默認的false值,當攻擊者構(gòu)造特殊的http請求時,就可以導致SpEL表達式注入,從而造成遠程代碼執(zhí)行漏洞。

5.5 漏洞分析

首先通過執(zhí)行confirm請求,斷點到如下位置:

如何進行Spring全家桶中各類RCE漏洞淺析這里可以發(fā)現(xiàn)可以通過判斷binderConfiguration是否為空來選擇進入哪個處理方法,這里的binderConfiguration值指的是在配置文件中配置的binder內(nèi)容。深入查看這兩個處理方法。其實都用了SpEL表達式,不過addModelBindings方法傳入的參數(shù)的是上面提到的binder,是寫死在xml文件中的,無法去更改,所以這里面就考慮當沒配置binder的情況下走進addDefaultMapping方法的情況。

如何進行Spring全家桶中各類RCE漏洞淺析addDefaultMappings方法如上,其作用是遍歷所有的參數(shù),包括GET參數(shù)和POST中的參數(shù),然后一個個判斷其是否以"_"開頭,如果符合就進入addEmptyValueMapping方法進行處理,否則就進入addDefaultMapping方法進行處理。本次漏洞的觸發(fā)點是上面這一個,所以我們深入查看一下addEmptyValueMapping方法。

如何進行Spring全家桶中各類RCE漏洞淺析可以看到該方法用SpEL表達式解析了傳入的變量名,并在后面使用了get操作,從而可以導致漏洞的產(chǎn)生。

5.6 補丁分析

查看官方補丁源碼如下:

如何進行Spring全家桶中各類RCE漏洞淺析將表達式類型換成了BeanWrapperExpressionParser,因為該類型內(nèi)部實現(xiàn)不能夠處理類所以避免了該問題的發(fā)生。

然而上述還提到如果參數(shù)類型不是以"_"開頭的將會進入addDefaultMapping方法,下面我們進入該方法進行查看:

如何進行Spring全家桶中各類RCE漏洞淺析可以看到這里也對傳入的參數(shù)進行了解析但是沒有看到明顯的get方法來觸發(fā),繼續(xù)往下尋找get方法。首先這里面將解析器放入了mapper中,下面就重點追蹤這個mapper的使用即可。

首先發(fā)現(xiàn)一步步回到之前的bind方法,可以發(fā)現(xiàn)最后一行對該mapper進行了操作,跟進該map方法:

如何進行Spring全家桶中各類RCE漏洞淺析在這里就進行了get操作,從而再次觸發(fā)了漏洞。

對此,也可能跟這個沒關系,官方最終將全局的解析器換成SimpleEvaluationContext來徹底解決此問題。

6 CNVD-2019-11630

6.1 威脅等級

嚴重

6.2 影響范圍

Spring Boot 1-1.4

Spring Boot 2.x

6.3 利用難度

簡單

6.4 漏洞描述

用戶在通過env路徑修改spring.cloud.bootstrap.location的位置,將該地址設置為一個惡意地址時,并在后面使用refresh接口進行觸發(fā)就可以導致靶機加載惡意地址中的文件,遠程執(zhí)行任意代碼。

6.5 漏洞分析

搭建環(huán)境并按上述方式進行攻擊,并搜索到spring-cloud-context-1.2.0.RELEASE.jar中的environment和refresh,然后下斷點跟進,可以發(fā)現(xiàn)首先的env改變會將下面體現(xiàn):

如何進行Spring全家桶中各類RCE漏洞淺析其實就是將環(huán)境中該變量的屬性值進行更新。

之后看一下關鍵點refresh接口,首先一旦refresh接口被觸發(fā),就會將有變化的信息以及一些基本信息挑選出來,如下圖可以看到之前變化的值已經(jīng)被挑選出來:

如何進行Spring全家桶中各類RCE漏洞淺析接著進入到addConfigFilesToEnvironment方法進行處理,先獲取到所有的環(huán)境值,然后設置一個監(jiān)聽器,依次處理變化的信息:

如何進行Spring全家桶中各類RCE漏洞淺析這里我們直接跳轉(zhuǎn)到處理這個惡意地址的關鍵部分,首先進入ConfigFileApplicationListener的load方法:

如何進行Spring全家桶中各類RCE漏洞淺析這里面先判斷url是否存在文件路徑,如果存在才進入處理該地址,否則將name的參數(shù)設置成searchName進行處理,這里的值為“bootstrap”,后面會強行加上后綴。然后一直深入到PropertySourcesLoader類中的load方法:

如何進行Spring全家桶中各類RCE漏洞淺析首先會發(fā)送一個head請求判斷文件是否存在,以及是否是一個文件,然后會根據(jù)文件后綴來判斷是否能解析,這里面就是yml文件,所以判斷可以用YamlPropertySourceLoader類來處理。然后進入該類的load方法中:

如何進行Spring全家桶中各類RCE漏洞淺析在這里將會加載遠程yml文件,并處理里面的內(nèi)容,而導致遠程代碼執(zhí)行的發(fā)生。

6.6 補丁分析

在springboot 1.5及以后,官方對這些接口添加了授權驗證,不能夠再肆意的調(diào)用他們了。

看完上述內(nèi)容,你們掌握如何進行Spring全家桶中各類RCE漏洞淺析的方法了嗎?如果還想學到更多技能或想了解更多相關內(nèi)容,歡迎關注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細節(jié)

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

AI