C0oki3s/ssrf

GitHub: C0oki3s/ssrf

一个基于 Node.js 的 SSRF 请求防护模块,通过黑名单、白名单与 CIDR 规则阻止对内网资源的非法访问。

Stars: 1 | Forks: 0

## ssrf [![NPM Version](https://badgen.net/npm/v/ssrf)][download-url] ![LICENSE](https://badgen.net/badge/license/MIT/blue) ## 服务器端请求伪造(SSRF) 攻击者可以利用服务器上的功能来读取或更新内部资源。攻击者可以提供一个或修改一个 URL,服务器上的代码会读取或提交数据到该 URL,通过精心选择的 URL,攻击者可能能够读取服务器配置(如 AWS 元数据)、连接到内部服务(如启用的 HTTP 数据库)或向内部服务发送 POST 请求,而这些服务本不应被暴露 [阅读更多](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) ## 安装 `npm install ssrf` ## 用法 ``` // Back-compat usage (direct API) ssrf.options({ blacklist: "/ssrf/list.txt", // Linux; on Windows use 'C:\\Users\\host.txt' path: false }) const gotssrf = await ssrf.url("http://13.54.97.2") ``` ## ssrf.url() ssrf.url 返回 Promise,因此请在 try-catch 块中使用 `await ssrf.url("http://example.com")` ``` try{ const result = await ssrf.url(url) //do stuff if success }catch{ //do stuff if fail } ``` ### ssrf.options({}) options 接受两个参数 + blacklist + path #### blacklist blacklist 参数接受指向文本文件的绝对路径输入 示例: - /usr/list/blacklist.txt (Linux) - C:\\Users\\host.txt (Windows) 默认情况下没有黑名单,但如果用户传递了绝对路径,则会读取文件并在每次命中中间件时运行一个 for 循环 ##### 文件格式 ``` evil.com example.com 87.26.7.9 98.72.6.2 ``` #### path path 参数接受一个布尔值(true 或 false) 默认值为 True,这意味着它将返回 /path 和附加到 Host 的 ?parameters 示例:如果用户发送 `http://example.com/path1?param=1`,则返回 `http://example.com/path1?param=1` ##### True 返回绝对 URL `http://example.com/path1?param=1` ##### False 返回主机名 `http://example.com 或 http://www.example.com` 该模块防止来自保留字符 `@` 的攻击和 DNS 重新绑定攻击。要了解更多关于 DNS 重新绑定的信息,请参阅 [更多](https://github.com/C0oki3s/research/tree/main/DNS-Rebinding) ## 高级配置(CIDR、白名单、IP 输入) 该库现在支持使用主机名、IP 和 CIDR 范围设置允许/拒绝列表,来源可以是文件或数组,并接受原始 IP/主机输入。 示例: ``` const path = require('path') const ssrf = require('ssrf') ssrf.options({ // Load lists from files (one entry per line; supports host/IP/CIDR; lines starting with # are comments) blacklistFile: path.join(__dirname, 'blacklist.txt'), whitelistFile: path.join(__dirname, 'whitelist.txt'), // Or configure directly blacklistHosts: ['evil.com'], blacklistIPs: ['13.54.97.2'], blacklistCIDRs: ['10.0.0.0/8', 'fd00::/8'], whitelistHosts: ['api.example.com'], whitelistIPs: ['203.0.113.10'], whitelistCIDRs: ['203.0.113.0/24', '2001:db8::/32'], // Return only scheme+host when false (defaults to true for full URL) path: false }) // Inputs can be full URLs, hostnames, or raw IPs await ssrf.url('http://api.example.com/v1?q=1') // allowed if matches whitelist await ssrf.url('evil.com') // throws if blacklisted await ssrf.url('13.54.97.2') // throws if blacklisted or not whitelisted ``` 说明: - 仅允许 `http` 和 `https` 方案。 - 输入可以是完整 URL、主机名、原始 IPv4 或原始 IPv6。原始 IPv6 会规范化为括号形式(例如 `::1` -> `http://[::1]`)。 - 主机名会解析为所有 A/AAAA 记录,并对每个地址进行评估。 - 默认情况下会阻止私有、循环、链路本地、多播和保留 IP,除非明确通过 IP 或 CIDR 白名单。 - 如果提供了白名单,则目标必须匹配白名单;否则即使不在黑名单中也会被拒绝。 - IPv4 私有地址在以十六进制、八进制或单整数形式提供时也会被检测(例如 `0x7f000001`、`0177.0.0.1`、`2130706433`)。 ## Express 中间件 全局使用(整个应用): ``` const express = require('express') const ssrf = require('ssrf') const app = express() app.use(express.json()) app.use( ssrf.middleware( { // Lists from files or arrays // blacklistFile: 'C:\\lists\\deny.txt', whitelistHosts: ['api.example.com'], whitelistCIDRs: ['2001:db8::/32', '203.0.113.0/24'], blacklistCIDRs: ['10.0.0.0/8', 'fc00::/7'], path: false }, { source: 'body', // 'body' | 'query' | 'params' | 'headers' key: 'url', // field name in the chosen source attachKey: 'safeUrl', // attach approved URL to req.safeUrl replaceOriginal: false, blockOnError: true, // respond with 400 + JSON by default statusCode: 400, // onError: (errors, req, res, next) => { ...custom handler... } } ) ) app.post('/fetch', (req, res) => { res.json({ ok: true, safeUrl: req.safeUrl }) }) ``` 在端点级别使用(路由特定配置)并使用隔离实例: ``` const filesOnly = ssrf.create({ whitelistHosts: ['files.example.com'], path: true }) app.post('/upload', filesOnly.middleware({ source: 'query', key: 'target' }), (req, res) => { res.json({ ok: true, url: req.safeUrl }) }) ``` 直接使用隔离实例(无全局状态): ``` const instance = ssrf.create({ path: false }) try { const safe = await instance.url('example.com') // use safe } catch (e) { // e.message contains a JSON array of reasons } ``` ## 示例 - 完整的 Express 示例:`examples/express-server/server.js` - 应用级中间件:`app.use(ssrf.middleware(...))` - 路由级中间件(带隔离实例):`const inst = ssrf.create(...); app.post('/path', inst.middleware(...))` ## TypeScript 此包提供类型定义。在 TypeScript 项目中正常导入即可获得 options 和 middleware 的智能感知: ``` import ssrf = require('ssrf') const inst = ssrf.create({ path: false, whitelistCIDRs: ['2001:db8::/32'] }) const safe = await inst.url('example.com') ```
标签:GNU通用公共许可证, IP 黑名单, MITM代理, Node.js, NPM 模块, SSRF, Streamlit, URL 过滤, 中间件, 反绕过, 后端开发, 安全防护, 服务器端请求伪造, 漏洞防护, 私有 IP 过滤, 网络安全, 访问控制, 路径处理, 隐私保护