php代码审查应聚焦高危函数入口(如eval、system、mysql_query等)逆向追踪参数来源,结合静态工具与人工审查,严控数据可控性、过滤有效性及上下文可信性,并落实双人确认与全链路污染分析。

PHP 代码审查(Code Review)不是“挑错比赛”,而是用可落地的检查动作,把漏洞、性能陷阱和协作断点提前暴露出来。学不会就容易变成走形式——比如只盯 if 缺不缺大括号,却放过了 eval($_GET['cmd']) 这种真实线上雷。
从哪几个函数开始逆向追踪最有效?
别一上来就通读全项目。先锁定高危函数入口,再倒查参数来源,这是审计效率最高的路径。重点盯死以下几类:
-
eval、assert、system、exec、shell_exec:只要参数含用户输入(哪怕经过一次base64_decode或urldecode),立刻标记为 RCE 风险 -
mysql_query、mysqli_query、PDO::query:看 SQL 字符串是否拼接了$_GET、$_POST、$_REQUEST或未过滤的数据库字段值 -
include、require、include_once、require_once:检查文件路径是否由用户控制,尤其是带.php后缀或未限制目录的场景 -
file_get_contents、file_put_contents、unlink、move_uploaded_file:关注路径参数是否拼接了$_FILES名称、$_GET['file']等,有无路径穿越(../)或协议绕过(phar://、data://)
为什么直接搜 $_GET 和 $_POST 往往漏掉关键漏洞?
因为真实项目里,用户输入早被“藏”起来了——可能进过 filter_input、$_REQUEST 合并、parse_str 解析、json_decode 转换,甚至被 extract 批量导入变量空间。只搜超全局变量会错过 70% 的污染源。
实操建议:
- 先全局搜索
extract(、parse_str(、$$,这些是变量覆盖高发区 - 再搜
filter_input(,确认是否用了FILTER_SANITIZE_SPECIAL_CHARS这类“假过滤”(它不防 SQL 注入) - 对 JSON 接口,重点看
json_decode($input, true)后的数组键名是否直接拼进 SQL 或文件路径
静态工具能代替人工审查吗?
不能。像 PHP_CodeSniffer 只能抓风格问题,PHPMD 主要报复杂度,RIPS 会漏掉逻辑漏洞(比如权限校验被 if ($user->role !== 'admin') return; 写在函数中间而非开头)。它们的价值是帮你省下机械劳动时间,而不是替代判断。
真正该做的组合是:
- 用
phpcs --standard=PSR12拦住命名、缩进等低级不一致 - 用
phpstan level=5发现未定义变量、类型不匹配等运行时隐患 - 人工聚焦三件事:数据是否可控、过滤是否到位、上下文是否可信(比如一个“导出 CSV”功能,
$filename来自用户,但后缀被硬写成.csv,仍可能通过test%00.csv截断绕过)
团队审查最容易忽略的“非技术点”是什么?
是“谁在什么时候看到什么”。很多团队 PR 提交后没人及时看,或者只让 senior 开发扫一眼 diff 就合并。结果 foreach ($items as $item) { db_query("UPDATE ... WHERE id = " . $item['id']); } 这种 N+1 查询或 SQL 注入,在上线前根本没被任何人读到完整上下文。
必须卡死两个动作:
- 所有涉及数据库、文件、命令执行的变更,必须至少两人签字(
LGTM不算,得写明“已确认$id经过intval()处理”) - 审查者不能只看改动行,必须打开对应函数/类的完整定义,确认调用链上有没有隐式污染(比如
get_user_by_id($_GET['id'])返回的对象,其email字段又被拼进了另一条 SQL)
真正的难点不在懂不懂 __wakeup,而在于你愿不愿意花三分钟点开那个被修改的函数,往上翻十行,看看输入到底从哪来。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











