crumrine/web-tarpit

GitHub: crumrine/web-tarpit

一个零依赖的 JavaScript Web 蜜罐,通过伪造 WordPress 页面和环境文件并以极慢速率响应,消耗恶意 Bot 的扫描资源并记录其行为。

Stars: 16 | Forks: 0

# web-tarpit 适用于任何 JavaScript 服务器的 Bot 陷阱。通过伪造的 WordPress 页面、蜜罐凭据和缓慢的响应流来消耗漏洞扫描器的时间。 零依赖。单次导入。适用于所有支持 Web 标准 `Request`/`Response` API 的环境。 ## 安装 ``` npm install web-tarpit ``` ## 使用方法 ### Cloudflare Workers ``` import { tarpit } from 'web-tarpit'; export default { async fetch(request, env, ctx) { const trap = tarpit(request, { ctx }); if (trap) return trap; return new Response('Hello world'); } }; ``` ### Hono ``` import { Hono } from 'hono'; import { tarpit } from 'web-tarpit'; const app = new Hono(); app.use('*', async (c, next) => { const trap = tarpit(c.req.raw); if (trap) return trap; await next(); }); app.get('/', (c) => c.text('Hello')); export default app; ``` ### Next.js Middleware ``` // middleware.js import { tarpit } from 'web-tarpit'; export function middleware(request) { const trap = tarpit(request); if (trap) return trap; } export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'] }; ``` ### Deno / Bun ``` import { tarpit } from 'web-tarpit'; Deno.serve((request) => { const trap = tarpit(request); if (trap) return trap; return new Response('Hello'); }); ``` ### Express ``` import express from 'express'; import { expressTarpit } from 'web-tarpit/adapters'; const app = express(); app.use(expressTarpit()); app.get('/', (req, res) => res.send('Hello')); app.listen(3000); ``` ### Node.js HTTP ``` import { createServer } from 'http'; import { nodeTarpit } from 'web-tarpit/adapters'; const trap = nodeTarpit(); createServer((req, res) => { if (trap(req, res)) return; // bot trapped res.end('Hello'); }).listen(3000); ``` ## 功能说明 每个 Web 服务器都会遭到 Bot 的扫描,寻找 WordPress 漏洞、暴露的 `.env` 文件以及管理面板。通常你会返回 404,然后它们会在几毫秒内离开。这个模块会让它们为扫描你而后悔。 | 路径 | Bot 获取到的内容 | |---|---| | `/wp-login.php` | 像素级还原的 WordPress 6.7.2 登录页。捕获凭据,每次尝试等待 5-15 秒。 | | `/wp-admin/*` | 无限的管理面板迷宫。包含 20 多个可点击的页面。 | | `/.env*` | 缓慢发送伪造的 AWS 密钥、Stripe 密钥和数据库密码。每次下载约 80 秒。 | | `/.git/*` | 缓慢发送伪造的 git 配置。 | | `/xmlrpc.php` | 缓慢发送 XML-RPC 错误。开启蜜罐模式后会解析 POST 请求,并使用伪造的管理员成功信息污染暴力破解数据库 —— 参见 [XML-RPC 蜜罐模式](#xml-rpc-honeypot-mode-opt-in)。 | | `/phpmyadmin/`、`/admin/`、`/login` | 缓慢发送带有 IP 警告的“拒绝访问”提示。 | | `/shell.php`、`*.sql`、`*.bak` | 缓慢发送“已记录违规行为”的消息。 | 合法请求会原封不动地通过 —— 此检查对正常流量增加的开销为零。 ## 日志记录 传入一个 `onTrap` 回调来记录每个被捕获的请求: ``` tarpit(request, { onTrap: (type, path, ip, request, data) => { console.log(`[tarpit] ${type} ${path} from ${ip}`); } }); ``` 默认(`'fault'`)模式下的事件类型包括:`login-page`、`login`、`admin`、`env`、`git`、`wp-probe`、`probe`、`xmlrpc`。蜜罐模式(见下文)增加了 `xmlrpc-bruteforce`、`xmlrpc-multicall`、`xmlrpc-pingback` 和 `xmlrpc-listmethods`。 `data` 参数在 `login` 事件中承载表单解码后的值,在 `xmlrpc-*` 事件中承载解析后的 XML-RPC 详情(方法名、捕获的凭据、multicall 计数、pingback 目标 URL)。**注意:`login` 和 `xmlrpc-bruteforce` 事件包含明文凭据。**如果你将它们持久化存储,你的存储将成为一个凭据数据库。如果你不想这样,请对密码字段进行哈希处理。 ## XML-RPC 蜜罐模式(可选启用) `/xmlrpc.php` 是现实世界中最常遭到攻击的路径。WordPress 暴力破解工具利用它将数百次凭据尝试打包进单个 HTTP 请求中,攻击者也利用它通过 `pingback.ping` 将存在漏洞的服务器变成 SSRF / DDoS 反射器。设置 `xmlrpcMode: 'honeypot'` 可将此路径变成一个主动陷阱,它会解析请求并进行欺骗响应: ``` tarpit(request, { xmlrpcMode: 'honeypot', ctx, onTrap: (type, path, ip, request, data) => { /* log to D1, etc. */ }, }); ``` | 方法 | 蜜罐回复 | |---|---| | `wp.getUsersBlogs`、`wp.getProfile`、`wp.getOptions`、`wp.getPosts`、`wp.getUsers`、`wp.getUser`、`wp.getPages`、`wp.getPage`、`metaWeblog.*`、`blogger.*` | 伪造 `isAdmin: true` 成功。攻击者尝试的每一对凭据看起来都“有效” —— 从而用垃圾数据污染暴力破解数据库。 | | `system.multicall` | 根据内部调用次数返回对应大小的成功数组,上限为 1..200。 | | `pingback.*` | 始终返回错误。永远不会返回成功 —— 拒绝被用作 SSRF 反射器。 | | `system.listMethods` | 缓慢发送包含约 80 个伪造的 WordPress 方法的列表。 | | 其他任何内容 | 缓慢发送错误。 | 默认模式(`xmlrpcMode: 'fault'`,即 1.0 版本的行为)对每个 `/xmlrpc.php` 请求返回缓慢发送的错误,并触发一次 `xmlrpc` 事件。 对于使用 D1 的 Cloudflare Workers,传入 `ctx` 并记录到数据库: ``` tarpit(request, { ctx, onTrap: (type, path, ip, request) => { return env.TARPIT_DB.prepare( "INSERT INTO tarpit_log (site, type, path, ip, ua, ts) VALUES (?, ?, ?, ?, ?, datetime('now'))" ).bind( new URL(request.url).hostname, type, path, ip, request.headers.get('user-agent') || '' ).run(); } }); ``` D1 的表结构定义在 `schema.sql` 中。配套的分析仪表板位于 `dashboard/` 目录中。 ## API ### `tarpit(request, options?)` | 参数 | 类型 | 描述 | |---|---|---| | `request` | `Request` | Web 标准 Request 对象 | | `options.onTrap` | `function` | 回调函数:`(type, path, ip, request, data?) => void\|Promise` | | `options.ctx` | `object` | 包含 `waitUntil()` 的执行上下文(Cloudflare Workers) | | `options.xmlrpcMode` | `'fault' \| 'honeypot'` | 默认为 `'fault'`。`'honeypot'` 启用识别方法的 XML-RPC 回复(见上文)。 | | `options.slowDripMs` | `number` | 每次发送数据块的延迟覆盖。省略则使用默认的 100..500ms 抖动。设为 `0` 可完全禁用缓慢发送(仅用于测试)。 | 如果路径是 Bot 探测,则返回 `Response`;如果是合法请求,则返回 `null`。 ### `isBotPath(path)` 检查 URL 路径是否会触发陷阱。返回 `boolean`。 ``` import { isBotPath } from 'web-tarpit'; if (isBotPath('/wp-login.php')) { /* ... */ } ``` ### `expressTarpit(options?)` (来自 `web-tarpit/adapters`) Express/Connect 中间件。选项与 `tarpit()` 相同。 ### `nodeTarpit(options?)` (来自 `web-tarpit/adapters`) 为 Node.js `http.createServer` 返回 `(req, res) => boolean`。 ## 慢速发送原理 响应以 3 字节的数据块进行流式传输,每次间隔 100-500ms 的随机延迟。期望快速响应的扫描器会在数据缓慢流入时保持连接打开。 对于一个 1KB 的伪造 `.env` 文件:大约 330 个数据块,平均每个约 250ms = 每次扫描大约 **80 秒**。 响应头包含 `X-Powered-By: PHP/8.2.13` 和 `Server: Apache/2.4.57`,以让 Bot 相信它找到了一个真实的 PHP 应用程序。 ## 仪表板(可选) ![Tarpit 仪表板](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/34f9956ae2174906.png) `dashboard/` 目录包含一个独立的 Cloudflare Worker,它从 D1 读取数据并提供一个分析仪表板,展示陷阱统计信息、攻击类型、Top Bot IP 以及 30 天的活动图表。有关完整的部署说明,请参阅 [`dashboard/README.md`](dashboard/README.md)。 ## 构建工具 由 [Brian Crumrine](https://github.com/crumrine) 使用 [Claude Code](https://claude.com/claude-code) 设计并构建。 ## 许可证 MIT
标签:AppImage, Bot陷阱, Bun, CISA项目, CMS安全, Deno, Express, GNU通用公共许可证, Hono, JavaScript, MITM代理, Node.js, Request/Response, WAF, Web应用防火墙, Web标准, WordPress伪装, 中间件, 密码管理, 恶意爬虫防御, 数据可视化, 欺骗攻击者, 漏洞扫描防御, 程序员工具, 缓慢响应, 网络安全, 自定义脚本, 蜜罐, 证书利用, 隐私保护, 零依赖