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

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

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

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
alibi — 交叉检查攻击面视图,找出无法相互印证的端点。 | Kitploit
工具/GitHubGitHub/owasp-noir/alibi
防御工具侦察静态分析漏洞分析代码分析配置审计信息收集Web安全DevSecOpsAPI 安全
GitHubowasp-noir/alibi

alibi

11878天前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

交叉检查攻击面视图,找出无法相互印证的端点。

查看仓库

alibi

交叉核对攻击面的各个视图,找出无法相互印证的端点。

一个端点应当能够自证其存在。它存在于代码中,因此应当有契约来描述它。它存在于契约中,因此应当有实现来落实它。它承载真实流量,因此它最好在某个地方真实存在。当某个视图知道某个端点而其他视图不知道时,这个缺口就是发现。

alibi 运行 OWASP noir,读取其 JSON,并将各个视图相互比对。

为什么这是一个独立的工具

Noir 已经读取同一攻击面的五个独立视图:

视图读取来源
code覆盖 33 种语言的 200 多个分析器
docOpenAPI、RAML、WSDL、GraphQL SDL、AsyncAPI、gRPC、Smithy、TypeSpec、OData、OpenRPC
trafficHAR、mitmproxy、Burp、Caido、ZAP、Postman、Insomnia、Bruno、.http
gatewaynginx、Apache、Envoy、Kong、Traefik、APISIX、Caddy、Istio、Kubernetes Ingress 和 Gateway API
infraTerraform、CloudFormation、CDK、Serverless、Vercel、Netlify、Wrangler、Azure Functions、Kamal

它不做的是将它们相互比对。而这正是本工具的全部工作,并且无需对 noir 做任何改动——alibi 为每个视图运行一次 noir,然后合并结果。

按视图分别处理这一点很重要。Noir 会跨所有分析器按 (method, url) 去重,因此一个 Flask 路由和一个拼写相同的 OpenAPI 路径会合并为一个端点,只携带一种技术。对于发现工具来说这是正确的——它就是一个端点——但它抹去了本工具旨在衡量的相互印证,而且抹去的方向恰恰是最糟糕的:两个视图越是一致,消失的端点就越多。Casdoor 扫描出 372 个代码端点和 9 个已记录端点;仅扫描其 swagger/ 目录,规范中就有 235 个。

--only-techs 限制检测器池,因此每个视图扫描一次即可保持每个视图完整。哪种技术代表哪个视图由 views.yml 定义;存在哪些技术则由 noir list techs 报告的内容决定。

alibi 不自行解析任何 API 格式。它唯一的输入是 noir 的 JSON。

安装

需要在 PATH 上安装 noir 1.0.0 或更新版本——正是该版本将 noir list techs 变为子命令,而该目录正是将每种技术分配到视图的依据。开发版跟踪当前 noir 发布版。较旧的二进制文件会按名称被拒绝,而不是留待其在首次读取目录时失败。

$ uv tool install noir-alibi     # or: pipx install noir-alibi
$ alibi scan ./my-service

使用

$ alibi scan                                      # the working directory
$ alibi scan ./service ./contracts ./prod.har     # or wherever the views live

每个路径都是一个来源,每个视图扫描一次。将其指向你手头拥有的任何内容——源代码树、规范目录、单个捕获文件——你缺失的视图会关闭其规则,而不是淹没报告。

alibi  ·  1 source  ·  377 endpoints

  code 372   doc 235

  230 corroborated -- vouched for by more than one view

  19 endpoints nearly matched another view -- these may be matching failures, not real gaps

SHADOW  Shadow API -- Implemented, but no contract describes it
  134 findings  ·  4 critical, 57 high, 62 medium, 11 low

  critical POST    /api/upload-groups        router.go:87
           upload paths carry more consequence than reads
  critical POST    /api/upload-permissions   router.go:208
  ...
  ... and 122 more (SHADOW in full: -f json)

TWO SURFACES?
  The doc view is 97% under /api, and 37 of these findings are outside it.
  If that is a separate surface the contract never covered, narrow the scan:
    alibi scan <paths> --ignore '^/(?!api(/|$))'
  If it is the same surface left undocumented, they are the findings that matter most.

分组最多到十二个——排序是最差优先,因此尾部是信息量最少的部分,而 -f json 包含全部内容。

noir 的标志放在裸 -- 之后,或通过 --noir-arg 传入。诸如 --exclude-path 之类的过滤器没有问题;会替换 JSON 契约或破坏 alibi 逐视图扫描的标志(--format、--diff-*、--only-techs 等)会被拒绝,并以退出状态 2 结束。

在 CI 中

- run: alibi scan . ./contracts -f sarif > alibi.sarif
- uses: github/codeql-action/upload-sarif@v3
  with: { sarif_file: alibi.sarif }

查看每个视图包含的内容

报告指出各视图之间存在分歧;--endpoints 则说明每个视图各自包含的内容。

$ alibi scan ./repo -f json --endpoints

每个视图都会得到一个列表:键、为其担保的视图、其背后的技术、文件,以及规范化之前的拼写——当两行本应匹配却未能匹配时,差异总是出现在这里。它的大小是其余载荷的三到四倍,因此它是一个标志,而非默认项。

或者直接设置门禁:alibi scan . ./contracts --fail-on high 在发现项达到该严重级别时以非零状态退出。noir 无法完整读取的扫描会报告 executionSuccessful: false,因此降级的运行不会被当作干净的运行。被有意跳过的符号链接、二进制文件或镜像不计入其中。

端点如何匹配

Noir 保留每个框架自身的路由语法,而不是发明一种通用语法,因此同一个端点会以多种拼写形式出现:

python_flask   /api/users/<int:user_id>
aiohttp        /users/{id}
java_spring    /api/catalog/{id}
oas3           /v1/pets/{petId}
rails          /posts/:id
nginx          /admin/.*

让这些结果具有可比性的规则是:路径参数的名称不属于其身份的一部分。 {petId} 和 <int:user_id> 描述的是同一个槽位;只有它的位置以及它是否跨越 / 才是关键。名称作为证据被保留并报告,但永远不会进入键中。

发现结果会说明匹配是如何完成的:

等级含义
G1拼写已经一致
G2参数语法规范化后一致
G0只有一个视图包含它——没有匹配到任何内容

如何保持诚实

像这样的工具,要么在首次运行时报告数百条发现结果而失败,要么报告无人取得的进展而失败。有六件事对此形成制约:

规则不会在缺少任一视图时触发。 扫描一个完全没有契约的代码库,每个端点从技术上讲都符合未记录影子 API 的条件。这些发现结果除了说明你没有提供任何文档之外,什么也说明不了,因此只有当规则所推理的每个视图都实际参与了扫描时,规则才会运行。报告会列出未参与运行的规则。

近似匹配被报告为存疑,而不是发现结果。 “在代码中,不在文档中”与“两者都有,但 alibi 未能将它们对齐”无法区分。因此,落入一个视图的端点会与其他视图进行近似匹配检查——相同路径但动词不同,或相差一个路径段,其中一侧是参数而另一侧是字面量。带有近似匹配的发现结果会被降级并标记为待审查。该计数与总数并列显示,因为每条发现结果的可信度取决于它有多小。

从未相遇的视图是一条诊断,而不是数百条发现结果。 Argo CD 在 Go 中注册了 /api,并在其下记录了 198 条路径,因此它的代码和它的规范没有一个共享的端点。按字面理解,那就是 58 个影子 API 和 198 个幻影契约,没有一个是真实的。两个有内容的视图之间零佐证意味着比较没有生效——一个挂载点代替了其下的路由,或者一个 noir 无法读取的栈——因此规则被搁置,转而打印原因。那些最终发现其下有许多来自其他视图的端点的路径,会被标记为可能的挂载点。

当两个视图在去掉其中一个的常量前缀后确实对齐时,诊断会说明这一点并指出该前缀。Gitea 生成的规范声明 basePath: /GITEA-API-APP-SUBURL/api/v1,而其 Go 路由器挂载的是 /api/v1;两个视图没有任何共享内容,但去掉这三个路径段后,535 条已记录路径中有 154 条与代码路径匹配。那是一个规范 basePath、一个 servers[].url,或代码读取器丢弃的一个挂载点——它会被报告,但绝不会被应用,因为重新对齐路径会隐藏它发现的缺陷。

一个实际上只是缺失子树的洪流会被命名为一个:NodeBB 的 354 个幻影契约中有 207 个位于 /api/v3 之下,而代码视图在那里什么都没有。

缺失的视图和空视图意味着相反的事情。 Noir 报告它无法读取的内容,alibi 会在发现结果上方打印该信息。NetBox 附带一个 12.35MB 的 OpenAPI 文档,包含 308 条路径;noir 因超过其文件大小上限而跳过它,如果没有该报告,alibi 会声称该项目没有记录任何内容——不仅仅是记录不完整,而是自信地给出了错误答案。

停止运行的规则并没有解决任何问题。 记录扫描并比较它们会在距离上重新引入同样的错误:在一次运行中忘记契约目录,SHADOW 就不会评估任何内容,而在朴素的差异看来,这恰恰就像每个影子 API 都已被关闭。在五视图夹具上,丢弃一个参数将七条现存发现结果变成了“已解决”。快照记录哪些规则进行了评估,差异只考虑在两次扫描中都运行的规则,其余规则在 NOT COMPARED 下列出。

缺失只有在信号存在时才算证据。 Noir 的认证标记器 只覆盖它们所了解的框架。在它们不覆盖的技术栈中,没有任何内容带有 认证标记,而将其视为“未认证”会提升每一个发现的严重性,并使严重性列 失去意义。针对缺失标记触发的调整,要求该标记首先出现在扫描中的某处。

规则

规则条件严重性
ORPHAN接收真实请求,但未出现在代码中高
LIVE_UNDOC接收真实请求,但没有任何契约描述高
SHADOW在代码中,但不在任何契约中中
DANGLING网关规则指向未实现的任何内容中
DRIFT为部署而声明,但未出现在代码中中
PHANTOM在契约中,但不在代码中低
UNEXPOSED已实现,但没有任何网关规则到达它低
COLD已实现,但从未见过接收请求信息

随后严重性会根据 noir 的标记器所发现的内容进行调整:个人数据、文件上传、 无认证迹象,或会改变状态的方法。

视图映射(views.yml)和规则(rules.yml)都是数据,而非代码。

网关不是端点列表

一个 location /api/ 代表其下的所有内容,因此网关和 基础设施规则回答的是这是否到达该端点,而不是这是否包含它。 按集合比较时,每条前缀规则看起来都像没人实现的路由,而每条已实现的路由 看起来都不可达。

覆盖范围被有意放宽。Noir 报告规则匹配的路径,但不报告 它是作为前缀匹配还是精确匹配(location = /x、Ingress pathType: Exact),因此无法还原精确性——而将每条规则 都视为前缀会抑制发现,而不是凭空捏造发现。

报告会说明每个路由视图覆盖了多少代码,因为 “34 个端点没有网关到达”是否真实,取决于该配置 是否正是为该服务提供前端的那一个。没有阈值能诚实地 区分这些:Argo CD 的 e2e 测试夹具覆盖其代码的 39%,而 NetBox 的真实配置覆盖 100%。

兜底规则——location /、位于 / 的 Ingress、RewriteRule ^(.*)$——无论哪种情况 都不算证据。它路由一切或什么都不路由,对每个 端点都一样,因此它被视为未到达其中任何一个。一个不包含其他内容的 网关视图没有可提供的信号,UNEXPOSED 会置身事外并说明这一点,而不是 将每个端点都报告为不可达。Casdoor 的 Helm chart 正是如此: 一条位于 / 的 Ingress 规则,若被当作证据,会产生 365 个发现。

流量必须是被观察到的

HAR 捕获记录的是实际发生过的请求。Postman 集合记录的是 某人打算发出的请求。ORPHAN、LIVE_UNDOC 和 COLD 都基于 实际运行的内容进行推理,因此它们要求有一个某人实际观察过的视图,并在 置身事外时说明这一点。

非 Web 表面不纳入

Noir 在同一列表中报告 CLI 参数、Kafka 主题和移动端深度链接。 cli://gitops-engine/agent 扁平化为 HTTP 后会变成 /agent——它会 与任何同名 Web 路由冲突,并被询问是否有网关 路由到它。协议属于端点的身份;http 和 https 属于同一空间,其他一切则各自保留自己的空间。

抑制

有些缺口是预期状态。在源代码旁放置一个 .alibi.yml:

ignore:
  - path: "^/internal/"
    why: internal-only admin surface
  - rule: UNEXPOSED
    path: "^/debug/"
    why: not fronted by the gateway in this repo

或传入 --ignore REGEX 进行一次性处理。被抑制的发现会被计数并打印出计数——一个悄悄丢弃发现的工具比一个打印过多发现的工具更糟糕,因为再也无法判断它隐瞒了什么。

状态

尚处早期,但所有五个视图都已比较。

针对五个仓库进行测量:

仓库codedoccorroboratedfindingscode↔doc
casdoor372235230 (98%)139已比较
netbox11461193796 (67%)746已比较
argo-cd59198131暂缓
authentik23111931192暂缓
flipt24200暂缓

Casdoor 是最干净的案例:其 235 个已记录端点中有 230 个与代码匹配,且完全没有路径规范化失败。 所有 19 个近似匹配都是同一路径在不同动词下——noir 在 Go catch-all 处理器上注册了每个方法,而不是匹配问题。

NetBox 则更具启发性。它在同一个仓库中持有两个表面:一个服务器渲染的 Web UI 和一个 DRF-router REST API,而只有后者被记录。整体扫描时它报告 746 个发现,其中大多数是真实但无用的观察,即 Web UI 不在 API 规范中。限定到契约所描述的表面后,它缩减为真正值得说的内容:

$ alibi scan ./netbox --ignore '^/(?!api(/|$))'

→ 3 个影子 API:/api/plugins、/api/schema/redoc、/api/schema/swagger-ui, 这三个都真实提供服务,且确实未出现在 schema 中。剩下的 397 个 幻影路径是 NetBox 自己的 router 子类为每个列表端点添加的批量操作, 任何 urlconf 遍历都无法看到。

另外三个被排除在外,每个都有值得了解的原因:

下载工具