CTFShow 萌新区 Web 1-10 题精讲:5 种 intval 绕过手法实战剖析
在 CTF 竞赛的 Web 安全领域中,PHP 类型转换漏洞一直是高频考点。本文将系统性地剖析 CTFShow 萌新区 Web 1-10 题中 intval() 函数的 5 种经典绕过手法,通过原理分析、Payload 构造和实战演示,帮助初学者建立完整的漏洞利用思维框架。
1. intval 函数特性解析
intval() 作为 PHP 中的类型转换函数,其核心特性决定了漏洞利用的可能性边界。该函数存在三个关键行为特征:
字符串解析规则:当输入为字符串时,函数会从首字符开始解析,直到遇到非数字字符停止。例如:
intval("123abc") => 123 intval("a123") => 0进制转换支持:支持二进制(0b)、八进制(0)、十六进制(0x)前缀识别:
intval("0x3e8") => 1000 intval("0b111") => 7科学计数法处理:对
1e3这类表示法会转换为 1000,但需注意:intval("1e3") => 1 // 仅当字符串形式直接传入时 intval(1e3) => 1000 // 数值形式传入时
典型漏洞代码模式如下所示,这种判断逻辑极易被绕过:
$id = $_GET['id']; if(intval($id) > 999){ die("Access Denied"); }2. 单引号字符串绕过
当过滤逻辑未处理引号时,可利用 PHP 的弱类型特性进行突破:
攻击原理:
- PHP 会将带引号的数字字符串视为字符串类型
- intval() 处理时自动忽略引号,但比较运算符
==会触发类型转换
Payload 构造:
?id='1000'实战演示:
GET /challenge.php?id='1000' HTTP/1.1 Host: ctf.show # 响应结果: # 成功绕过判断,返回 flag{...}技术要点:
- 适用于未过滤引号的场景
- 单/双引号均可使用
- 注意与
===严格比较的区别
3. 数学运算绕过
当过滤了引号但未过滤运算符时,可通过数学表达式实现绕过:
攻击原理:
- 利用运算符构造结果为 1000 的表达式
- intval() 会先计算表达式结果
Payload 变种:
?id=100*10 ?id=500+500 ?id=2000-1000 ?id=1000/1 ?id=500<<1 ?id=400|624防御对比:
| 过滤措施 | 可绕过方式 |
|---|---|
过滤+ | 使用*/<< |
| 过滤所有运算符 | 需采用其他方法 |
4. 进制转换技巧
当过滤了常规数字但允许特殊前缀时,进制转换成为突破口:
各进制表示法:
十进制 1000 => 1000 十六进制 => 0x3e8 八进制 => 01750 (历史遗留写法) 二进制 => 0b1111101000实战案例:
GET /challenge.php?id=0x3e8 HTTP/1.1 # 服务器处理流程: 1. 接收字符串 "0x3e8" 2. intval() 识别为十六进制数 3. 转换为十进制 1000 4. 绕过 999 的限制特殊技巧:
- 某些环境下
0x可能被过滤,可尝试省略前导零:x3e8 - 结合 URL 编码:
%30%78%33%65%38(0x3e8 的编码)
5. 位运算与二次取反
当常规运算符被禁用时,位运算提供新的可能性:
按位取反原理:
~1000 = -1001 ~~1000 = 1000 # 双重取反还原Payload 示例:
?id=~~1000 ?id=(1000)技术细节:
- 利用 PHP 的位运算优先级特性
- 括号可改变运算顺序,有时能绕过简单过滤
- 注意部分环境会过滤
~符号
6. 字符串拼接技术
当过滤严格但允许字符串连接时,可采用动态构造方式:
Payload 设计:
?id="1000" ?id=("10"."00") ?id=${1000}高级技巧:
// 利用变量动态构造 $a="10"; $b="00"; $id=$a.$b;7. 综合防御方案
针对 intval 绕过的完整防护应包含以下措施:
$id = $_GET['id']; // 多层防御策略 if(!is_numeric($id)) die("Invalid input"); if(strpos($id,".") !== false) die("No float allowed"); if($id > 999 || $id < 1) die("Out of range"); // 类型严格校验 if(intval($id) !== $id) die("Type mismatch"); // 白名单过滤 $allowed = range(1,999); if(!in_array($id, $allowed)) die("Not in whitelist");防护方案对比表:
| 防护等级 | 措施 | 可绕过性 |
|---|---|---|
| 基础 | 仅 intval() | 极易绕过 |
| 中级 | 增加运算符过滤 | 可能被进制绕过 |
| 高级 | 白名单+类型校验 | 极难绕过 |
| 终极 | 数字签名+服务端验证 | 理论上不可破 |
8. 实战挑战与思考
通过构造特殊 Payload 测试以下过滤规则:
if(preg_match("/or|\-|\\|\*|\<|\>|\!|x|hex|\+/i",$id)){ die("Filter triggered"); }突破思路:
- 使用未被过滤的
/运算符:?id=2000/2 - 采用位右移操作:
?id=4000>>2 - 组合使用括号和除法:
?id=(8000)/(8)
在真实攻防对抗中,往往需要结合多种技术才能突破层层防御。建议读者在本地搭建测试环境,通过修改过滤规则来验证不同绕过方法的有效性。