本文章主要涉及group by報錯注入的原理講解,如有錯誤,望指出。(附有目錄,如需查看請點右下角)一、下圖為本次文章所使用到 user表,該表所在的數據庫為 test二、首先介紹一下本文章所使用的到的語法:(第5、6條必須看,這涉及到之后的原理講解)1、group by語句:用于結合合計函數,根據一個或多個列對結果集進行分組。如下圖: 2、rand()函數:用于產生一個0-1之間的隨機數:如下圖: 注意: 3、floor()函數:向下取整:如下圖: 4、count()函數:返回指定列的值的數目(NULL 不計入),count(*):返回表中的記錄數如下圖 5、floor(rand()*2):rand()*2 函數生成 0-2之間的數,使用floor()函數向下取整,得到的值就是【不固定】的 “0” 或 “1”如下圖: 6、floor(rand(0)*2):rand(0)*2 函數生成 0-2之間的數,使用floor()函數向下取整,但是得到的值【前6位(包括第六位)是固定的】。(為:011011)如下圖: 三、接下來我們開始講解group by進行分組的原理:(如果你覺得已經理解了該原理請直接轉:四)首先讓我們思考一下下面三個sql語句,從中我們可以得知什么:
運行結果如下: 結論:我們發(fā)現group by后面的參數可以是一個column_name(字段名),可以是一個字符串(或返回值為字符串的函數),不可以是不完整的column_name。這時你們可能會想,參數是column_name我倒是可以理解是怎么分組的,但是參數是 字符串 是怎么回事?username字段的值中沒有"username"啊?只有"admin","chen"兩個,結果怎么會是 7 呢?讓我們接著往下看。 原因:上面sql語句的分組原理(雖然是我的推測,但是這樣說明的確可以解釋的通):1、如果參數是 column_name,即 username,不是字符串("username")。語句執(zhí)行的時候會建立一個虛擬表(里面有兩個字段,分別是 key 主鍵,count(*)),如果參數是 column_name,系統便會在 user 表中【 依次查詢 [相應的] 字段的值(即:參數指明的字段中的值) 】,取username字段第一個值為 admin,這時會在虛擬表的 主鍵key 中查找 admin 這個字符串,如果存在,就使 count(*) 的值加 1 ;如果不存在就將 admin 這個字符串插入到 主鍵key 字段中,并且使 count(*) 變?yōu)?1;接著取username字段第二個值也為 admin ,查找虛擬表中的 主鍵key 中已經存在 admin 字符串,就直接將 count(*) 加 1;…… …… ……;到username字段第四個值為 chen 時,查找虛擬表中的 主鍵key 字段不存在 chen 這個值,此時就將 chen 這個字符串再次插入到 主鍵key 字段中,并且使 count(*) 變?yōu)?1,就這樣一直執(zhí)行下去,直到所有的字段值分組完畢。之后系統就按照虛擬表中的結果將其顯示出來。 取完username字段第四個值(即:chen)時的 虛擬表 ,如下圖: 2、如果參數是字符串:"username",而不是字段名:語句執(zhí)行的時候仍會建立一個虛擬表(里面有兩個字段,分別是 key 主鍵,count(*)),如果參數是字符串 "username",那系統就不會去取user表中的字段值了,而是直接取字符串:"username"作為值,然后查找比對虛擬表中 key 字段的值,發(fā)現沒有字符串 "username",便插入 "username" 這個字符串,并將count(*) 變?yōu)?;然后執(zhí)行第二次,在虛擬表 key 字段中查找 "username" 這個字符串,發(fā)現有,便使 count(*) 加 1,就這樣執(zhí)行 7 次,count(*)便變成了 7。 四、理解完上面之后,讓我們進入正題,請看下兩條的sql group by報錯注入語句,以及其運行結果:
可以看到,user表所在的 test 數據庫被成功的爆了出來。但是你們仔細觀察的話會發(fā)現第二個sql語句爆率并不是100%,有時會爆不出來,為什么呢?別著急,繼續(xù)往下看: 原因:在我們已經有上面的鋪墊之后其實要理解這個sql group by報錯注入的原理已經不難了:以第一條語句為例:select count(*) from information_schema.tables group by concat(database(),floor(rand(0)*2));
報錯的過程:
由以上過程發(fā)現,總共取了三條記錄(所以表中的記錄數至少為三條),floor(rand(0)*2)執(zhí)行了五次。 五、總結現在,解釋了group by報錯注入的原理,想必大家已經知道為什么:
沒錯是因為floor(rand()*2)的前幾位隨機數順序是不固定的,所以并不能保證一定會注入成功,但是其只需兩條記錄數就行了(因為它可能會產出 “0101” ,這樣只需兩條記錄就可以成功注入,你可以試試推導一下),這也算是它的優(yōu)勢吧。 文章是博主一字一字打出來的,轉載請標明出處,謝謝! |
|