资讯动态

Seay源代码审计系统实战:PHP漏洞扫描与规则扩展

发布时间:2026/10/21 3:07:05 来源:尧图企业网站定制
简介Seay源代码审计系统是一款基于C#开发的PHP代码安全审计工具主要运行于Windows平台面向网络安全初学者、CTF/AWD参赛选手及渗透测试人员用于快速定位PHP项目中的安全隐患。它能够识别SQL注入、代码执行、命令执行、文件包含、文件上传、XSS跨站、信息泄露、任意URL跳转等常见漏洞并支持一键审计、代码调试、函数定位、插件扩展、自定义规则、代码高亮与数据库执行监控等功能。资源包共30个文件以dll动态库、exe可执行程序为主另含rar、zip源码与插件示例压缩包及少量配置、说明文件整体约42.16MB解压后可直接运行主程序并加载插件。目前已有804人学习下载适合在AWD对抗中快速排查源码风险也可作为代码审计入门与规则定制的练习素材。1. 从一次 AWD 被吊打说起这套源码审计系统到底能干什么打 AWD 的时候最怕的不是对手有多强而是自己守的那套 PHP 源码里藏着一个eval($_POST[cmd])你还在那儿悠哉悠哉地加固 WAF对面已经用一句话木马把你服务器当自家后花园逛了。我最早接触 Seay 源代码审计系统就是被这种“血泪经验”逼的——比赛前想快速过一遍源码看有没有明显的危险函数调用手工 grep 效率太低于是翻出了这套老牌工具。它本质上是一个面向 PHP 项目的静态代码审计工具核心能力是扫描源码目录自动识别危险函数、可控变量传递路径、以及常见的漏洞模式SQL 注入、文件包含、命令执行、代码执行等。适合两类人一是打 AWD 或 CTF 的选手需要在短时间内定位源码里的“雷”二是做代码审计入门的安全学习者想通过工具辅助理解漏洞在代码里长什么样。它不依赖复杂的编译环境Windows 下双击就能跑这也是它在比赛场景里流传很广的原因。2. 环境搭建与首次扫描从解压到出报告2.1 运行环境与依赖确认Seay 这套工具本身是用 C# 写的所以运行环境是 .NET Framework。我一般会在 Windows 虚拟机里跑它避免污染主力机。如果你手头只有 Linux常见做法是开一个 Windows 虚拟机或者用 Wine 尝试但 Wine 下界面渲染偶尔会出玄学问题比赛场景不建议折腾。需要确认的东西不多.NET Framework 4.0 及以上Win7 以上系统一般自带一个待审计的 PHP 源码目录足够的磁盘空间放扫描缓存大项目扫描时临时文件可能上百 MB提示扫描前把源码目录复制一份出来不要直接扫生产环境或正在开发的目录工具会写入一些索引文件。2.2 新建项目与目录配置打开主界面后第一步是新建一个审计项目。这里有个容易翻车的地方项目路径不要选到源码根目录的上级否则工具会把整个磁盘分区都纳入扫描范围扫描时间直接爆炸。操作顺序是这样的点击菜单栏的“新建项目”项目名称随便填比如awd_target_01源码路径选择你要审计的 PHP 项目根目录文件类型过滤里勾选.php、.inc、.module等 PHP 相关后缀配置完成后工具会先做一次文件索引把目录树和文件列表加载进来。这一步的耗时取决于文件数量几千个文件的话大概十几秒。2.3 执行扫描与结果解读索引完成后就可以点“开始扫描”了。扫描过程中工具会逐文件解析 PHP 代码提取函数调用、变量赋值、字符串拼接等语法结构然后跟内置的危险函数规则库做匹配。扫描结束后结果会按漏洞类型分类展示。我一般会重点关注这几类漏洞类型典型危险函数风险等级代码执行eval、assert、create_function高命令执行system、exec、shell_exec、passthru高文件包含include、require、include_once高SQL 注入mysql_query、mysqli_query 拼接中高文件操作file_get_contents、fopen、unlink中结果列表里每一条会显示文件名、行号、匹配到的函数和上下文代码片段。双击可以直接跳转到对应位置。这里要注意工具报出来的不一定是真漏洞它只是告诉你“这里有个危险函数”至于参数是否可控、是否有过滤需要你自己跟进去看。3. 核心机制拆解规则匹配、变量跟踪与误报控制3.1 危险函数规则库的结构Seay 的扫描能力核心在于它的规则库。规则库本质上是一组配置项每条规则定义了“什么样的函数调用算危险”。我用下来感觉它的规则文件结构大致是这样的逻辑!-- 规则库片段示意定义危险函数及其参数位置 -- rule name代码执行/name functioneval/function param_index0/param_index !-- 第0个参数是可控点 -- levelhigh/level /rule rule name命令执行/name functionsystem/function param_index0/param_index levelhigh/level /rule这段配置的意思是当扫描器遇到eval($x)或system($cmd)这样的调用时把第 0 个参数标记为潜在可控点并归入对应漏洞类型。param_index决定了工具关注哪个参数——比如preg_replace的危险参数是第一个模式参数而不是第二个。逻辑说明扫描器在解析 PHP 文件时会构建一棵简化的语法树遍历所有函数调用节点拿函数名去规则库里查。命中后再根据param_index取出对应参数表达式判断它是不是变量、是不是来自超全局数组$_GET、$_POST、$_REQUEST等。如果是就标记为“疑似可控”。参数怎么改如果你想增加自定义规则比如公司内部框架里有个my_exec()函数可以在规则文件里追加一条把函数名和参数位置填进去重启工具就能生效。3.2 变量传递链的跟踪逻辑单纯匹配危险函数误报率很高因为很多system()调用参数是硬编码的。Seay 做了一层变量跟踪从危险函数的参数出发反向追溯这个变量是在哪里赋值的赋值来源是不是用户输入。?php // 示例一个典型的可控变量传递链 $cmd $_GET[cmd]; // 第3行变量来自用户输入 $cmd escapeshellcmd($cmd); // 第4行经过过滤函数 system($cmd); // 第5行危险函数调用 ?工具在扫描这段代码时会这样处理在第 5 行发现system()调用参数是$cmd向上追溯$cmd的赋值历史发现第 4 行有一次赋值来源是escapeshellcmd()的返回值继续追溯escapeshellcmd()的参数发现是第 3 行的$cmd第 3 行的$cmd来自$_GET[cmd]标记为可控最终报告里会显示这条链但是否真的可利用取决于escapeshellcmd是否足够。工具不会替你做这个判断它只负责把链路摆出来。这也是为什么我说“工具报的不一定是真漏洞”——它给的是线索不是结论。3.3 误报与漏报的常见来源用久了会发现几个规律误报高发区框架封装的安全函数、参数白名单校验后的调用、测试代码里的 demo 函数漏报高发区动态函数调用$func system; $func($cmd);、多层变量覆盖、编码混淆后的 payload我一般会先把高危结果过一遍手工确认前 20 条剩下的根据文件路径判断——/test/、/demo/目录下的直接降权/admin/、/api/目录下的重点看。4. 避坑与排查那些年扫描时踩过的雷4.1 扫描大项目时卡死或崩溃现象源码目录超过 5000 个文件时扫描进度条卡住不动内存占用飙升最后程序无响应。原因工具在扫描时会一次性把文件索引和语法树都加载到内存里没有做分批处理。大项目直接撑爆内存。解决分目录扫描。把项目按模块拆成几个子目录每次只扫一个。或者先排除vendor/、node_modules/、cache/这些第三方库和缓存目录只扫业务代码。4.2 中文路径导致文件读取失败现象源码目录里有中文文件夹名扫描时提示“文件无法读取”或直接跳过。原因底层文件流处理对非 ASCII 路径支持不完善编码转换时丢字符。解决把源码复制到一个纯英文路径下再扫。我一般会在D:\audit\下建项目目录避免中文和空格。4.3 扫描结果里全是第三方库的告警现象报告里几千条告警翻了几页全是vendor/或framework/目录下的代码。原因工具默认扫描所有 PHP 文件不会自动区分业务代码和第三方依赖。解决在项目配置里添加排除目录规则把vendor、libs、plugins等目录排除掉。如果工具版本不支持排除就手动把业务代码复制到一个干净目录再扫。4.4 同一个漏洞被重复报告现象一个文件里的同一个危险函数调用在结果列表里出现多次。原因规则库里有重复规则或者文件被多次索引。解决检查规则库是否有重复条目重新扫描前先清空项目缓存再重新索引。4.5 变量跟踪断链导致漏报现象明明代码里有一个明显的可控变量传入了eval()但工具没报。原因变量经过了多次重新赋值、或者通过数组/对象属性传递跟踪逻辑断了。解决这种情况工具靠不住只能手工审计。我一般会配合 grep 命令做补充搜索# 搜索所有 eval 调用人工确认参数来源 grep -rn eval( --include*.php /path/to/source/ # 搜索超全局变量直接传入危险函数的情况 grep -rn \$_GET\|\$_POST\|\$_REQUEST --include*.php /path/to/source/ | grep -i system\|exec\|eval这两条命令能兜住一部分工具漏掉的场景尤其是动态函数调用和简单的直接传参。5. 二次开发与规则扩展让工具适配你的代码风格5.1 自定义规则库的修改方法每个团队的代码风格不一样有的喜欢用封装函数有的直接调原生函数。Seay 内置的规则库覆盖的是通用场景要让它适配你的项目就得改规则。规则库一般是一个 XML 或 JSON 文件放在工具安装目录的rules/或config/下。我一般会这样做先备份原始规则文件在文件末尾追加自定义规则重启工具用一个小测试文件验证规则是否生效测试文件可以这样写?php // 测试自定义规则是否生效 my_custom_exec($_GET[input]); // 应该被标记为命令执行 safe_function($_GET[input]); // 不应该被标记 ?如果扫描结果里第一条被标记、第二条没有说明规则生效了。5.2 用脚本批量处理扫描结果工具导出的报告一般是文本或 CSV 格式条目多了之后手工筛选很痛苦。我习惯用 Python 做一层后处理把结果按文件路径、漏洞类型、风险等级做聚合。import csv from collections import Counter # 读取扫描结果 CSV统计各目录下的漏洞分布 def analyze_report(csv_path): with open(csv_path, r, encodingutf-8) as f: reader csv.DictReader(f) rows list(reader) # 按目录聚合 dir_counter Counter() for row in rows: filepath row.get(file, ) # 取文件所在目录 directory /.join(filepath.split(/)[:-1]) dir_counter[directory] 1 # 输出漏洞最多的前10个目录 for directory, count in dir_counter.most_common(10): print(f{directory}: {count} 条告警) if __name__ __main__: analyze_report(scan_result.csv)这段脚本的逻辑很直接读 CSV按文件路径的目录部分做聚合输出告警数量最多的前 10 个目录。参数csv_path换成你导出的报告路径就行。这样能快速定位到“重灾区”优先审计那些目录。5.3 把工具接入 CI 流程的思路如果想把代码审计左移可以在 CI 里加一步自动扫描。思路是用命令行方式调用 Seay 的扫描引擎如果版本支持扫描结果输出为 JSON用脚本判断高危漏洞数量超过阈值就阻断合并# 伪代码示意CI 中的扫描步骤 # 假设工具支持命令行模式 SeayScanner.exe --project /build/source --output /build/result.json --level high # 用 Python 检查结果 python check_result.py /build/result.json --max-high 0check_result.py里读取 JSON统计level为high的条目数量如果大于--max-high参数值就退出码非零CI 就会失败。这样能在代码合并前拦住明显有问题的提交。不过说实话静态扫描接入 CI 的误报率是个大问题。我一般会把阈值设得宽松一点只拦“代码执行”和“命令执行”这两类SQL 注入和文件包含先放行人工复核。5.4 一个我常用的验证习惯每次改完规则库或者写完自定义脚本我不会直接拿大项目去跑而是先准备一个“已知答案”的小测试集——里面放几个明确有漏洞的文件和几个明确安全的文件跑一遍看结果是否符合预期。这个习惯是被坑出来的有一次改规则时手滑把param_index写错了导致所有preg_replace的告警都指向了错误参数大项目跑了一遍才发现白白浪费了半小时。从那以后我每次动规则库都强制走一遍小测试集确认误报和漏报没有明显变化再上真实项目。希望这个习惯也能帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑