Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

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

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

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

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

alibi

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

10122天前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
查看仓库

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 版本。较旧的二进制文件会被按名称拒绝,而不是留到第一次读取目录时才失败。

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

使用

root@kitploit:~
$ alibi scan                                      # the working directory
$ alibi scan ./service ./contracts ./prod.har     # or wherever the views live

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

root@kitploit:~
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 包含全部内容。

在 CI 中

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

查看每个视图包含的内容

报告说各视图不一致;--endpoints 说明每个视图包含的内容。

root@kitploit:~
$ alibi scan ./repo -f json --endpoints

每个视图都会得到一个列表:键、哪些视图为其背书、背后的技术、文件,以及规范化之前的拼写——当两行本应匹配却没有匹配时,差异总是在这里。它是其余载荷的三到四倍,因此它是一个标志而不是默认值。

或者直接设置门禁:alibi scan . ./contracts --fail-on high 在发现达到该严重级别时以非零退出。noir 无法完整读取的扫描会报告 executionSuccessful: false,因此降级的运行不会作为干净的运行通过。

端点如何匹配

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

root@kitploit:~
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,或代码读取器丢弃的挂载——它会被报告,从不被应用,因为重新对齐路径会隐藏它发现的 bug。

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

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

停止运行的规则没有解决任何问题。 记录扫描并比较它们会在远处重新引入同样的错误:一次运行忘记 contracts 目录,SHADOW 就什么都不评估,对于朴素的差异来说,这看起来完全像每个影子 API 都已被关闭。在五视图夹具上,去掉一个参数将七个持续存在的发现变成了“已解决”。快照记录哪些规则被评估,差异只考虑在两次扫描中都运行的规则,其余的在 NOT COMPARED 下列出。

只有当信号存在时,缺失才是证据。 Noir 的认证标记器覆盖它们知道的框架。在它们不覆盖的栈中,没有任何东西携带认证标记,将其视为“未认证”会提升每个发现并抽干严重性列的意义。在缺失标记上触发的调整要求该标记首先出现在扫描中的某处。

规则

严重性随后会根据 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:

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

或者传递 --ignore REGEX 用于一次性使用。被抑制的发现会被计数并打印计数——一个悄悄丢弃发现的工具比一个打印过多的工具更糟糕,因为再也无法分辨它扣留了什么。

状态

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

针对五个仓库测量:

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

NetBox 是有启发性的那个。它在一个仓库中持有两个攻击面:一个服务器渲染的 Web UI 和一个 DRF 路由器 REST API,只有后者被文档化。整体扫描时它报告 746 个发现,其中大多数是真实但无用的观察,即 Web UI 不在 API 规范中。限定到契约描述的攻击面后,它坍缩为真正值得说的内容:

root@kitploit:~
$ alibi scan ./netbox --ignore '^/(?!api(/|$))'

→ 3 个影子 API:/api/plugins、/api/schema/redoc、/api/schema/swagger-ui,这三个都确实被服务且确实不在 schema 中。剩下的 397 个幻影是 NetBox 自己的路由器子类添加到每个列表端点的批量操作,任何 urlconf 遍历都看不到。

其他三个被扣留,每个都有值得知道的原因:

  • Argo CD 在 Go 中注册 /api 并在其下记录 198 个路径——同一攻击面的两种粒度。
  • authentik 在运行时通过导入每个已安装应用的 urls 模块来组装其 URLconf,任何静态读取器都无法跟随。
  • flipt 挂载一个 gRPC 网关;其 Go 源代码持有一个路由。它的 HTTP 攻击面在 .proto 注解中实现,这就是为什么 grpc 代表代码视图:归档在那里,其 36 个文档化路径中有 36 个相互印证。

这就是本工具的上限,直白地说:它比较 noir 能读取的内容,而以错误粒度读取的视图比完全不读取更糟糕。上面的大部分机制存在是为了区分这些,而不是将它们报告为缺陷。

许可证

MIT

下载工具
规则条件严重性
ORPHAN接收真实请求,但代码中不存在high
LIVE_UNDOC接收真实请求,但没有任何契约描述high
SHADOW在代码中,不在任何契约中medium
DANGLING网关规则到达不了任何已实现的东西medium
DRIFT为部署而声明,但代码中缺失medium
PHANTOM在契约中,不在代码中low
UNEXPOSED已实现,但没有网关规则到达它low
COLD已实现,从未见过接收请求info
仓库codedoc相互印证发现code↔doc
casdoor372235230 (98%)139已比较
netbox11461193796 (67%)746已比较
argo-cd59198131已扣留
authentik23111931192已扣留
flipt24200已扣留