PhishDrill:零依赖开源钓鱼演练平台,一台内网机器完成企业安全意识培训全流程
企业做钓鱼演练,过去只有两条路:要么采购动辄数万元的商业平台,要么用 GoPhish 之类的框架自己搭 C2、配数据库、调依赖,折腾一两天才能发出第一封测试邮件。**PhishDrill 给出了第三种答案——一个零第三方依赖的开源钓鱼演练平台,不用搭 C2、不用买服务,一台内网机器甚至一台笔记本,就能跑完「发信 → 埋点 → 去重 → 归因到人 → 报表交付」的完整钓鱼攻防演练**流程,并且自带浏览器管理控制台和实时数据大屏。
整套系统从 CLI、HTTP 服务、SMTP 发信到事件日志、报表、GUI,全部基于 Python 标准库实现。对于需要在纯内网环境开展**安全意识培训**和演练评估的团队来说,这意味着没有外联、没有公网依赖,也没有供应链层面的隐忧。
产品介绍:PhishDrill 是什么
PhishDrill 的定位很清晰:让演练组织者用最轻的成本,完成一次合规、可量化、可交付的企业内部钓鱼演练。埋点服务直接运行在组织者本机或内网服务器上,邮件中的像素、链接、凭据页全部指向这台机器,员工侧的演练链接不出内网,数据不出边界。
平台提供浏览器管理控制台,从目标导入、模板预览、创建演练、发送测试邮件、全量发送,到事件监控和报表下载,全程图形化操作;同时也保留完整的 CLI 形态,方便脚本化和自动化集成。首次访问会强制设置管理员密码,登录失败限流(5 次锁定 60 秒),可以直接部署到服务器上长期使用。
核心功能:从发信到报表的完整闭环
| 特性 | 说明 |
|---|---|
| 无 C2 | 埋点服务在演练组织者本机/内网运行,无任何公网依赖、无外联 |
| 零依赖 | CLI / HTTP 服务 / SMTP 发送 / 事件日志 / 报表 / GUI 全部 Python 标准库实现 |
| 浏览器控制台 | 目标导入、模板预览、创建演练、发送测试邮件、全量发送、事件监控、报表下载,全程图形化 |
| 数据大屏 | 攻击风险趋势、转化漏斗、部门 TOP、场景分布、实时事件流,5 秒刷新,可投屏演示 |
| 强制登录 | 首次访问强制设置管理密码,失败限流(5 次锁 60 秒),可直接部署到服务器 |
| 内置模板库 | 10 套中文企业场景(凭据/链接/像素/附件四类),配套拟真落地页 |
| 唯一身份标识 | 每人一枚随机 token 贯穿像素/链接/凭据页,触发情况精准到邮箱 |
| 数据去噪 | 网关预取识别、去重窗口、孤儿点击检测,四层漏斗口径公开可回溯 |
| 最小化收集 | 凭据页默认只记录用户名,明文密码无落盘路径 |
| 交付完整 | 明细 CSV、脱敏 CSV、三张统计图、单文件 HTML 报告,可直接交付 |
| 可靠发送 | 节流、失败重试、断点续发,CLI 与控制台双形态 |
技术优势:为什么内网钓鱼演练适合用它
一是彻底的内网闭环。 很多演练工具要么依赖云端服务,要么需要对接外部邮件 API,数据合规上很难交代。PhishDrill 的埋点端点和管理控制台跑在同一个进程里,所有事件数据留在本地工作区,天然满足「数据不出内网」的要求。
二是归因精准且口径透明。 每个目标分配唯一 token,打开、点击、提交三类事件全部按 token 归因到具体邮箱。报表采用四层漏斗口径,并明确区分「原始打开」与「人工打开」——网关安全设备预取邮件像素造成的虚高数据,会按 UA 自动剔除并单独统计,避免演练结果被安全设备「刷量」污染。
三是收集克制。 凭据类场景默认只记录用户名,不存在明文密码落盘路径,这在向管理层和法务合规部门报备时是关键的加分项。
四是工程细节扎实。 发送带节流(默认 0.2 秒/封)、失败重试、断点续发——中断后重跑不会重复打扰已发送成功的目标;目标 CSV 支持合并导入,已有邮箱保留唯一标识、演练归属与发送状态,只更新新提供的字段。
快速开始:3 分钟跑通内网钓鱼演练平台
整个部署只有两条命令:
# 1. 初始化工作区(自动复制内置模板,自动探测内网 IP 作为对外地址)
python phishdrill.py init --workspace drill
# 2. 启动平台(单进程:管理控制台 + 埋点端点)
python phishdrill.py serve --workspace drill --host 0.0.0.0 --port 8090
浏览器打开 http://<本机IP>:8090/,按下面的顺序即可完成一次完整演练:
- 设置管理员密码:首次访问强制设置,这是服务可被他人访问时的安全前提;
- 系统设置:填写 SMTP 发信接口(内网中继 25 / 企业邮箱 465-SSL / 587-STARTTLS),点「连通性测试」+「发送测试邮件」;
- QQ/163 等个人邮箱:密码栏填写「授权码」而非登录密码(QQ 邮箱:网页版设置 → 账号 → 开启 IMAP/SMTP 服务后生成);
- 企业邮箱:使用「客户端专用密码」,且账号需开通 SMTP 权限;
- 目标管理:粘贴 CSV(name、email、dept、scenario 四列,模板 ID 可留空)一键导入,点「生成唯一标识」;
- 邮件模板:浏览内置 10 套模板,点击预览,邮件内 CTA 可点击体验落地页;
- 演练与发送:填名称 → 选模板 →(可选筛选目标)→ 创建演练 →「发测试邮件」给自己验真 →「全量发送」;
- 事件监控 / 人员明细:实时看谁打开、谁点击、谁提交;
- 报表:一键生成,下载 HTML 报告 / 明细 CSV / 脱敏 CSV 交付;
- 数据大屏:新窗口打开
http://<IP>:8090/bigscreen,实时投屏演示。
实战操作:一次合规钓鱼演练的六个阶段
阶段 0:书面授权(不可跳过)
书面授权需包含四大要素:**目标人群、时间窗口、允许采集范围(建议仅用户名)、通报与培训安排**。没有这一步,后面的一切都不合法。
阶段 1:初始化与目标准备
> python phishdrill.py init --workspace drill
[*] 工作区已初始化: …\drill
> python phishdrill.py targets --workspace drill --csv targets.csv
[*] 读取 5 行,有效目标 4 个(已按邮箱去重),无效行 1 行
> python phishdrill.py plan --workspace drill
[*] 新生成 token 4 个,共 4 个目标
> python phishdrill.py campaign new --workspace drill --name 2026Q3全员钓鱼演练
[*] 新建演练: drill_2026…(2026Q3全员钓鱼演练),目标 4 人,场景: 全部
对外地址会自动探测本机内网 IP;若检测到回环地址,启动服务时会自动纠正并给出警告——邮件里的核验链接必须使用员工可达的地址。
阶段 2:发信通道验证
先在「系统设置」完成连通性测试并发送测试邮件给自己,核对渲染效果;再用 --dry-run 全量渲染,检查每封邮件的唯一标识:
> python phishdrill.py send --workspace drill --dry-run
[dry-run] [email protected] -> outbox/wangqiang_at_example.com_vpn_upgrade.eml
完成: 成功 4,失败 0,跳过 0
阶段 3:正式发送
正式发送自带节流(默认 0.2 秒/封)、失败重试、断点续发(已成功的自动跳过,中断重跑不重复发送)。建议先对 10% 的目标试投,观察网关拦截情况,再决定全量发送。
阶段 4:监控与归因
演练期间保持埋点服务在线。「事件监控」页面查看原始事件流(类型/时间/IP/UA),「人员明细」页面按触发程度(提交 > 点击 > 打开)排序到人。注意甄别两类假信号:
- 网关预取:安全设备自动访问像素,已按 UA 自动剔除并单独统计;
- 孤儿点击:有点击无打开,疑似扫描器爬链接。
阶段 5:复盘与收尾
生成报表并按部门下钻分析;演练结束 48 小时内全员通报,并安排中招人员复训;最后通过 campaign close 或删除演练完成收尾。
统计口径:报表数字是怎么算出来的
口径公开是这个平台区别于很多同类工具的地方,每一项指标都可以回溯:
- Open(原始):全部像素请求,含网关预取;
- 打开(人工):剔除预取 UA、按「类型+token+IP+UA」默认 5 分钟窗口去重后的请求;
- 点击 / 提交:唯一链接与凭据页事件,按 token 归因到人;
- 中招人数:点击 ∪ 提交的去重人数(既点又提交者只计一次);
- 孤儿点击:有点击无人工打开,疑似扫描器爬链接;
- 主指标:点击率 + 提交率 + 上报率。打开率受预取(高估)与图片拦截(低估)双重影响,单独看没有结论价值。
内置邮件模板:10 套中文企业场景
| 模板 | 类型 | 场景 |
|---|---|---|
| 账号安全核验 | 凭据提交 | 异地登录风险、身份核验 |
| 邮箱密码到期提醒 | 凭据提交 | 密码到期、登录修改 |
| 工资条/绩效结果确认 | 凭据提交 | 工资查询确认 |
| VPN 升级重新认证 | 凭据提交 | 远程办公重新认证 |
| 绩效目标确认 | 凭据提交 | 绩效目标登录确认 |
| 会议通知 | 链接点击 | 全员会议入口 |
| 安全意识培训通知 | 链接点击 | 在线培训入口 |
| OA 系统升级通知 | 链接点击 | 新门户入口 |
| 安全公告 | 纯像素 | 纯粹打开率 |
| 会议纪要附件 | HTML 附件 | 附件内嵌追踪 |
每套场景都对应一个拟真落地页——标题、话术、主题色与邮件故事保持一致。以工资条场景为例,落地页是「员工自助服务平台」风格,包含工号输入框、「查询工资条」按钮、隐私提示和验证码。
自定义场景也很简单:在工作区 scenarios/ 目录复制任意 JSON 修改即可,模板支持 {{name}}、{{email}}、{{dept}}、{{pixel}}、{{link}}、{{login}} 占位符。
模拟压测:上线前先用合成数据彩排
组织级演练(数百人规模)上线前,建议先用合成数据彩排全流程。harness/ 目录自带合成数据集生成器与模拟器,可合成姓名、邮箱、部门序列,数据明确标注「合成」。
注意:模拟器脚本仅用于验证工具的规模化能力,生成的全部是合成数据,严禁作为真实演练结果对外发布。
CLI 速查
| 命令 | 作用 |
|---|---|
init --workspace W [--base-url URL] |
初始化工作区 |
targets --workspace W --csv F |
导入目标(合并导入,按邮箱去重) |
plan --workspace W |
生成唯一 token |
campaign new/list/close/delete |
演练管理 |
send --workspace W [--dry-run] [--force] |
渲染/发送(节流+重试+续发) |
serve --workspace W [--host H] [--port P] |
启动埋点服务 |
report --workspace W [--masked] |
报表与图表 |
gui --workspace W |
tkinter 图形界面 |
所有命令支持 --help 查看详细参数。除浏览器控制台外,平台还提供 tkinter 桌面 GUI(随官方 Python 自带,无需额外依赖)。
常见问题
- 打开率虚高/虚低:虚高通常是网关预取,看报表中的「预取」数据并核对 UA;虚低是客户端拦图,属正常现象,应以点击/提交为主要指标。
- 像素不触发:客户端默认拦图,员工点「显示图片」才会产生事件——所以打开率只作参考。
- 发信 535 认证失败:个人邮箱确认使用「授权码」且已开启 SMTP/IMAP 服务;企业邮箱用「客户端专用密码」;账号须为完整邮箱地址;连续失败会被临时锁定,等 10\~30 分钟再试。
- 发信 503 提示需要 EHLO 和 AUTH:网关认证形式不兼容,可参考源码
smtp_connect的 LOGIN 握手实现。 - 员工点不开链接:对外地址是回环地址或不在同一网络——改为本机内网 IP 并重启服务。
- GUI 需要什么依赖:无,tkinter 随官方 Python 自带。
测试与已知限制
python harness/smoke_test.py # 后端端到端 60 项断言
node harness/js_boot_test.js # 前端无头 25 项断言(需 Node.js,可选)
已知限制:像素受客户端图片拦截影响,打开率会被低估,阅读回执依赖客户端支持;埋点服务需在演练周期内保持在线,否则链接 404;埋点页面仅建议内网访问,公网部署需额外访问控制;部分列表时间以 UTC 存储(表头已标注)。
应用场景
- 企业安全意识培训:用真实演练代替说教式培训,用点击率和提交率量化培训效果;
- 红蓝对抗与攻防演练:内网闭环、无外联,适合作为蓝队评估员工侧防线的轻量化工具;
- 合规审计与风险评估:脱敏 CSV 和单文件 HTML 报告可直接归档交付,支撑等保、内控类审计材料;
- 新员工入职考核:针对特定部门或人群发起小规模演练,快速定位高风险人群并安排复训。
总结
如果团队需要一套**开源钓鱼演练平台**,又受限于内网环境、合规要求和预算,PhishDrill 值得放进候选清单:零依赖、无 C2、归因到人、口径透明、交付完整,从初始化到发出第一封测试邮件只要两条命令。图形界面与 CLI 双形态也让它在「安全团队自用」和「交给非技术同事运营」两种场景下都能落地。
感兴趣的话,可以从 init 命令开始,先用 --dry-run 和合成数据完整彩排一遍,再申请书面授权开展正式演练。