mysql數據庫中有兩個函數:concat和updatexml,在sql注入時經常組合使用,本文通過學習concat和updatexml函數的使用方法,結合實例來理解這種sql注入方式的原理。
concat函數是mysql的字符串連接函數,定義如下:

先來驗證下concat函數的功能:
select concat('m','y','s','q','l')
驗證結果:如定義所示,concat將字符串連接起來了

如果把SQL語句放在concat中,SQL語句會被執行么?
select concat((select last_name from users limit 0,1))
驗證結果:concat中的sql語句可以被執行(這點對后面的sql注入非常重要)

select concat(0x7e,(select user()) ,0x7e)
驗證結果:16進制也能被自動轉義(0x7e是 ~符號)

其次是updatexml函數,網上找的關於該函數的介紹:

函數功能驗證:
select updatexml(0,concat(0x7e,(select user()) ,0x7e) ,0)
驗證結果:concat執行sql注入語句,再利用updatexml的報錯信息返回sql語句執行結果。這里你可能會問,難道不能直接用updatexml執行sql語句么?我試了一下,並不能,原因可能是updatexml第二個參數必須是字符串吧,所以才需要借助返回值為字符串的concat函數。

接下來是實操:下面是一個網站的登錄請求,如果用戶名錯誤,會返回Unknown user,如果密碼錯誤會返回Invalid password.

嘗試輸入單引號,返回數據庫的報錯,並且得知表名為admins,說明存在sql注入:

先用concat來注入,發現還是返回Unknown user,沒有得到其他有用的信息:

再結合updatexml,在報錯信息中返回了數據庫用戶root@localhost,看到這里,咱們應該更深入的理解了updatexml和concat注入的原理了吧:利用concat執行sql注入語句,再利用updatexml的報錯信息將sql語句的執行結果返回:

這里還有一個疑問:用concat+updatexml注入的時候,大家都會加上16進制的連接符(這里是0x7e,用其他16進制符號也可以的),為什么呢?如果不加呢?
不加的話返回內容可能會被吃掉部分,據說這是updatexml這個函數的特性。。。,如下:

接下來看下admins表中有哪些字段:

最后根據id依次查詢admins表中的用戶名和密碼

針對這個登錄頁面,其實有更好的sql注入方法,那就是萬能密碼^_^,使用萬能密碼不需要知道用戶名和密碼也能登錄,如下:

那updatexml還留着干嘛呢?萬能密碼登錄進去后不一定是admin權限,使用updatexml能拿到更多數據庫信息~
除了select,還可以利用updatexml完成insert,update和delete注入,原理和select相同。如下:
insert into guestbook(comment_id,comment,name) values (2,'0livia' or updatexml(1,concat(0x7e,(version())),0) or'','Nervo') delete from guestbook where comment_id=2 or updatexml(2,concat(0x7e,(database())),0)
一點點感悟:
1. 還是之前說過的:一定要對輸入進行過濾,一定要攔截和處理數據庫的異常和報錯!!!
2. concat和updatexml的組合方式只是一種思路,對於其他類型的數據庫,只要找到與這兩個函數功能類似的函數就可以了!
如需轉載,請注明出處,這是對他人勞動成果的尊重~
