SpringSecurityOauth RCE (CVE-2016-4977) 分析與復現


影響版本:
2.0.0-2.0.9
1.0.0-1.0.5

0x00 前言

這個漏洞與之前那個SpringBoot的SpEL表達式注入漏洞點基本一樣,而且漏洞爆出來的時間點也差不多,可是沒有找到那個漏洞的CVE編號,不知道是什么原因。
這個漏洞的觸發點也是對用戶傳的參數的遞歸解析,從而導致SpEL注入,可是兩者的補丁方式大不相同。Springboot的修復方法是創建一個NonRecursive類,使解析函數不進行遞歸。而SpringSecurityOauth的修復方法則是在前綴${前生成一個六位的字符串,只有六位字符串與之相同才會對其作為表達式進行解析。然而如果請求足夠多,這種補丁也是會失效的。

0x01 調試分析

payload:
http://localhost:8080/oauth/authorize?response_type=token&client_id=acme&redirect_uri=${new%20java.lang.ProcessBuilder(new%20java.lang.String(new%20byte[]{99,97,108,99})).start()}

首先,這個漏洞是在錯誤頁觸發的,所以這里在錯誤頁的控制器打個斷點。可以看到,最后渲染視圖的時候使用了SpelView,並傳入一個模板字符串,跟springboot的洞類似。

然后跟到render方法,接收模板字符串之后,接着使用replacePlaceholders方法,對模板進行解析。

跟進一下replacePlaceholders方法

跟進parseStringValue方法,這個方法與springboot中的方法基本相同,簡單看一下。

72行進行一次遞歸,用於解析模板中類似於${${}}的結構。由於這里的模板只是一個單純的${errorSummary},故不跟進這里。

73行是將errorSummary作為參數傳入SpEL模板解析引擎

可以看到,35行將errorSummary轉換成了一個字符串,注意看這個值,其中包含我們的payload:${xxxx}。

return之后回到parseStringValue函數,將返回值賦值給propVal。

繼續跟進,到87行,這里對propVal又進行了一次遞歸解析。而propVal的值中剛好包含我們的payload(即包含“${}”)

跟進遞歸,到66行成功將我們的payload從${}中提取出來,馬上就到觸發點了

跟進到73行,將payload傳入resolvePlaceholder,繼續跟進

成功在35行將payload作為SpEL表達式解析,彈出了計算器。

0x02 補丁分析

可以看到,這里在${前加了個
RandomValueStringGenerator().generate(),用於生成一個隨機字符串。可是正如前面說的,如果可以發出足夠多的請求,那么這個補丁依舊是可以被利用的。

0x03 參考

Spring Security OAuth RCE (CVE-2016-4977) 漏洞分析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM