CTFshow-Web入门:PHP特性实战之is_numeric函数绕过技巧解析

1. 从一道CTF题说起:is_numeric函数到底在“看”什么?

如果你刚开始接触CTF的Web题目,尤其是PHP代码审计类的,大概率会遇到一个老朋友:is_numeric()函数。很多新手朋友第一次看到这个函数名,可能会想:“这不就是判断是不是数字吗?能有什么花活?” 我刚开始也是这么想的,直到在实战里被它“教育”了几次,才发现这个看似简单的函数,背后藏着不少PHP语言特性的“坑”,而这些“坑”,恰恰是出题人最喜欢设置考点的地方。

简单来说,is_numeric() 函数用于检测一个变量是否为数字或数字字符串。听起来很直白,对吧?比如 is_numeric(123) 返回 trueis_numeric("123") 也返回 trueis_numeric("abc") 返回 false。但它的“宽容度”可能比你想象的要高。它不仅能识别十进制整数、浮点数,还能识别科学计数法(如 "1e3")、带有正负号的数字(如 "+123""-3.14"),甚至是一些十六进制表示(在某些PHP版本中,如 "0x1A")。这种“宽容”在方便开发的同时,也给安全留下了隐患,因为攻击者可以利用这些非标准的数字表示形式,绕过一些看似严格的输入校验。

在CTFshow的Web入门系列题目(web100-web103)中,is_numeric() 函数就是核心的“守门员”。题目设计者故意把它放在关键的逻辑判断位置,让你必须想办法让这个函数对你精心构造的“非纯数字”payload返回 true,才能进入后续的代码执行环节。这就像是一道门的密码锁,你以为密码只能是0-9的数字,结果发现它还能识别一些特殊的“暗号”。我们接下来的任务,就是学会识别并构造这些“暗号”,从而打开这扇门,拿到后面的flag。

理解这个函数,不仅仅是记住它的返回值。更重要的是,要理解它在PHP表达式中的行为,尤其是当它和赋值运算符(=)、逻辑运算符(and, &&, or, ||)一起出现时,PHP那套独特的运算符优先级和求值顺序规则。这往往是绕过检测的第一步,也是最容易让人迷惑的一步。别担心,我会用最直白的例子,带你把这些弯弯绕绕理清楚。

2. 运算符优先级:那个容易被忽略的“and”

在PHP里,运算符优先级决定了表达式中各个部分计算的先后顺序。这是一个基础但至关重要的概念,尤其是在代码审计时。我们直接看web100题目的核心代码片段:

$v0 = is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
    // 执行关键代码
}

很多人的第一反应是:$v0 的值应该是后面整个逻辑表达式 is_numeric($v1) and is_numeric($v2) and is_numeric($v3) 的结果。也就是说,$v1$v2$v3 必须全是数字,$v0 才会是 true,才能进入if语句。

但这里有一个巨大的陷阱:运算符 and 的优先级低于赋值运算符 =

这意味着上面那行代码的实际执行顺序是:

  1. 先计算 is_numeric($v1) 的结果(假设为 $tmp)。
  2. 然后执行赋值操作:$v0 = $tmp
  3. 最后,才将 $v0 的值与后面的 is_numeric($v2) and is_numeric($v3) 进行 and 运算。但这个运算的结果并没有赋值给任何变量,直接被丢弃了。

所以,整行代码执行完后,$v0 的值仅仅等于 is_numeric($v1) 的结果。只要 $v1 是数字,$v0 就是 true,后面的 $v2$v3 是什么,根本不影响 $v0 的值!

为了让你看得更清楚,我们对比一下 and 和更常见的 &&


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值