1. 程式人生 > >Sqlmap命令列引數解析(一)

Sqlmap命令列引數解析(一)

前言

本文轉載自werner-wiki的部落格,便於參考學習(侵權刪)原文地址:https://blog.csdn.net/wn314/article/details/78872828。

一、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時,進入到“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
  • 1
  • 2

(2).當資料庫管理系統是SQLite、Microsoft Access或Firebird等時格式為:

  DBMS://DATABASE_FILEPATH
  • 1
  • 2

我用如下命令連線裝在本機上的Mysql:

  python sqlmap.py -d "mysql://root:[email protected]:3306/DISSchool"
  • 1
  • 2

卻出現了錯誤,錯誤為:

  [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
  • 1
  • 2

意思是我沒有安裝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
  • 1
  • 2
  • 3
  • 4

安裝好python-pymysql後再執行命令:

  python sqlmap.py -d "mysql://root:[email protected]:3306/DISSchool"
  • 1
  • 2

這次沒有報錯,成功的連線到了資料庫。只是除了檢測資料庫確實是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"
  • 1
  • 2

3.從Burp或WebScarab的代理日誌中解析目標

引數:-l

使用引數“-l”指定一個Burp或WebScarab的代理日誌檔案,Sqlmap將從日誌檔案中解析出可能的攻擊目標,並逐個嘗試進行注入。該引數後跟一個表示日誌檔案的路徑。

WebScarab我沒有用過,Burp倒是常常會用。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
  ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

可以看到該日誌檔案不僅記錄了GET引數,還記錄了cookie和POST引數。現在使用如下命令讓Sqlmap解析該日誌檔案,自動尋找目標,檢測注入漏洞:

  python sqlmap.py -l ../proxy.log
  • 1
  • 2

注意日誌檔案的路徑要寫正確。執行該命令時,每找到一個可能的攻擊目標,Sqlmap都會詢問是否要檢測該目標。,預設回答為“Y”,想要測試該目標,直接按回車鍵就行。

當日志較大時會有很多可能目標,雖然有詢問機制但依舊麻煩,因為不能一路按回車而要進行判斷。若是可以對日誌進行過濾就好了!確實是可以的,引數為“–scope”,詳情見“五.18”。

4.從站點地圖檔案中解析目標

引數:-x

為便於搜尋引擎收錄,許多網站專門為搜尋引擎生成了xml格式的站點地圖,如百度Sitemap支援xml格式。Sqlmap可以直接解析xml格式的站點地圖,從中提取攻擊目標,對一個網站全方位無死角地進行注入檢測,此時使用的引數是“-x”,如:

  python sqlmap.py -x http://www.6eat.com/sitemap.xml
  • 1
  • 2

但執行該命令的結果卻是:

  [WARNING] no usable links found (with GET parameters)
  • 1
  • 2

沒有找到有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*
  • 1
  • 2
  • 3

然後可用使用如下命令讓Sqlmap測試這些URL是否存在注入漏洞:

  python sqlmap.py -m url.txt
  • 1
  • 2

同樣,執行該命令時,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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

則使用如下命令讓Sqlmap解析該檔案,以該檔案中HTTP請求目標為攻擊目標進行測試:

  python sqlmap.py -r get.txt
  • 1
  • 2

7.將Google搜尋結果作為攻擊目標

引數:-g

Sqlmap能自動獲取Google搜尋的前一百個結果,對其中有GET引數的URL進行注入測試。當然,所處的網路環境要能訪問Google才行。下面是Sqlmap手冊中“-g”引數的例子:

  python sqlmap.py -g "inurl:\".php?id=1\""
  • 1
  • 2

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"
  • 1
  • 2

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=";"
  • 1
  • 2

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;"
  • 1
  • 2

與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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

5.User-Agent

引數:–user-agent和–random-agent

預設情況下Sqlmap傳送的HTTP請求中的User-Agent值為:

  sqlmap/1.0-dev-xxxxxxx (http://sqlmap.org)
  • 1
  • 2

使用引數“–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
  • 1
  • 2

結果為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"
  • 1
  • 2

傳送的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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

加引數“-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"
  • 1
  • 2

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
  • 1
  • 2

如果要求高度的匿名性可以使用引數“–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)"
  • 1
  • 2

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()"
  • 1
  • 2

每次返送請求前,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"
  • 1
  • 2

如果不想測試某一引數則可以使用“–skip”。如設定了level為5但不想測試User-Agent和Referer,則可以這麼寫:

  --level=5 --skip="user-agent,referer"
  • 1
  • 2

有時會遇到偽靜態網頁。動態網頁會明目張膽地列出引數,如:

  /user.php?id=1
  • 1
  • 2

顯然引數是id,值為1。但若是偽靜態網頁則可能這樣寫:

  /user/1/
  • 1
  • 2

將引數隱藏在URL中。通常情況下Sqlmap不會對這樣的偽靜態網頁的引數做測試,因為Sqlmap無法判斷哪個是引數。若想要對這樣的偽靜態進行測試,只需要加上“*”,告訴Sqlmap哪個是偽靜態引數就行,剩下事的和GET引數沒有什麼區別。如:

  python sqlmap.py -u "http(s)://target.cc/user/1*/"
  • 1
  • 2

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>
  • 1
  • 2
  • 3

對於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";
  • 1
  • 2

對這樣的例子可以讓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"
  • 1
  • 2

最終SQL語句會變成:

  SELECT * FROM users WHERE id=('1') <PAYLOAD> AND ('abc'='abc') LIMIT 0, 1
  • 1
  • 2

這個句子語法是正確的,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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

下面是一個示例,該示例的目標是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
  • 1
  • 2
  • 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
  [...]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

而若不加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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

八、檢測

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在上例中可以看到有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”,預設情況下聯合查詢注入中使用的