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

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

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

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
AfterLife — 撤销持久化检测实验:当密码重置成功但攻击者从未离开时。复现 Strapi CVE-2026-22706 条件撤销漏洞、其修复方案、一个三规则检测包,以及会漏报该漏洞的朴素规则。 | Kitploit
工具/GitHubGitHub/het-p301204/afterlife
防御工具漏洞分析Web安全身份验证学习与教育红队事件响应实验室与实践
GitHubhet-p301204/afterlife

AfterLife

撤销持久化检测实验:当密码重置成功但攻击者从未离开时。复现 Strapi CVE-2026-22706 条件撤销漏洞、其修复方案、一个三规则检测包,以及会漏报该漏洞的朴素规则。

查看仓库
1921天前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

AFTERLIFE

撤销持久化检测实验室

当密码重置成功,但攻击者从未离开。

一个针对单一漏洞类别的本地红/蓝实验室:凭证的生命周期超出了本应终结它的事件。 它提供了漏洞利用、根本原因、修复方案、三规则检测包、针对规则在结构上无法看到的内容的状态审计、一个取证控制台——以及那条不起作用的检测规则,保留在仓库中以便演示其失败。

CI tests python rules OWASP CWE license

快速开始 · 发现 · 为什么朴素检测会失败 · 规则包 · 控制台 · 修复方案 · 矩阵 · 测试 · 文档


针对两种实现的同一攻击。每个凭证一根条形,从签发到消亡,按谱系分组。虚线是密码更改。在易受攻击模式下,五根条形越过它并继续延伸;在修复模式下,被盗谱系中的每根条形都在那里停止。

同一攻击。同样的请求。唯一的区别。 由 scripts/figures.py 根据控制台绘制的同一载荷生成——在 CI 中重新生成并比对差异,因此图表不会与代码脱节。


未能遏制攻击的遏制操作```text

09:00 alice logs in ┐ refresh credential rt-001 │ the attacker steals rt-001 ┘

10:00 alice changes her password ← the one thing a victim can do alone HTTP 200 · password changed · fresh session issued

10:00:03 attacker: POST /refresh rt-002 → HTTP 200 new access credential at-004, issued 10:00:03

10:01:00 attacker: GET /me at-004 → HTTP 200 {"username": "alice", "authenticated": true}

没有错误。没有异常。没有可计数的失败认证。攻击者的访问凭证*只有三秒大*,并且是由服务器在重置后根据请求生成的。

以下是整个漏洞:```python
def _revoke_for_security_change(self, user, kind, device_id):
    if device_id:
        revoke_credentials(user, device_id=device_id)   # ← the finding

以审阅者的方式去读。撤销逻辑就在那里。它用正确的范围调用了正确的函数。它周围的端点更新了密码哈希,返回 200,并签发了一个新的会话——一次正确的密码更改所应具备的每一个可观察行为都出现了。

而如果调用方省略了 device_id,则什么都不会被撤销,而端点仍然报告成功。

这不是假设。这就是 CVE-2026-22706 在 Strapi ≤ 5.33.2 中的情况,其中刷新令牌失效步骤取决于调用方提供的 deviceId。评分为 2.1,低危。讨论见 下文。


为什么这很重要

评分之所以低,是因为攻击者已经拥有访问权限——这是进入条件,而这个漏洞并没有授予任何新的东西。它授予的是持续时间,并且是通过破坏受害者自己能够操作的唯一控制来实现的。

  • 每一份账户接管运行手册都以重置密码开始。每个产品都告诉用户同样的事情。
  • 当它静默失败时,受害者被告知问题已解决,并停止寻找——这关闭了账户接管中最重要的检测信号:用户注意到。
  • 持久化窗口是刷新凭据的生命周期:默认 30 天,通过轮换可无限续期。 test_persistence_lasts_as_long_as_the_refresh_credential 模拟了七天的时间来展示这一点。
  • 用户没有第二个可以采取的操作。第二次更改密码与第一次的效果完全相同。

遏制路径中的低危漏洞比功能路径中的低危漏洞代价更高,因为代价是在事件期间付出的,而那时没人在读安全公告。


朴素检测器

你最先写下的规则:```text IF credential.issued_at < credential_change.timestamp: ALERT

这不是一条愚蠢的规则。它成本低,只需要一个字段,读起来就像问题的定义,而且**在简单情况下是正确的**——攻击者在重置后使用窃取的*访问*令牌会被抓住。
`test_the_naive_rule_catches_the_simple_case` 断言它有效。

两条规则针对同一凭证提出同一个问题。它们读取不同的字段来回答,而这两个字段相互矛盾:

![两行,每个字段一行。credential.issued_at 显示为 10:00:03,即变更后三秒,并得出结论认为该凭证看起来干净。lineage.root_issued_at 显示为 09:00:00,即变更前一小时,并发出警报。](https://raw.githubusercontent.com/het-p301204/afterlife/main/docs/figures/two-fields.svg)

**三秒之后,还是一小时之前——同一凭证,同一时刻。** 朴素规则询问的是攻击者控制的字段,而一次 `POST /refresh` 就能将其重置。

在请求日志上运行它,这才是这个查询实际被写入的地方,因为请求日志才是你拥有的东西:```text
NAIVE DETECTOR (NAIVE-001), over the request log

  Result: NO ALERT

  Six requests were served to the attacker after the reset. Every one of them
  carried at-004, minted at 10:00:03 -- three seconds *after* the password
  change. By its own timestamp it is the newest credential on the account.

就此止步固然轻松,却不诚实,因此实验室还运行了最公平版本的朴素规则——将其扩展至同时监控刷新端点:```text NAIVE DETECTOR, widened to include POST /refresh

1 alert at 2026-09-11T10:00:03.000Z: the credential presented to /refresh was rt-002, issued 2026-09-11T09:30:00.000Z. Then it goes blind. 6 events follow that hop and it flags none of them, because every credential from there on carries a post-reset timestamp. Its incident covers 1 accepted request; the lineage rule's covers all of them.

And look at what the alert names: NAIVE-001 revoke rt-002 -- rotated away and already dead at 10:00:03 AFTERLIFE-001 revoke lin-001 -- the live thing every future credential descends from

真正重要的是凌晨三点时的差异。朴素规则只捕捉到调用链越过边界的那一瞬间,随后在剩下的29天里丢失了线索——而它所指认的凭证*早已被服务器轮换并吊销*。吊销它毫无意义。`lin-001` 才是你必须清除的对象。

**而且朴素规则并不缺乏遥测数据。** 它使用相同的事件流、相同的血缘索引、相同的容差、相同的去重机制和相同的有限状态。它只覆盖了一个方法:```python
class Correlator:                                  # AFTERLIFE-001
    def _age_reference(self, facts):
        return facts.root_issued_at

class NaiveCorrelator(Correlator):                 # NAIVE-001
    def _age_reference(self, facts):
        return facts.issued_at

root_issued_at 就位于它已经在查询的索引中。 test_the_naive_rule_had_the_data_it_needed 证明了这一点。问题出在 比较上,而不是日志记录。


规则包

三条规则作用于同一份日志。它们回答不同的问题,并且按照事件实际展开的 顺序触发。

规则严重级别回答触发时机
AFTERLIFE-002刷新凭证重用CRITICAL / MEDIUM它是否被盗用?在重用时
AFTERLIFE-003安全变更时的不完整吊销HIGH / LOW遏制措施是否执行?在变更时——无需攻击者
AFTERLIFE-001吊销后凭证谱系使用HIGH是否使用了过期的谱系?在首次接受时
RULE PACK

10:00:00 HIGH AFTERLIFE-003 Incomplete revocation at a security change 10:00:03 HIGH AFTERLIFE-001 Post-revocation credential lineage use

**这种排序是这个仓库中最有用的东西。** AFTERLIFE-003
在变更落地的瞬间触发,比攻击者触碰任何东西早三秒,因为它所需的证据已经完整:日志说明了哪些谱系在进入时是活跃的,并且没有说明它们已被撤销。

它不需要受害者,也不需要利用。它会在任何用户执行的第一次密码重置时报告该缺陷——这使它成为你在预发布环境中运行的那一个,那里没有攻击者需要等待。AFTERLIFE-001 告诉你入侵正在进行;AFTERLIFE-003 告诉你你的遏制控制已失效。

![两张告警卡片。AFTERLIFE-003 在 10:00:00 报告判定结果为 no_containment,水印未记录,范围为 none,且 lin-001 存活。AFTERLIFE-001 在 10:00:03 报告凭据 rt-002,其 root 在变更前一小时签发。](https://raw.githubusercontent.com/het-p301204/afterlife/main/docs/figures/findings-vulnerable.svg)

`application recorded watermark: no` 是引导事件响应人员指向*缺陷*而非症状的字段。

### 规则使用的水印不是应用程序报告的那个

凭据变更事件携带一个 `revocation_watermark` 字段——即应用程序写入的 `credentials_valid_after` 值。**在易受攻击的实现中它是 `null`,因为应用程序从未写入过。** 这就是那个 bug。

因此,以该字段为键的规则将恰好对它存在所要捕获的情况视而不见。规则锚定在事件自身的 `timestamp` 上,无论应用程序是否履行了职责,该时间戳都是真实的,并将缺失的字段作为证据报告。

### 属性```text
  deduplication        6 accepted requests on the stale lineage -> 1 alert
  event order          shuffled stream -> same alert  (1 alert)
  duplicate telemetry  log replayed twice -> 1 alert  (24 duplicate events discarded)
  false positives      the fixed implementation's log -> 0 alerts
  bounded state        caps at 256 activity/user, 2000 users, 20000 credentials

顺序无关性不是“基本能用”: test_6b_every_permutation_of_the_critical_events_detects 会运行四个关键事件的全部 24 种排列,并要求每种排列恰好产生一个告警。 去重以 (user_id, credential_change_event_id, lineage_id) 为键, 并在其前面加上 event_id 抑制,这样重放的文件就无法虚增计数。

完整规则卡片、所需遥测数据和响应运行手册: docs/detection.md。


控制台

一个用于回答本实验所关注的那个问题的阅读界面。不是告警计数的仪表盘——而是一个死亡登记册。每个凭据一根条形,从签发到死亡,按其所继承的血统分组,密码更改被画成一条线,之前的一切本应终止于此。

漏洞模式下的完整 AFTERLIFE 控制台:报头、衬线字体的裁决、五格计数器条、双字段对比、带有五根条形穿过断头台的生命线图,以及两张告警卡片。

下载工具