CTF比赛中如何绕过过滤机制?
CTF论剑场-SQL注入~~~
在CTF夺旗赛的Web安全赛道上,你经常会遇到一些“不讲武德”的题目。它们明晃晃地告诉你这里有个洞,但当你兴冲冲地掏出经典的union select时,页面却只回给你一个冰冷的“非法字符”或者干脆一片空白。这种时刻,真正的较量才刚开始——这不是单纯的知识测试,而是一场与出题人过滤逻辑的正面博弈。
过滤的本质:一场规则定义的攻防
所谓过滤机制,说白了就是出题人在后端用代码设置的一道道“安检门”。常见的初级过滤包括对特定关键词(如and, or, select, union, sleep)的直接字符串匹配和替换,甚至直接拦截。高级一些的,可能会用正则表达式、WAF(Web应用防火墙)规则,或者对输入进行编码校验。理解这道“安检门”的运作规则,是绕过去的第一步。
试探:摸清安检门的脾气
盲目尝试是大忌。你得像个侦探,用最轻微的动作去试探系统的反应。比如,提交一个单引号',看页面是否报错或回显异常,这能判断是否存在注入点以及如何闭合。接着,尝试and 1=1和and 1=2,观察页面内容是否不同,这是经典的布尔盲注判断法。如果返回“非法”,就说明and被盯上了。
经典绕过技巧:化整为零与借尸还魂
当发现关键词被过滤,老手们工具箱里的第一件武器往往是双写绕过。这招专门对付那种简单粗暴的字符串替换。比如,过滤脚本可能这样写:$input = str_replace("select", "", $input);。它会把“select”替换为空。那好,我们输入“selselectect”,当中间的“select”被删掉后,两边的残骸正好拼成一个新的“select”。原文案例中的“ununionion”和“seleselectct”正是此法的典型应用。
另一件利器是大小写混淆。如果过滤是大小写敏感的(很多简单匹配都是),那么SeLeCt、UNiOn就能轻松溜过去。更隐蔽的,是利用等价替换和注释符分割。例如,在MySQL中,and可以用&&替代,or可以用||;空格可以用/**/(内联注释)、+、%0a(换行符)或%09(制表符)来绕过对空格的过滤。
进阶:当简单规则失效时
如果遇上更智能的过滤(比如正则表达式/bunionb/i),上述技巧可能失效。这时就需要更巧妙的思路。编码绕过是常用手段:尝试URL编码、双重URL编码、十六进制编码。把union select转换成%75%6e%69%6f%6e %73%65%6c%65%63%74,或者把数据库名、表名用十六进制表示(如0x7765623138代表‘web18’),有时能骗过解码层与过滤层不一致的检查点。
在SQL注入场景中,还可以利用数据库的特性。堆叠查询(;select 1)在支持多语句执行时是条捷径。无列名注入则是在无法获取列名时的终极手段,通过使用select 1,(select `2` from (select 1,2,3 union select * from flag)a limit 1,1),3这类嵌套查询,直接通过列的位置来提取数据。
思维跃迁:从“绕过”到“利用”
最高明的绕过,有时不是对抗过滤,而是让过滤为你所用。这需要你彻底理解上下文。比如,一个过滤了<script>的XSS题目,你可以尝试<img src=x onerror=alert(1)>。如果它过滤了“on”事件,或许<svg><script>alert(1)</script>又能奏效。关键在于,过滤规则往往只针对他们能想到的“恶意”模式,而语言和协议本身的复杂性与灵活性,提供了无数种意想不到的组合方式。
每一次成功的绕过,背后都是一次对系统思维盲区的精准打击。这无关乎记住所有技巧,而在于培养那种见招拆招、在限制中寻找缝隙的直觉。当你在深夜的CTF赛场,终于用一串扭曲变形却精准无比的payload让页面吐出flag时,那种快感,远胜于解开一道纯粹的数学题。

参与讨论
暂无评论,快来发表你的观点吧!