本文目录导读:

我来为你详细讲解PHP代码审计竞赛的相关知识和技巧。
竞赛基础知识准备
必备工具
# 常用静态分析工具 - RIPS (商业) - PHPStan - Psalm - SonarQube - phpcs-security-audit # 动态调试工具 - Xdebug - PHPStorm (IDE) - Burp Suite - SQLMap
核心审计思路
// 常见审计切入点 1. 用户输入点:$_GET, $_POST, $_REQUEST, $_COOKIE, $_FILES 2. 数据库操作:SQL查询、ORM操作 3. 文件操作:include, require, fopen, file_put_contents 4. 命令执行:exec, system, shell_exec, passthru 5. 代码执行:eval, assert, preg_replace /e
常见漏洞类型及审计技巧
SQL注入审计
// 危险代码示例
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = " . $id; // 直接拼接
// 安全写法
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
// 审计要点
- 搜索SQL拼接关键字:SELECT, INSERT, UPDATE, DELETE
- 检查参数是否经过过滤
- 查看是否使用预处理语句
XSS漏洞审计
// 危险代码 echo $_GET['name']; // 直接输出未过滤 // 安全写法 echo htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8'); // 审计要点 - 搜索echo, print, print_r等输出函数 - 检查输出点是否经过htmlspecialchars - 关注json_encode等特殊输出场景
文件包含漏洞
// 危险代码 $page = $_GET['page']; include($page . '.php'); // 可包含任意文件 // 审计要点 - 搜索include, include_once, require, require_once - 检查路径是否可控 - 关注../目录穿越 - 支持php://伪协议
命令注入漏洞
// 危险代码
$cmd = "ping " . $_GET['ip'];
system($cmd);
// 安全写法
$ip = filter_var($_GET['ip'], FILTER_VALIDATE_IP);
if ($ip) {
system("ping " . escapeshellarg($ip));
}
// 审计要点
- 搜索system, exec, shell_exec, passthru, popen
- 检查变量拼接情况
- 关注`符号和通配符
反序列化漏洞
// 危险代码 $data = $_COOKIE['user']; $user = unserialize($data); // 未验证数据 // 审计要点 - 搜索unserialize函数 - 分析魔术方法:__wakeup, __destruct, __toString - 查找可利用的POP链
审计实战流程
整体审计流程
// 审计步骤 步骤1: 获取源码后先了解整体架构 - 查看目录结构 - 阅读入口文件 (index.php) - 了解框架或CMS类型 步骤2: 关注核心配置文件 - config.php, database.php - 查看数据库连接方式 - 检查全局过滤机制 步骤3: 分析路由和控制器 - 确定参数传递方式 - 找寻业务逻辑漏洞 - 关注文件上传功能 步骤4: 重点审计危险函数 // 使用正则搜索危险函数 grep -r "eval\|system\|exec\|unserialize" *.php
快速定位漏洞技巧
// 使用grep命令搜索 # 搜索SQL注入 grep -rn "SELECT.*\$_" *.php # 搜索命令执行 grep -rn "system\|exec\|shell_exec" *.php # 搜索文件包含 grep -rn "include.*\$_" *.php # 搜索反序列化 grep -rn "unserialize" *.php // IDE插件辅助 - PHP Intelephense - SonarLint - PHP CodeSniffer
实战案例分析
案例1:SQL注入利用
// 漏洞代码
<?php
$conn = mysqli_connect("localhost", "root", "", "test");
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username='$username' AND password='$password'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
echo "登录成功";
}
// 攻击Payload
username: ' OR 1=1 -- -
password: anything
// 修复建议
$stmt = $conn->prepare("SELECT * FROM users WHERE username=? AND password=?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
案例2:文件上传绕过
// 漏洞代码
<?php
$upload_dir = "uploads/";
$file_name = $_FILES['file']['name'];
$file_tmp = $_FILES['file']['tmp_name'];
// 只检查扩展名
if (preg_match('/\.(jpg|png|gif)$/i', $file_name)) {
move_uploaded_file($file_tmp, $upload_dir . $file_name);
echo "上传成功";
}
// 绕过方法
1. 双扩展名:shell.php.jpg
2. 大小写:shell.PHP
3. 特殊字符:shell.php%00.jpg
4. .htaccess绕过
// 修复建议
$allowed = ['jpg', 'png', 'gif'];
$ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
if (in_array($ext, $allowed) && getimagesize($file_tmp)) {
// 重命名文件、检查MIME类型
}
CTF竞赛特殊技巧
快速发现漏洞关键点
// 常见CTF考点 - 变量覆盖 - 弱类型比较 - 伪随机数 - 加密构造 - URL解析绕过
常见绕过技巧
// 弱类型比较绕过
if ($_POST['password'] == "admin123") {
// 使用 0e 开头字符串绕过
// 0e123 或 0e456 均等于 0
}
// 变量覆盖
extract($_GET); // 可覆盖任意变量
parse_str($_SERVER['QUERY_STRING']); // 参数覆盖
// MD5绕过
if (md5($_GET['a']) == md5($_GET['b'])) {
// a[]=1&b[]=2 可绕过
}
审计报告撰写
漏洞报告模板
# 漏洞报告 ## 漏洞名称:SQL注入 - **风险等级**:高危 - **受影响文件**:user.php 第23行 - **漏洞类型**:SQL注入 ## 漏洞描述 ... ## 复现步骤 1. 访问 http://target.com/user.php?id=1' AND 1=1-- - 2. 观察返回结果 ## 影响范围 - 可获取数据库敏感信息 - 可能导致数据泄露 ## 修复建议 - 使用预处理语句 - 对输入进行过滤
学习资源推荐
练习平台
- Pikachu靶场:https://github.com/zhuifengshaonianhanlu/pikachu
- DVWA:https://github.com/digininja/DVWA
- WebGoat
- PortSwigger Web Security Academy
书籍推荐
- 《代码审计:企业级Web代码安全架构》
- 《白帽子讲Web安全》
- 《Web安全深度剖析》
常用工具下载
- Seay源代码审计系统(国内)
- RIPS(商业软件,开源替代品可用)
- PHP_CodeSniffer
实战技巧总结
// 快速审计口诀 1. 先看入口,后看配置 2. 关注参数,跟踪流向 3. 搜索危险,重点突破 4. 业务逻辑,别忘分析 5. 测试验证,确保无误 // 提效技巧 - 优先审计功能点:登录、上传、搜索、导出 - 建立漏洞模式库 - 善于使用版本对比 - 关注注释和TODO标记
代码审计竞赛最重要的是思路清晰和经验积累,多练习、多总结,祝你在比赛中取得好成绩!