零、前言
這篇文章是學習Sqlmap的用法時做的筆記,記錄了Sqlmap的常見、基礎用法。
一、Sqlmap是什麼
Sqlmap是開源的自動化SQL隱碼攻擊工具,由Python寫成,具有如下特點:
- 完全支援MySQL、Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access、IBM DB2、SQLite、Firebird、Sybase、SAP MaxDB、HSQLDB和Informix等多種資料庫管理系統。
- 完全支援布林型盲注、時間型盲注、基於錯誤資訊的注入、聯合查詢注入和堆查詢注入。
- 在資料庫證照、IP地址、埠和資料庫名等條件允許的情況下支援不通過SQL隱碼攻擊點而直接連線資料庫。
- 支援列舉使用者、密碼、雜湊、許可權、角色、資料庫、資料表和列。
- 支援自動識別密碼雜湊格式並通過字典破解密碼雜湊。
- 支援完全地下載某個資料庫中的某個表,也可以只下載某個表中的某幾列,甚至只下載某一列中的部分資料,這完全取決於使用者的選擇。
- 支援在資料庫管理系統中搜尋指定的資料庫名、表名或列名
- 當資料庫管理系統是MySQL、PostgreSQL或Microsoft SQL Server時支援下載或上傳檔案。
- 當資料庫管理系統是MySQL、PostgreSQL或Microsoft SQL Server時支援執行任意命令並回現標準輸出。
二、安裝Sqlmap
Sqlmap的開源專案,託管在github,最簡單的安裝方式便是使用git,執行如下命令:
git clone https://github.com/sqlmapproject/sqlmap.git
片刻後命令執行完畢,可以看到當前目錄中多了一個名為“sqlmap”的目錄, 該目錄中儲存著Sqlmap的Python原始碼、配置檔案和文件。 由於Python是解釋執行的語言,不用編譯,所以至此最新版的Sqlmap已經安裝完成。 cd到“sqlmap”目錄中,用命令“python sqlmap”啟動Sqlmap,如下圖所示:
當想要更新Sqlmap時,進入到“sqlmap”目錄中執行命令“git pull”即可。
三、輸出級別(Output verbosity)
引數:-v
Sqlmap的輸出資訊按從簡到繁共分為7個級別(和葫蘆娃一樣多),依次為0、1、2、3、4、5和6。使用引數“-v <級別>”來指定某個等級,如使用引數“-v 6”來指定輸出級別為6。預設輸出級別為1。各個輸出級別的描述如下:
- 0:只顯示Python的tracebacks資訊、錯誤資訊[ERROR]和關鍵資訊[CRITICAL];
- 1:同時顯示普通訊息[INFO]和警告資訊[WARNING];
- 2:同時顯示除錯資訊[DEBUG];
- 3:同時顯示注入使用的攻擊荷載;
- 4:同時顯示HTTP請求;
- 5:同時顯示HTTP響應頭;
- 6:同時顯示HTTP響應體。
各個級別輸出的資訊詳細到什麼程度,還需要自己嘗試下,親眼見到,才會有明確的認識。
四、指定目標
Sqlmap執行時必須指定至少一個目標,支援一次指定多個目標。有以下幾種指定目標的方式:
1.直接連線資料庫
引數:-d
使用引數“-d”直接連線資料庫,該引數後跟一個表示資料庫的字串,該字串有以下兩種格式:
(1).當資料庫管理系統是MySQL、Oracle、Microsoft SQL Server或PostgreSQL等時格式為:
DBMS://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME
(2).當資料庫管理系統是SQLite、Microsoft Access或Firebird等時格式為:
DBMS://DATABASE_FILEPATH
我用如下命令連線裝在本機上的Mysql:
python sqlmap.py -d "mysql://root:root@127.0.0.1:3306/DISSchool"
卻出現了錯誤,錯誤為:
[CRITICAL] sqlmap requires 'python-pymysql' third-party library in order to directly connect to the DBMS 'MySQL'. You can download it from 'https://github.com/petehunt/PyMySQL/'. Alternative is to use a package 'python-sqlalchemy' with support for dialect 'mysql' installed
意思是我沒有安裝Python連線Mysql用的第三方庫python-pymysql。雖然我安裝了python-mysqldb可以使Python連線Mysql,但顯然Sqlmap使用的是python-pymysql而不是python-mysqldb。使用如下命令安裝python-pymysql:
git clone https://github.com/petehunt/PyMySQL/
cd PyMySQL/
sudo python setup.py install
安裝好python-pymysql後再執行命令:
python sqlmap.py -d "mysql://root:root@127.0.0.1:3306/DISSchool"
這次沒有報錯,成功的連線到了資料庫。只是除了檢測資料庫確實是Mysql版本號大於等於5.0.0之外便什麼都沒有做。讓Sqlmap做點什麼需要用其他引數指定,這些引數我們稍晚些再學習。
2.指定目標URL
引數:-u 或 --url
使用引數“-u”或“--url”指定一個URL作為目標,該引數後跟一個表示URL的字串,可以是http協議也可以是https協議,還可以指定埠,如:
python sqlmap.py -u "http://192.168.56.102:8080/user.php?id=0"
3.從Burp或WebScarab的代理日誌中解析目標
引數:-l
使用引數“-l”指定一個Burp或WebScarab的代理日誌檔案,Sqlmap將從日誌檔案中解析出可能的攻擊目標,並逐個嘗試進行注入。該引數後跟一個表示日誌檔案的路徑。
WebScarab我沒有用過,Burp倒是常常會用。Burp預設不記錄日誌,想要記錄日誌需要手動開啟,設定方法如下圖所示:
只用勾選代理中的請求資料就足夠了,日誌檔案路徑可隨意設定,這裡我設定日誌檔名為proxy.log,放在使用者主目錄中。
設定瀏覽器的代理為Burp,隨便瀏覽幾個網頁後發現proxy.log竟然已經有70多K大,檢視其內容,部分輸出如下:
werner@Yasser:~$ more proxy.log
======================================================
7:22:52 PM http://ocsp.digicert.com:80 [117.18.237.29]
======================================================
POST / HTTP/1.1
Host: ocsp.digicert.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-SG,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Length: 83
Content-Type: application/ocsp-request
DNT: 1
Connection: close
0Q0O0M0K0I0 +
�ǝ��Pr�Tz�
======================================================
======================================================
7:23:00 PM http://blog.csdn.net:80 [47.95.49.160]
======================================================
GET /pyufftj/article/details/21469201 HTTP/1.1
Host: blog.csdn.net
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
...
可以看到該日誌檔案不僅記錄了GET引數,還記錄了cookie和POST引數。現在使用如下命令讓Sqlmap解析該日誌檔案,自動尋找目標,檢測注入漏洞:
python sqlmap.py -l ../proxy.log
注意日誌檔案的路徑要寫正確。執行該命令時,每找到一個可能的攻擊目標,Sqlmap都會詢問是否要檢測該目標。,預設回答為“Y”,想要測試該目標,直接按Enter鍵就行。
當日志較大時會有很多可能目標,雖然有詢問機制但依舊麻煩,因為不能一路按回車而要進行判斷。若是可以對日誌進行過濾就好了!確實是可以的,引數為“--scope”,詳情見“五.18”。
4.從站點地圖檔案中解析目標
引數:-x
為便於搜尋引擎收錄,許多網站專門為搜尋引擎生成了xml格式的站點地圖,如[百度Sitemap支援xml格式][Sitemap_xml]。Sqlmap可以直接解析xml格式的站點地圖,從中提取攻擊目標,對一個網站全方位無死角地進行注入檢測,此時使用的引數是“-x”,如:
python sqlmap.py -x http://www.6eat.com/sitemap.xml
但執行該命令的結果卻是:
[WARNING] no usable links found (with GET parameters)
沒有找到有GET引數的可用連結。就我有限的經驗而言,站點地圖中的URL很少包含GET引數,POST引數就更不用說了。所以Sqlmap的這一功能似乎有些雞肋。
5.從文字檔案中解析目標
引數:-m
引數“-u”一次只能指定一個URL,若有多個URL需要測試就顯得很不方便,我們可用將多個URL以一行一個的格式儲存在文字檔案中,然後使用引數“-m”,後跟該文字檔案路徑,讓Sqlmap依次讀取檔案中的URL作為攻擊目標。
如我們有檔案url.txt,內容為:
www.target1.com/vuln1.php?q=foobar
www.target2.com/vuln2.asp?id=1
www.target3.com/vuln3/id/1*
然後可用使用如下命令讓Sqlmap測試這些URL是否存在注入漏洞:
python sqlmap.py -m url.txt
同樣,執行該命令時,Sqlmap會很貼心地一個個詢問:“do you want to test this URL?”
6.從檔案載入HTTP請求
引數:-r
可以將一個HTTP請求儲存在檔案中,然後使用引數“-r”載入該檔案,Sqlmap會解析該檔案,從該檔案分析目標並進行測試。
設有如下所示的HTTP請求儲存在檔案get.txt中:
GET /user.php?id=1 HTTP/1.1
Host: 192.168.56.101:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-SG,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
則使用如下命令讓Sqlmap解析該檔案,以該檔案中HTTP請求目標為攻擊目標進行測試:
python sqlmap.py -r get.txt
7.將Google搜尋結果作為攻擊目標
引數:-g
Sqlmap能自動獲取Google搜尋的前一百個結果,對其中有GET引數的URL進行注入測試。當然,所處的網路環境要能訪問Google才行。下面是Sqlmap手冊中“-g”引數的例子:
python sqlmap.py -g "inurl:\".php?id=1\""
8.從配置檔案中載入攻擊目標
引數:-c
使用引數“-c”指定一個配置檔案(如:sqlmap.conf),Sqlmap會解析該配置檔案,按照該配置檔案的配置執行動作。配置檔案中可以指定攻擊目標,實際上除了攻擊目標外,配置檔案還可以指定各種引數的值。
Sqlmap的按照目錄中有一個名為sqlmap.conf的檔案,該檔案是配置檔案的模板,看看該檔案內容,就能明白配置檔案是什麼意思了。
五、請求
HTTP是一個複雜的協議。HTTP請求有很多種方法(method),可以在不同位置(GET、POST、cookie和User-Agent等)攜帶不同引數。往往只有在特定位置攜帶了特定引數以特定方法發起的請求才是合法有效的請求。Sqlmap執行時除了需要指定目標,有時還需要指定HTTP請求的一些細節。下面這些引數都用於指定HTTP請求細節。
1.HTTP方法
引數:--method
一般來說,Sqlmap能自動判斷出是使用GET方法還是POST方法,但在某些情況下需要的可能是PUT等很少見的方法,此時就需要用引數“--method”來指定方法。如:“--method=PUT”。
2.POST資料
引數:--data
該引數指定的資料會被作為POST資料提交,Sqlmap也會檢測該引數指定資料是否存在注入漏洞。如:
python sqlmap.py -u "http://192.168.56.102:8080/user.php" --data="id=0&name=werner"
3.指定分隔符
引數:--param-del
上一個例子中“--data”的資料“id=0&name=werner”其實由兩個部分組成:“id=0”和“name=werner”,預設地以“&”作為分隔符。我們可以使用“--param-del”來指定分隔符,如:
python sqlmap.py -u "http://192.168.56.102:8080/user.php" --data="id=0;name=werner" --param-del=";"
4.cookie
引數:--cookie、--cookie-del、--drop-set-cookie和--load-cookies
有兩種情況會用到這些引數:
- 要測試的頁面只有在登入狀態下才能訪問,登入狀態用cookie識別
- 想要檢測是否存在cookie注入
當“--level”設定為2或更高時,Sqlmap會檢測cookie是否存在注入漏洞,關於“--level”的更多資訊見下文。
(1).“--cookie”和“--cookie-del”
在瀏覽器中登入目標網站後複製出維持登入狀態的cookie,用引數“--cookie”來指定這些cookie,如:
python sqlmap.py -u "http://192.168.56.102:8080/user.php" --cookie "JSESSIONID=E5D6C8C81;NAME=werner;"
與POST引數不同,cookie預設的分隔符為“;”,想要指定cookie中的分隔符,使用引數“--cookie-del”。
(2).“--drop-set-cookie”
若HTTP響應頭中有“Set-Cookie”,Sqlmap會自動設定“Set-Cookie”設定的cookie,並對這些cookie進行檢測。若不想讓Sqlmap這麼做,新增引數“--drop-set-cookie”即可,這樣,Sqlmap會忽略“Set-Cookie”。
(3).“--load-cookies”
該引數用於從檔案中載入Netscape或wget格式的cookie。
wget可以儲存和載入cookie,示例如下:
# Log in to the server. This can be done only once.
wget --save-cookies cookies.txt \
--post-data 'user=foo&password=bar' \
http://server.com/auth.php
# Now grab the page or pages we care about.
wget --load-cookies cookies.txt \
-p http://server.com/interesting/article.php
5.User-Agent
引數:--user-agent和--random-agent
預設情況下Sqlmap傳送的HTTP請求中的User-Agent值為:
sqlmap/1.0-dev-xxxxxxx (http://sqlmap.org)
使用引數“--user-agent”可以指定一個User-Agent值。但正常的User-Agent值長什麼樣我們可能並不記得,所以有了引數“--random-agent”,使用該引數,Sqlmap會從檔案./txt/user-agents.txt中隨機地取一個User-Agent。注意,在一次會話中只有使用同一個User-Agent,並不是每發一個HTTP請求包,都隨機一個User-Agent。
用如下命令統計user-agents.txt行數:
cat sqlmap/txt/user-agents.txt | wc -l
結果為4211,當然其中還包含空行、註釋等,但總的來說該檔案中儲存的User-Agent也有4千多個。
當“--level”設定為3或更高時,Sqlmap會檢測User-Agent是否存在注入漏洞,關於“--level”的更多資訊見下文。
6.Host
引數:--host
使用該引數可以手動指定HTTP頭中的Host值。
當“--level”設定為5或更高時,Sqlmap會檢測Host是否存在注入漏洞,關於“--level”的更多資訊見下文。
7.Referer
引數:--referer
使用該引數可以指定HTTP頭中的Referer值。Sqlmap傳送的HTTP請求頭部預設無Referer欄位。
當“--level”設定為3或更高時,Sqlmap會檢測Referer是否存在注入漏洞,關於“--level”的更多資訊見下文。
8.額外的HTTP頭
引數:--headers
使用該引數可以在Sqlmap傳送的HTTP請求報文頭部新增欄位,若新增多個欄位,用“\n”分隔。如命令:
python sqlmap.py -u "http://192.168.56.101:8080/" -v 5 --headers "X-A:A\nX-B: B"
傳送的HTTP請求包為:
GET / HTTP/1.1
X-B: B
Host: 192.168.56.101:8080
Accept-encoding: gzip,deflate
X-A: A
Accept: */*
User-agent: sqlmap/1.1.10#stable (http://sqlmap.org)
Connection: close
加引數“-v 5”是為了讓Sqlamp輸出傳送的HTTP請求包,便於我們觀察。
9.身份認證
引數:--auth-type和--auth-cred
這些引數用於進行身份認證。“--auth-type”用於指定認證方式,支援以下三種身份認證方式:
- Basic
- Digest
- NTLM
“--auth-cred”用於給出身份認證的憑證,格式是“username:password”。
如:
python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/basic/get_int.php?id=1" --auth-type Basic --auth-cred "testuser:testpass"
10.基於證照的身份認證
引數:--auth-file
若Web伺服器要求客戶端提供證照則可以使用此引數指定一個PEM格式的證照檔案。我們知道SSL協議的客戶端認證是可選的,實踐中一般都只用伺服器端提供自己的證照供客戶端驗證,很少要求客戶端提供自己的證照。
11.忽略401
引數:--ignore-401
使用該引數忽略401錯誤(未認證)。
12.HTTP(S)代理
引數:--proxy、--proxy-cred、--proxy-file和--ignore-proxy
使用引數“--proxy”來設定一個HTTP(S)代理,格式是“http(s)?/url:port”。若代理需要認證,使用引數“--proxy-cred”來提供認證憑證,格式是“username:password”。
使用引數“--proxy-file”指定一個儲存著代理列表的檔案,Sqlmap會依次使用檔案中的代理,當某個代理有任何連線問題時就會被棄用而換下一個代理。
使用引數“--ignore-proxy”忽略本地代理設定。
13.Tor匿名網路
引數:--tor、--tor-type、--tor-port和--check-tor
不管出於什麼原因,如果想要保持匿名狀態與其使用單個的HTTP(S)代理,不如安裝類似Privoxy這樣的軟體按照[Tor的安裝指導][Tor]配置一個Tor客戶端。設定好後使用引數“--tor”讓Sqlmap自動設定使用Tor代理。
如果想要手動指定Tor的型別和埠可以使用引數“--tor-type”和“--tor-port”,如:
--tor-type=SOCKS5 --tor-port 9050
如果要求高度的匿名性可以使用引數“--check-tor”,加上該引數後Sqlmap會確保所有流量都走Tor代理,若Tor代理失效,Sqlmap會發出警告並退出。檢測方法是訪問[Are you using Tor?][Are you using Tor]。
14.HTTP請求之間新增延遲
引數:--delay
過於頻繁地傳送請求可能會被網站察覺或有其他不良後果。使用引數“--delay”來指定HTTP請求之間的延遲,單位為秒,型別是浮點數,如“--delay 1.5”表示延遲1.5秒。預設是沒有延遲的。
15.超時
引數:--timeout
超時時間預設為30秒,可以用引數“--timeout”指定超時時間,如“--timeout 44.5”表示設定超時時間為44.5秒。
16.超時後最大重試次數
引數:--retries
超時後Sqlmap會進行重試,最大重試次數預設為3,可以用引數“--retries”指定最大重試次數。
17.隨機化引數值
引數:--randomize
使用該引數,Sqlmap會隨機生成每次HTTP請求中引數的值,值的型別和長度依照於原始值。
18.用正規表示式過濾代理日誌
引數:--scope
指定一個Python正規表示式對代理日誌進行過濾,只測試符合正規表示式的目標,如:
python sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"
19.避免錯誤請求過多而被遮蔽
引數:--safe-url、--safe-post、--safe-req和--safe-freq
有時伺服器檢測到某個客戶端錯誤請求過多會對其進行遮蔽,而Sqlmap的測試往往會產生大量錯誤請求,為避免被遮蔽,可以時不時的產生幾個正常請求以迷惑伺服器。有以下四個引數與這一機制有關:
- --safe-url: 隔一會就訪問一下的安全URL
- --safe-post: 訪問安全URL時攜帶的POST資料
- --safe-req: 從檔案中載入安全HTTP請求
- --safe-freq: 每次測試請求之後都會訪問一下的安全URL
這裡所謂的安全URL是指訪問會返回200、沒有任何報錯的URL。相應地,Sqlmap也不會對安全URL進行任何注入測試。
20.關閉URL編碼
引數:--skip-urlencode
Sqlmap預設會對URL進行URL編碼,可以使用該引數關閉URL編碼。
21.繞過CSRF保護
引數:--csrf-token和--csrf-url
現在有很多網站通過在表單中新增值為隨機生成的token的隱藏欄位來防止CSRF攻擊,Sqlmap會自動識別出這種保護方式並繞過。但自動識別有可能失效,此時就要用到這兩個引數。
“--csrf-token”用於指定包含token的隱藏欄位名,若這個欄位名不是常見的防止CSRF攻擊的欄位名Sqlmap可能不能自動識別出,需要手動指定。如Django中該欄位名為“csrfmiddlewaretoken”,明顯與CSRF攻擊有關。
“--csrf-url”用於從任意的URL中回收token值。若最初有漏洞的目標URL中沒有包含token值而又要求在其他地址提取token值時該引數就很有用。
22.強制使用SSL
引數:--force-ssl
23.在每次請求前執行特定Python程式碼
引數:--eval
直接看例子:
python sqlmap.py -u "http://www.target.com/vuln.php?id=1&hash=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib;hash=hashlib.md5(id).hexdigest()"
每次返送請求前,Sqlmap都會依據id值重新計算hash值並更新GET請求中的hash值