Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
pfsense-api-snort-file-join — pfSense Plus MIM API 工具包 b4acd7ca - 高危 - 远程 - 文件读取 - Snort 规则 {file} 先解码再拼接 | Kitploit
工具/GitHubGitHub/abraxas/pfsense-api-snort-file-join
漏洞分析漏洞利用Web应用程序漏洞利用信息收集Web安全渗透测试API 安全实验室与实践

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
GitHub
abraxas/pfsense-api-snort-file-join

pfsense-api-snort-file-join

pfSense Plus MIM API 工具包 b4acd7ca - 高危 - 远程 - 文件读取 - Snort 规则 {file} 先解码再拼接

查看仓库
11天前尚未审核
分享

Abraxas Labs - pfsense-api-snort-file-join

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  pfsense-api-snort-file-join

pfsense-api-snort-file-join

类别: 文件读取 可达性: 远程

pfSense Plus MIM API(Netgate/pfsense-api b4acd7ca)- Netgate

GET /services/snort/rules/{name}/{file} 接受两个路径参数,均为 type: string,无 pattern。描述:检查规则集中的文件。SnortRuleFileContents.filename 为“文件路径”。生成的 get_snort_ruleset_file._get_kwargs 执行 quote(str(...), safe=""),因此 ../ 在传输中变为 ..%2F。服务器若先进行 URL 解码再拼接进规则集目录,仍可跳出该目录。

能够 GET 该路径的调用者,加上 fleet JWT,即可在每台已注册设备上以 MIM agent 身份读取指定规则集之外的文件。且拼接操作并未执行。该实验环境是公开路径的“先解码后拼接”利用组件。

这是 9 个遗留问题中的第 8 个。地图:pfsense-api-nexus-mim。同一固定版本的遗留问题:fleet JWT。这不是 jaredhendrickson/pfsense-api。

ID暂无 CVE
类别文件读取(Snort {file} 先解码后拼接)
可达性远程(已认证 GET;fleet JWT 在每个 device_id 上复用同一路径)
CWECWE-22
CVSS高危:6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N,针对可 GET Snort 规则集文件的 JWT
产品Netgate/pfsense-api(pfSense Plus Nexus MIM 控制器 OpenAPI + 生成的客户端)
受影响版本main b4acd7ca21dbca739a530403a1f62a7440f7726f(2026-05-25,Add Snort-3 API definitions)
认证示例在 POST /login 后发送控制器 JWT。OpenAPI 无 securitySchemes。未认证情况未经验证。
许可证GNU Affero GPL v3.0
实验环境仅 127.0.0.1:19181。先解码后拼接利用组件。拼接操作未执行。

攻击者能做什么

需要一个能够 GET /services/snort/rules/{name}/{file} 的调用者。官方示例在 POST /login 后使用 Authorization: Bearer,然后将该令牌作为 base_url=.../api/device/pfsense/{device_id}/api 重放,用于 GET /mim/devices 返回的每个 id。生成的操作为 AuthenticatedClient | Client 类型。此 GET 请求不涉及 CSRF。

方法汇聚点权限实验室验证 vs 推断
生成的客户端 GET 请求,带 {file}=../../oracle/WITNESS(线上为 ..%2F..%2Foracle%2FWITNESS)解码 unquote(file) 后拼接到指定的规则集目录并读取侦察: HTTP 200,filename 为 /oracle/WITNESS,响应体为 PFSENSE-API-SNORT-FILE-JOIN-WITNESS。预期是该规则集内的一个 .rules 文件。实验室验证(gadget)。拼接未被执行。
同样的 GET 请求,带 {file}=../../../etc/passwd如果控制器将其映射到设备文件系统,则同样的拼接侦察: 以 MIM 代理身份读取主机文件(Plus WebGUI/PHP 通常为 root)。实验室使用 /oracle/WITNESS,而非真实的 /etc/passwd。推断(同样的拼接,主机路径)。
在 fleet JWT 之后执行同样的 GET 请求(POST /login 一次,在 /api/device/pfsense/{id}/api 上重放)同一未受限 {file} 的设备代理侦察: 一个 helpdesk 形态的控制器令牌即可读取所有已注册设备上的文件,而不仅仅是登录所针对的那一台。推断(G6 契约 + 此路径)。RBAC 未被执行。
同样的遗留问题出现在 {name} 上GET|DELETE /services/snort/rules/{name} 以及同级的 address/suppress {name} 也是未受限字符串侦察 / 完整性: 重命名或删除名称是路径的规则集。根据规范推断。实验室仅驱动了 {file}。
对同一线上路径的受限控制解码后执行 relative_to(ruleset_dir.resolve())已关闭。HTTP 400,无见证。实验室验证
正常的 {file}=local.rules预期的规则集读取已关闭。200,sid:1,无见证,朴素与对照均如此。实验室验证

相邻已关闭项: 客户端对 ../ 的百分号编码(encoding=%2F)。解码后的控制拼接(control-confined=yes)。Plus 控制器拼接(plus-join-not-executed)。规则集 foo 内对 local.rules 的预期读取。未认证 GET(未证实;示例发送 Bearer)。POST /services/snort/rules 归档 / 植入 .so(预期的 IDS 管理员操作,非此遗留问题)。诊断 PHP/shell。文件写入。主机 shell。此遗留问题不是 RCE。

我是如何发现的

我固定了 Netgate/pfsense-api 的 b4acd7ca21dbca739a530403a1f62a7440f7726f,因为 2026-10-14 的 HEAD 没有标签,且最新提交是 "Add Snort-3 API definitions"。这条路径就是这样存在的。YAML 中任何地方都没有 pattern: 键。{name} 和 {file} 是未受限字符串。quote(..., safe="") 是客户端编码器,不是服务端 basedir 检查。

  /services/snort/rules/{name}/{file}:
    parameters:
      - in: path
        name: name
        required: true
        schema:
          type: string
      - in: path
        name: file
        required: true
        schema:
          type: string
    get:
      description: Obtain the contents of the specified file in the ruleset. This is intended for inspecting scripts provided by it.
      operationId: GetSnortRulesetFile
"url": "/services/snort/rules/{name}/{file}".format(
    name=quote(str(name), safe=""),
    file=quote(str(file), safe=""),
),

已记录的错误转向:将客户端编码视为闭合遍历;组合 pfSense Plus;将 Snort 归档 .so 排序为此残留物;声称存在未认证 GET。剧场:反向 shell。预言机是 /oracle/WITNESS 的 gadget 200 加上 control 400。

实验环境

python3 pfsense-api-snort-file-join-Abraxas-Labs.py

或

cd lab
./run.sh

仅针对 http://127.0.0.1:19181。Compose 项目 pfsense-api-snort-file-join。公共路径的 decode-then-join gadget。Plus join 未被执行。运行后栈被拆除。

SUCCESS PFSENSE-API-SNORT-FILE-JOIN encoding=%2F decode-then-join=yes control-confined=yes plus-join-not-executed PFSENSE-API-SNORT-FILE-JOIN-WITNESS

../../../etc/passwd 的客户端编码为 ..%2F..%2F..%2Fetc%2Fpasswd。对 /services/snort/rules/foo/..%2F..%2Foracle%2FWITNESS 的朴素 GET 请求返回 200,文件名为 /oracle/WITNESS,响应体为 PFSENSE-API-SNORT-FILE-JOIN-WITNESS。在受限控制下,同一请求在规则集根目录下解析,返回 400 且无见证。良性的 local.rules 保持在 foo 内。

修复

解码后在规则集根目录下解析。拒绝 .. 和绝对路径。在读取之前,先 Path.resolve() 再 relative_to(ruleset_dir.resolve()),或等效操作。在 OpenAPI 中将 {file}(以及 {name})约束为规则集安全模式,以便生成器停止发送路径形状的字符串。

参考

  • 系列地图:pfsense-api-nexus-mim
  • 同一 pin,fleet token:pfsense-api-fleet-jwt
  • github.com/Netgate/pfsense-api b4acd7ca21dbca739a530403a1f62a7440f7726f
  • pfapi_openapi.yml /services/snort/rules/{name}/{file}
  • get_snort_ruleset_file.py
  • CWE-22

许可证

GNU Affero GPL v3.0。参见 LICENSE。仅限回环实验室。无担保。

下载工具