我滴個乖乖,我復(fù)現(xiàn)了Spring的漏洞,害怕!
你好呀,我是歪歪。
前天發(fā)布了《我想問問:你昨晚吃到 Spring 的驚天大瓜了嗎?》這篇文章,沒想到閱讀量居然這么高。
這篇文章其實是我那天晚上知道這個“瓜”之后,看到很多技術(shù)群都在討論,大概在 ?23 點 30 分的時候開始想寫一篇,然后卡著零點發(fā)。
因為我想著本來著憑借我的手速,寫這篇文章 30 分鐘夠夠的吧。
于是我邊寫邊吃瓜,吃著吃著,時間就來到了第二天零點。

看著時間,又看著沒寫幾個字的文章,當時我就想:哎,這特么的拖延癥也來越嚴重了.......反正都已經(jīng)到凌晨了,要不打幾把歡樂斗地主,歡樂歡樂?昨天把豆子輸光了,今天又可以免費領(lǐng)豆子了。
所以....
我又打了幾把斗地主。很快啊,又沒有豆子了。

接著開始苦哈哈的寫文章,一不留神就寫到第二天凌晨 1 點 25 分。
為什么我記得這么清楚呢?
因為我寫這篇文章的時候還是很興奮的,畢竟吃 Spring 的大瓜,一輩子也吃不了幾次。
我看了一下我的手表記錄,在 1 點 25 分之后,我的心率開始下降,所以應(yīng)該是這個時候?qū)懲晡恼碌模?/p>
哎,這件事情再次印證了寫公眾號的,或者說做自媒體的人的一個“黃金定律”:
一些文章寫的時候覺得這文章真牛逼,我花了這么多時間寫出來,這玩意一發(fā)出去肯定是爆款啊,這都不火,天理難容啊!
結(jié)果,真的發(fā)出去之后,石沉大海,無人問津。
往往是不經(jīng)意間寫的東西,突然就火了。
這東西,你找誰說理去?

言歸正傳
好了,言歸正傳。
我真的復(fù)現(xiàn)了這次 Spring 的漏洞。
昨天晚上我正在家里悄悄卷你們的時候,突然有人給我發(fā)來這樣的一個鏈接:
https://sizeof.cat/post/springcore-rce/
然后只配上了四個字:

于是我趕緊點進去看了一下。
很明顯這個文章最開始的時候應(yīng)該也是和我一樣一起吃瓜的。
因為他最開始的描述是用的這樣的詞匯:

可能、據(jù)說、大概...
然后在某個時間點變成了這樣:

簡單來說就是:實錘了!

而文章中提到的這個地方是一個 PDF 文件:

這個 PDF 文件就是本文的核心了。
但是,我想先拐個彎讓你看看這個地方:
https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement
這里才是 Spring 關(guān)于這個漏洞的官宣。我強烈建議你自己去讀一讀這個官宣,里面內(nèi)容比較多,我就不給大家一一翻譯了。
只是給大家看看這個地方:

這里說了兩件事,相當于“辟謠”。
第一個是關(guān)于我之前文章中提到的廢棄 SerializationUtils 方法。

你看我之前的文章說的還是“疑似瓜”,說明我還是比較嚴謹?shù)摹?/p>
官方的博客說:
The deprecation is unrelated to this vulnerability.
棄用與此漏洞無關(guān)。
幸好我在之前的文章里面說了:

這不,打臉來的那么快。但是沒關(guān)系,吃瓜嘛,開心最重要,挨幾巴掌,不寒磣。

第二個事情是說這段時間 Spring Cloud Function 也爆出了一個高危漏洞,但是這個漏洞是在 Spring 漏洞之前爆出來的。
官方的說法是:
It is also unrelated.
這兩者之間這也是不相關(guān)的。
所以,大家在吃瓜的時候要看準方向,被別一些司機帶錯路了,假瓜吃的津津有味,自己還不知道。

然后,在我寫文章的時候,這個官方博客也在不斷的更新:

可以看到在 14:00 更新了這個漏洞報告:
https://tanzu.vmware.com/security/cve-2022-22965

在這個報告里面,再次明確了這個漏洞的先決條件:
- 必須是 JDK 9+ 的版本。
- 必須是 Apache Tomcat 作為 Servlet 容器。
- 必須是以 war 的形式打包。
- 必須是依賴了 spring-webmvc 或 spring-webflux。
我想第一個條件,就讓一大批人放心了。
至少這波,不用加班加點的升級修復(fù)了。
可以安心吃瓜。

開始復(fù)現(xiàn)
額,這么寫到這里了都還沒有進入正題呢。
好吧,我想閑扯的基本上也就扯完了,下面開始搞事情。
讓我們回到這個地方:

你訪問下面這個鏈接,可以直接拿到這個 pdf:
https://sizeof.cat/post/springcore-rce/files/readme.pdf
打開這個 PDF 之后,你可以看到如果要復(fù)現(xiàn)漏洞,要求條件是這樣的:

你仔細思考,其實這些條件都在 Spring 官宣的先決條件內(nèi)。
先不必糾結(jié)于此,主要記住我框起來的這兩個點,然后直接看下面的重點。

在漏洞分析里面,他提到了一句話,是重中之重:
因為我覺得需要使?的參數(shù)內(nèi),存在?個 Class 類型的屬性。
什么意思呢?
就是假設(shè)我們定義一個請求對象,叫做 UserReqDto,是這樣定義的:

里面有一個 Class 類型的屬性,就是這個意思。
確實,我縱橫開發(fā)界這么久,就沒有見過請求對象里面要求傳 Class 的。
但是他給出了這樣的一個示例:

分別有兩個對象,EvalBean 和 CommonBean。
其中 CommonBean 是 EvalBean 的一個屬性。
這樣的定義就非常的常見了吧,項目里面一抓一大把。
然后還記得我前面框起來的兩個點嗎?

這啥意思?
上個代碼你就看的明明白白的:

這寫法就是“Spring 的參數(shù)綁定”,這不就是我們常規(guī)的寫法嗎?沒有看到任何不妥的地方呀?
是的,沒有看到任何不妥的地方。
但是,如果你這樣的代碼對應(yīng)的運行環(huán)境和方式,滿足了前面官方提到的先決條件。
那么恭喜你,就是有漏洞的。
你就仔細想想,是不是細思極恐?

那么對應(yīng)的原理是啥呢?
大佬在 PDF 里面指了個路:


意思就是在前面的示例代碼中,請求對象中雖然沒有 class 熟悉,但是在 Spring 進行參數(shù)綁定的時候會憑空多出一個 “class” 屬性。
那么為什么會多出來呢?
我不知道,我也沒去深入研究。大概是因為反射的時候獲取 bean 信息會處理所有以 get 開頭的方法,所以?getClass 方法被映射成了 class 屬性。
然后再想一想為什么是 JDK 9+ 以后才有這個問題呢?
我也不知道,但我盲猜一波是因為這個東西,模塊化:

但是我也沒有具體的依據(jù),都說了是盲猜了。
反正路指給你了,你想深入的話,可以從這條路走。
那么到底怎么發(fā)起攻擊呢?
PDF 里面也寫了。
你只要把代碼打個 war 包,然后運行在對應(yīng)的環(huán)境中,并執(zhí)行下面這五個請求:

就能在項目的 out 文件夾中寫入一個 jsp:

寫入 jsp 文件啊!
老鐵,這可是寫入了一個 jsp 文件啊!
我不知道你有沒有經(jīng)歷過 jsp 文件寫頁面的那個時代,我以前寫過。
我當年特別喜歡這個東西,因為它支持熱部署,修改了 jsp 頁面的內(nèi)容,都不用重啟的。
所以,我喜歡通過 jsp 頁面留下一點方便我對項目進行運維的后門操作。
后門是啥,具體就不詳說了。

如果你知道 jsp 的威力,你就能明白這句話的分量是多大:
這可是由別人通過構(gòu)造特定的請求寫入了一個 jsp 文件在你的項目里面啊!
而且,我能寫 jsp 了,難道我就不能多寫點其他的什么東西....
但是我必須要補充一句,如果你也想復(fù)現(xiàn)這個漏洞,最關(guān)鍵的是前面提到的“五個請求”。
然而在 pdf 里面,這五個請求的內(nèi)容其實是不全的,大概缺失了 30% 的內(nèi)容。
我不知道為什么,但是我猜測是作者故意的。
但是,憑借我超強的悟(瞎)性(猜),我花了一點時間,補全了這部分的請求。
所以,經(jīng)過一番折騰,我本地也成功寫入了這個 jsp 文件:

萬事俱備,只需要觸發(fā)一下了。
怎么觸發(fā)呢?
jsp 頁面還能怎么觸發(fā),簡單的很嘛。
直接訪問對應(yīng)鏈接就可以了:

我能調(diào)起計算器,我就能接管你的機器。
而在這個過程中,控制臺不會有任何輸出:

但是還是能處理正常的請求,且打印日志:

潛入細無聲,我就問你,怕不怕!

p1n93r
從 PDF 上看,是一個叫做 p1n93r 寫的這個 PDF,并且把相關(guān)測試代碼開源了:

但是在我看到這篇文章并點擊這個開源項目的時候,發(fā)現(xiàn)已經(jīng) 404 了:

甚至,p1n93r 也已經(jīng) 404 了:

然后我搜索了一下這個關(guān)鍵詞:

確認這是一個安全大佬,但是不知道是紅是黑。
我的搜索也就止步于此了,很明顯,他主動刪除了相關(guān)的項目,甚至主動讓自己在 github 上消失,就是不想引起關(guān)注。
對于一個安全大佬來說,靜默,就是最好的生存之道。
這讓我想起了和另外一個安全大佬的對話:

幸好,我這里還有另外一份源碼。
好了,如果你也想要對應(yīng)的源碼的話。可以在公眾號后臺回復(fù)關(guān)鍵字【漏洞】就可以了。
拿著源碼,配合著 PDF 看,自己去玩吧。但是可能手速得快,我怕這一份源碼也被刪了。
就到這。
荒腔走板

我就是我 是顏色不一樣的煙火
天空海闊 要做最堅強的泡沫
我喜歡我 讓薔薇開出一種結(jié)果
孤獨的沙漠里 一樣盛放的赤裸裸
——《我》
冥冥中都早注定你富或貧
是錯永不對真永是真
任你怎說安守我本分
始終相信沉默是金
——《沉默是金》
風(fēng)繼續(xù)吹不忍遠離
心里極渴望希望留下伴著你
風(fēng)繼續(xù)吹不忍遠離
心里亦有淚不愿流淚望著你
——《風(fēng)繼續(xù)吹》
最后說一句
好了,看到了這里了, 轉(zhuǎn)發(fā)、在看、點贊 隨便安排一個吧,要是你都安排上我也不介意。寫文章很累的,需要一點正反饋。
給各位讀者朋友們磕一個了:
推薦???:發(fā)現(xiàn)Spring事務(wù)的一個bug,官方表示6.0版本修復(fù)。
推薦???:當Synchronized遇到這玩意兒,有個大坑,要注意!
··································
你好呀,我是歪歪。一個主要敲代碼,經(jīng)常懟文章,偶爾拍視頻的成都人。
我沒進過一線大廠,沒創(chuàng)過業(yè),也沒寫過書,更不是技術(shù)專家,所以也沒有什么亮眼的title。
當年以超過二本線 13 分的“優(yōu)異”成績順利進入某二本院校計算機專業(yè),誤打誤撞,進入了程序員的行列,開始了運氣爆棚的程序員之路。
說起程序員之路還是有點意思,可以看看。點擊藍字,查看我的程序員之路
