Java程式碼審計篇 - ofcms系統審計思路講解 - 篇2 - SQL隱碼攻擊漏洞審計

leyilea發表於2024-09-23

Java程式碼審計篇 | ofcms系統審計思路講解 - 篇2 | SQL隱碼攻擊漏洞審計

1. 前言

我發現很多文章包括教程,大概套路是:只說有漏洞的點,將有漏洞的點指出,然後分析程式碼;或者黑盒測試出漏洞之後,然後分析程式碼。

我認為這是在分析漏洞程式碼,而非程式碼審計。程式碼審計文章或教程應該是從0開始找到漏洞所在,包括思路!

所以這裡不管有沒有漏洞,我都會把審計過程寫出來,因此篇幅會很長,但我認為這樣對你會很有幫助。

知其然亦知所以然。

由於篇幅較長,因此我會分幾篇進行,本篇是整個系列的第2篇,講解1個內容:

  • SQL隱碼攻擊漏洞審計

搭建好環境,確定好專案結構之後,按我思路是應該審計專案所使用框架漏洞的,這裡關於框架漏洞就放最後篇章來說了,我們想了解下基礎漏洞的審計~

文章中有錯誤點,或者思路上有什麼問題的,歡迎師傅們留言指出~

2. SQL隱碼攻擊程式碼審計【有1處】

sql注入漏洞一般搜尋的關鍵字:

Statement
createStatement
PreparStatement
like "%{
in (${
select 
update
insert
...

1)全域性搜尋Statement關鍵字,發現有幾處,不過大多都是preparStatement預編譯方式執行sql語句。

那要不要點選去看看?答案是需要!因為可能會有繞過方式...

2)點進第一個看看

核心程式碼已框出,就是預編譯執行sql語句~哦,戲不大。

不過大家可以思考一下:如果整個sql語句都可控呢?是不是可以繞過預編譯限制呢?

所以我們不要放棄,接下來看一下sql語句怎麼來的。

3)搜尋executeSQL()方法的呼叫,檢視sql語句怎麼傳遞進來的

在方法上右擊,然後“Find Usages”或Alt+F7檢視方法的呼叫:

發現有兩個,如下

有辦法注入嗎?貌似沒有,原因有2:

  • sql語句是寫死的
  • 引數是單獨傳入的,但是後期是需要經過預處理的

其實這裡還有一個點,就是這兩個方法是在安裝工具類InstallUtils下,因此即使有sql注入點,也無法利用,畢竟你不可能去重新安裝該專案吧。

所以,接下來,安裝工具類InstallUtils下的程式碼我們就不需要看了。

2.4. 4)我們搜尋的Statement關鍵字,所處位置都是安裝工具類InstallUtils,所以全部忽略。

接下來換關鍵字搜尋:

5)全域性搜尋like "%關鍵字,發現有1處,不過是註釋,不需要管了。

6)全域性搜尋in (${關鍵字,無

7)全域性搜尋select關鍵字,很多,但是翻了一圈,沒有和sql語句相關的

8)全域性搜尋update關鍵字,搜尋到了很多貌似和sql有關係的語句

並且可以發現一個共同點,大部分都是Db.update呼叫的。

9)點進第一個看看,發現這個ComnController類裡面的方法都和sql語句相關,那挨個看一下

10)先分析下query()方法

這裡發現,Db這個是什麼,點進去看一下,發現是專門用來運算元據庫的類:

自己寫的嗎?不不不,可以看到,該檔案是Db.class,可以下載原始碼

經過分析檢視,這個Dbcom.jfinal.plugin.activerecord目錄下的一個類,原來是使用的jfinal框架~ 是我孤陋寡聞了。

透過分析Db的原始碼,發現每個方法都使用了預編譯處理~ 有漏洞的可能性不大了

但是還有一種情況,就是前面所說的,整個sql語句可控,那麼可能會存在sql注入~

11)檢視每個方法的呼叫,發現整個sql語句可控的情況

當我們找到update(String sql)方法的呼叫情況,SystemGenerateController類的create()方法時,發現此處的sql語句是透過getPara()方法直接獲取的,並沒有傳遞什麼引數

這裡大機率可以判定為sql語句可控,當然也不一定,需要看一下getPara()方法是怎麼實現的:

點選進入看一下,發現是透過request.getParameter(name)直接獲取的引數內容!

這個時候可以斷定,這裡99.9%存在sql注入,因為整個sql語句可控。

12)尋找對應的前端功能

既然得知,SystemGenerateController類的create()方法可以觸發該sql執行,那麼找一下前端哪個功能可以觸發該方法,這裡需要根據前面所說的路由機制來判斷。

可以看到類名上存在一個@Action(path = "/system/generate")註解,並且方法名是create,並且該類在admin目錄下

因此,可以推斷出,前端請求的路徑是/admin/system/generate/create.json

那麼接下來去前端搜尋一下:

  • 注意點1:搜尋的時候不要搜全,因為路徑可能是拼接出來的
  • 注意點2:這些路徑大部分都是在js檔案中,所以直接搜不一定搜出來,因為有些js檔案可能沒載入呢,所以搜尋的時候,需要不斷的點選不同功能來獲取到不同的js檔案(這裡可以根據路徑判斷大體的功能點)。

當我們點選到“程式碼生成”-“新建”的時候,出現了我們搜尋的路徑(真費時呀)。

再透過引數名,可以再進一步驗證該功能是正確的,如下圖:都為sql引數名。

2.13. 13)驗證漏洞

接下來,根據這個功能可以驗證該漏洞了。

但是這個功能是用來建立表的,透過原始碼,我們可以得出可以使用的sql指令是update。

既然只能使用update,那這裡我的思路大概就是:報錯注入

那麼接下來試一下,報錯注入,使用update報錯注入需要知道表名和列名,那我們可以去資料庫看一下~(注意:這裡是程式碼審計,不是黑盒,所以是可以得到資料庫資訊的)

那就隨機找個表名欄位名~

構造報錯注入語句:

update of_cms_field set is_disabled=updatexml(1,concat(0x5e,database(),0x5e),3) where field_id=2

點選新增,成功執行!

2.14. 14)繼續尋找其他sql語句可控的位置

好吧,找了其他的方法對應的呼叫,發現,不是sql語句固定,就是語句透過預編譯,沒有完全可控的sql語句了。ok,sql注入的程式碼審計到此結束。

相關文章