什么是SQL注入?
Web應(yīng)用程序在向后臺(tái)數(shù)據(jù)庫傳遞SQL語句查詢時(shí),如果攻擊者可以影響該查詢的能力,就會(huì)引發(fā)SQL注入!
(缺乏對(duì)用戶輸入數(shù)據(jù)的合法性檢查,傳遞的參數(shù)是可控的,則可以構(gòu)造不同的SQL語言,來實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的操控!)
SQL注入的產(chǎn)生過程
開發(fā)人員在運(yùn)行程序過程中,動(dòng)態(tài)構(gòu)造SQL語句(字符串)!
轉(zhuǎn)義字符處理不當(dāng)
SQL數(shù)據(jù)庫會(huì)將單引號(hào)(')解析為代碼與數(shù)據(jù)的分界線:
輸入框輸入:tony
user_id = 'tony' // 數(shù)據(jù)(參數(shù))外面會(huì)自動(dòng)加上單引號(hào),單引號(hào)外面是運(yùn)行的代碼!
因此輸入框只要輸入('),就能判斷是不是存在SQL注入!
user_id =''' // 會(huì)提供SQL語法錯(cuò)誤!因?yàn)樗?')解析為字符串分隔符,相當(dāng)于多出來一個(gè)('),所以報(bào)錯(cuò)!
構(gòu)造自己的查詢語句:
1' and 1='1
相當(dāng)于:user_id ='1' and 1 = '1' // SQL語句可以正常執(zhí)行!(沒有語法錯(cuò)誤!)
在Oracle數(shù)據(jù)庫中,還有"空格","||",",",".","*/","""(雙引號(hào))等等具有特殊含義的轉(zhuǎn)義字符,我們可以利用其特殊含義,去拼接要執(zhí)行的SQL語句!
類型處理不當(dāng)
加入查詢的數(shù)據(jù)(參數(shù))為數(shù)字類型,開發(fā)人員不會(huì)在數(shù)字類型外面添加單引號(hào)!
比如:
user_id = 1
攻擊者在構(gòu)造SQL語句的時(shí)候,沒有必要使用單引號(hào)來轉(zhuǎn)義查詢:
user_id = 1 and 1=1
所以,攻擊者常常使用1' and 1='1和1 and 1=1來判斷查詢的字段是數(shù)字類型還是字符類型!(具體判斷,下文會(huì)提及!)
查詢語句組裝不當(dāng)
開發(fā)人員在構(gòu)造動(dòng)態(tài)SQL語言中,以表名或字段名作為查詢參數(shù),這樣的組裝容易導(dǎo)致攻擊者使用自己的表名和字段名來替換查詢,比如GET請(qǐng)求查詢,替換URL中的表名和字段名!
http://www.tony.com?table=users&column1=user&column2=password
導(dǎo)致了users表中的字段user和password的信息泄漏:
錯(cuò)誤處理不當(dāng)
開發(fā)人員將詳細(xì)的錯(cuò)誤消息顯示在頁面上!
攻擊者可以根據(jù)錯(cuò)誤消息來提取有用信息:
利用:
根據(jù)報(bào)錯(cuò)信息,不斷變化order by后面的數(shù)字,來獲取表中的字段數(shù)!
不安全的數(shù)據(jù)庫配置
保證應(yīng)用程序的代碼的安全是首要任務(wù),但也不能忽略數(shù)據(jù)庫本身的安全!
MySQL:使用root和anonymous用戶賬戶!
Oracle:默認(rèn)創(chuàng)建的數(shù)據(jù)庫 - SYS,SYSYTEM,DBSNMP,OUTLN等,并且密碼也默認(rèn)!
SQL Server:用sa作為數(shù)據(jù)庫系統(tǒng)管理員賬戶!
安裝數(shù)據(jù)庫服務(wù)時(shí),允許以root,sa,SYSTEM等特權(quán)用戶來執(zhí)行操作,一旦數(shù)據(jù)庫遭到攻擊,破壞力太大!
沒有對(duì)元數(shù)據(jù)的訪問設(shè)置權(quán)限!(元數(shù)據(jù)指數(shù)據(jù)庫系統(tǒng)內(nèi)部包含的數(shù)據(jù),比如數(shù)據(jù)庫名,表名,列名,訪問權(quán)限等信息)
尋找SQL注入點(diǎn)
(操縱用戶數(shù)據(jù)輸入并分析服務(wù)器的響應(yīng)來尋找SQL注入漏洞!)
源代碼
借助推理進(jìn)行測試(可以利用BurpSuite中的重放功能,向服務(wù)器發(fā)送不同請(qǐng)求,根據(jù)服務(wù)器的響應(yīng)來推斷!)
注意:借助推理進(jìn)行測試,最好發(fā)送一些意外請(qǐng)求,來觸發(fā)服務(wù)器異常:
識(shí)別Web應(yīng)用上的所有數(shù)據(jù)輸入(如POST、GET、Cookie等!)
哪種類型的輸入會(huì)觸發(fā)異常
檢測服務(wù)器響應(yīng)中的異常
舉例:
http://www.tony.com?name=tony // Get請(qǐng)求
確定name=tony,是select,insert,update,delete中的哪一種?
構(gòu)造:('或變化不同的參數(shù),通過不同的響應(yīng)結(jié)果來判斷!)
name=或name=tony' // 不同響應(yīng),select!
name=tony或name=to' 'ny // 相同響應(yīng),很可能存在SQL注入!(兩個(gè)單引號(hào)中間是空格!)
根據(jù)不用的響應(yīng)異常,可以大概率推斷是select,并存在注入點(diǎn),這時(shí)可以拼接SQL語句來進(jìn)行攻擊!
數(shù)據(jù)庫錯(cuò)誤
用戶請(qǐng)求,觸發(fā)數(shù)據(jù)庫錯(cuò)誤時(shí),開發(fā)人員會(huì)根據(jù)應(yīng)用編碼方式的不同,作如下處理:
SQL錯(cuò)誤顯示在頁面中,對(duì)瀏覽器用戶可見!
SQL錯(cuò)誤隱藏在頁面源代碼中,便于調(diào)試!
檢測到錯(cuò)誤時(shí),跳轉(zhuǎn)到另一個(gè)頁面!
返回HTTP錯(cuò)誤碼,如500,或HTTP重定向碼302
適當(dāng)?shù)靥幚礤e(cuò)誤但不顯示結(jié)果,或者可能顯示一個(gè)統(tǒng)一的錯(cuò)誤處理頁面!
應(yīng)用程序的響應(yīng)
尋找SQL注入漏洞的過程包括識(shí)別用戶數(shù)據(jù)輸入、操縱發(fā)送給應(yīng)用的數(shù)據(jù)以及識(shí)別服務(wù)器返回結(jié)果中的變化,但操縱參數(shù)產(chǎn)生的錯(cuò)誤可能與SQL注入無關(guān)!
如:統(tǒng)一錯(cuò)誤處理頁面,根本覺察不了什么異樣!
所以,要弄清楚該錯(cuò)誤到底是不是由SQL注入引發(fā)的!
方法:
插入不觸發(fā)應(yīng)用錯(cuò)誤的SQL代碼測試!(反復(fù)訓(xùn)練和不斷嘗試的過程!)
or '1' ='1'
or '1' ='2'
HTTP代碼錯(cuò)誤
200:成功接收
500:內(nèi)部服務(wù)器錯(cuò)誤
302:當(dāng)發(fā)現(xiàn)錯(cuò)誤時(shí),重定向到首頁或自定義錯(cuò)誤頁面!
(意味著,我們已經(jīng)以某種方式干預(yù)了應(yīng)用的正常行為!)
不同大小的響應(yīng)(通過BP很容易捕獲到!)
注意:SQL盲注常利用這個(gè)錯(cuò)誤!
SQL盲注
Web應(yīng)用訪問數(shù)據(jù)庫,會(huì)把結(jié)果呈現(xiàn)給用戶!
攻擊者修改SQL語句,通過響應(yīng)來獲取數(shù)據(jù)庫中的任意信息!
(需要發(fā)送多次請(qǐng)求,建議在BP中操作,修改參數(shù),重放請(qǐng)求!)
修改參數(shù)需要注意:
id=1+1
+:在URI中時(shí)保留字,不能直接使用,需要進(jìn)行URL編碼!
%2B=+號(hào)的URL編碼!
id=1%2B1 // 對(duì)id=1+1進(jìn)行了URL編碼!
確認(rèn)SQL注入
構(gòu)造一條有效SQL語句來確認(rèn)SQL注入漏洞!
(執(zhí)行的這條SQL語句,不會(huì)引發(fā)任何錯(cuò)誤!)
區(qū)分?jǐn)?shù)字還是字符串
數(shù)據(jù)庫有不同的數(shù)據(jù)類型,用于不同的表示方式:
數(shù)字型(不要使用單引號(hào))
字符型(需要使用單引號(hào))
如何判斷?
數(shù)字型:
輸入單引號(hào)('),返回不正常!
輸入 and 1=1,正常返回!
輸入 and 1=2,不正常返回!
(具體有沒有數(shù)字型注入,是否能夠通過數(shù)字型注入獲取有效的信息,還需要大量的測試來驗(yàn)證。
字符型:
輸入單引號(hào)('),返回不正常!
輸入 ' and '1'='1,正常返回!
輸入 ' and '1'='2,不正常返回!
(具體有沒有字符型注入,是否能夠通過數(shù)字型注入獲取有效的信息,還需要大量的測試來驗(yàn)證。
SQL注入方式
這里以MySQL數(shù)據(jù)庫為例,至于其他數(shù)據(jù)庫如Oracle,SQL Server,Access,PostgreSQL等,到時(shí)候再整理吧!
MySQL前置知識(shí):
MySQL 5.0之后,MySQL默認(rèn)在數(shù)據(jù)庫中存放一個(gè)“information_schema”的數(shù)據(jù)庫,該庫中存放著這三張表:
1. SCHEMATA:存儲(chǔ)該用戶創(chuàng)建的所有數(shù)據(jù)庫的庫名,記錄庫名的字段為SCHEMATA_NAME。
2. TABLES:存儲(chǔ)該用戶創(chuàng)建的所有數(shù)據(jù)庫的庫名和表名,記錄庫名的字段為TABLE_SCHEMA,記錄表名的字段為TABLE_NAME。
3. COLUMNS:存儲(chǔ)該用戶創(chuàng)建的所有數(shù)據(jù)庫的庫名、表名、字段名。記錄庫名的字段為TABLE_SCHEMA,記錄表名的字段為TABLE_NAME,記錄字段名的字段為COLUMN_NAME。
limit:
limit m,n
m:記錄開始的位置,0代表第一條記錄
n:取n條記錄
limit 0,2:第一條記錄開始,取兩條記錄!
常用的函數(shù)和屬性:
version():查詢MySQL的版本
database():查詢數(shù)據(jù)庫名
user():查詢使用MySQL的用戶
@@datadir:查詢數(shù)據(jù)庫物理路徑
@@version:查詢MySQL的版本
MySQL的4種注釋:
1. # 我是注釋
2. -- 我是注釋 (--和我是注釋之間有空格)
3. /*我是注釋*/
以上注釋都可以放在SQL語句的任意位置中。!
4. /*!code*/ (內(nèi)聯(lián)注釋)
內(nèi)聯(lián)注釋可以用于整個(gè)SQL語句中,用來執(zhí)行SQL語句!
例如:userid=1/*! UNION*//*! SELELCT*/1,2,3,4
基本注入
聯(lián)合查詢注入(union)
利用union可以同時(shí)執(zhí)行多條SQL語句的特點(diǎn),在參數(shù)中插入惡意的SQL注入語句,同時(shí)SQL語句,來獲取額外敏感信息等操作!
分析:
select 1,2,3會(huì)生成一張臨時(shí)表,表中的字段為查詢的字段,內(nèi)容也是查詢的字段
select 1,2,3 union select 3,2,1,同樣生成一張臨時(shí)表,表中的字段為un
Tag標(biāo)簽: 字段 數(shù)據(jù)庫 查詢 SQL 錯(cuò)誤 語句 引號(hào) 數(shù)據(jù) 輸入 用戶