收下這張小貼士,填補那些年在HQL注入留下的坑
前言
SQL注入是一種大家非常熟悉的攻擊方式,目前網絡上有大量存在注入漏洞的DBMS(如MySQL,Oracle,MSSQL等)。但是缺少針對hibernate查詢語言的相關資源,以期本文能給在滲透測試時能給各位多提供一條路。
HQL查詢并不直接發送給數據庫,而是由hibernate引擎對查詢進行解析并解釋,然后將其轉換為SQL。為什么這個細節重要呢?因為有兩種錯誤消息來源,一種來自hibernate引擎,一種來自數據庫。
如果在HQL語法中發現了注入點,我們是不能直接使用平時的SQL利用方法來應對的,HQL有屬于它自己特定的語法,相對SQL而言限制更多一些,比如說HQL就沒有方法可以直接查詢未映射的表單,沒有聯合,沒有函數來創建簡單延遲,沒有系統函數。好在俄羅斯程序員在幾年前尋找到一個方法,將HQL context轉義成SQL context,進而實現直接與數據庫通信。接下來進入正題,此外各位需要注意,不同的數據庫轉義方法不盡相同,以下案例使用的是MySQL數據庫。
開胃菜:HQL轉義
最初的請求/響應信息(注意POST body中的GWT格式)
在參數后面加上單引號,在返回的響應信息中可以看到服務器拋出一個錯誤。
像是豎線(‘|’)、反斜杠(‘\’)這類特殊符號會打亂GWT結構,我們得對這些數據進行編碼。GWT格式對特殊字符的處理:
- | => !
- \ => \
在將HQL context進行轉義之前,我們還需要對涉及到的數據庫進行一些測試:
在MySQL, MSSQL, Oracle等常用數據庫中進行測試,最終選定的最后一條payload卻只能在MySQL下執行,接下來我們就將HQL context進行轉義。
將字符串\'',由HQL context轉換為MySQL context。在HQL查詢上下文中,單引號會被附加另一個單引號來進行轉義,反斜杠依舊是平常的反斜杠。這里與MySQL全然不同,MySQL使用反斜杠來轉義單引號,而不是另一個單引號。因此,當Hibernate框架解析到一個查詢語句,剛好底層使用的數據庫又是MySQL的時候,就變得十分有趣了:
Hibernate解析到的語句:
- 'orderInGroup'||'\''|| (select 1)) -- ' // as a string
加上payload之后的MySQL:
- 'orderInGroup'||'\''|| (select 1)) -- ' // string '\'', logical 'or', select query
以下截圖顯示了payload成功執行
吃完字符串轉義這口開胃菜之后,胃口不妨打開一些,從數據庫中檢索信息
正餐:布爾型盲注
我們這個案例中的注入點在'order by'查詢部分,由于應用無法顯示查詢的數據,這時我們就使用布爾型盲注的思路,MySQL函數updatexml就是一個非常不錯的選擇,如果它的第二個參數不是有效的XPath查詢字符串就會報錯,如果XPath查詢是正確的就不返回值。
- updatexml(xml_target,xpath_expr,new_xml)
重要的是,只會在計算完第二個參數后才會拋出錯誤(其中包含有if子句),也就是根據if判斷子句,應用確定是否返回錯誤。和SQL下的布爾值盲注思路一樣,之后通過逐個字符的提取數據即可。
獲取到的完整值:
最后解碼得到[…]PROD_SELF[…]
強烈推薦ORM2Pwn: Exploiting injections in Hibernate ORM
參考文獻
Эксплуатация инъекций в Hibernate ORM
GWT RPC data format
SQL布爾型盲注思路分析
ORM2Pwn: Exploiting injections in Hibernate ORM
HQL Injection Exploitation in MySQL
Exploiting a HQL injection
HQL for pentesters Hibernate:深入HQL學習