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

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

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

订阅源联系隐私© 2026 Kitploit

工具目录

分类

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

alibi

11751天前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

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

查看仓库

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

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

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

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

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

规则

规则条件严重性
ORPHAN接收真实请求,但代码中不存在high
LIVE_UNDOC接收真实请求,但没有任何契约描述high
SHADOW在代码中,不在任何契约中medium
DANGLING一条网关规则,但未到达任何已实现的内容medium
DRIFT为部署而声明,但代码中缺失medium
PHANTOM在契约中,不在代码中low
UNEXPOSED已实现,但没有任何网关规则到达它low
COLD已实现,从未见过接收请求info

严重性随后会根据 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 作为一次性使用。被抑制的发现会被计数并打印计数——一个悄悄丢弃发现的工具比一个打印过多的工具更糟糕,因为再也无法分辨它隐瞒了什么。

状态

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

针对五个仓库的测量:

仓库codedoc已印证发现code↔doc
casdoor372235230 (98%)139已比较
netbox11461193796 (67%)746已比较
argo-cd59198131已搁置
authentik23111931192已搁置
flipt24200已搁置

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

NetBox 是有启发性的那个。它在一个仓库中持有两个攻击面:一个服务器渲染的 Web UI 和一个 DRF 路由的 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 自己的路由器子类添加到每个列表端点的批量操作,任何 urlconf 遍历都无法看到。

另外三个被搁置,每个都有值得了解的原因:

下载工具