Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
AfterLife — 失効の永続化検出ラボ:パスワードリセットは成功したのに攻撃者が去らない場合。Strapi CVE-2026-22706 の条件付き失効バグ、その修正、3つのルールからなる検出パック、そしてそれを見逃す素朴なルールを再現します。 | Kitploit
ツール/GitHubGitHub/het-p301204/afterlife
防御ツール脆弱性分析ウェブセキュリティ認証学習と教育レッドチーミングインシデントレスポンスラボと実践
GitHubhet-p301204/afterlife

AfterLife

失効の永続化検出ラボ:パスワードリセットは成功したのに攻撃者が去らない場合。Strapi CVE-2026-22706 の条件付き失効バグ、その修正、3つのルールからなる検出パック、そしてそれを見逃す素朴なルールを再現します。

リポジトリを見る
1921日前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

AFTERLIFE

失効永続化検出ラボ

パスワードリセットが成功しても、攻撃者が去らないとき。

単一の脆弱性クラスに焦点を当てたローカルのレッド/ブルーラボ:本来それを無効化するはずの イベントよりも長く生き残る資格情報。 これにはエクスプロイト、根本原因、修正、3ルールの検出パック、ルールが構造的に見ることのできない ものを対象とした状態監査、フォレンジックコンソール — そして機能しない検出ルールが含まれ、 失敗を実演するためにリポジトリに保持されている。

CI tests python rules OWASP CWE license

クイックスタート · 発見事項 · なぜ素朴な検出は失敗するのか · ルールパック · コンソール · 修正 · マトリクス · テスト · ドキュメント


同じ攻撃を両方の実装に対して行ったもの。資格情報ごとに1本のバーで、発行から消滅までを系統ごとにグループ化している。破線はパスワード変更を表す。脆弱モードでは5本のバーがそれを越えて伸び続けるが、修正モードでは盗まれた系統のすべてのバーがそこで止まる。

同じ攻撃。同じリクエスト。違いは1つだけ。 コンソールが描画するのと同じペイロードから 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}

エラーなし。異常なし。数えるべき認証失敗もなし。攻撃者のアクセス資格情報は*3秒前*に生成されたもので、リセット後にサーバーが要求に応じて発行したものだ。

これが脆弱性のすべてである:```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 を省略した場合、何も失効されず、エンドポイントは依然として成功を報告する。

これは仮定の話ではない。Strapi ≤ 5.33.2 における CVE-2026-22706 であり、リフレッシュトークンの無効化ステップが呼び出し元が指定する deviceId に条件付けられていた。スコアは 2.1、Low。詳細は 後述。


なぜこれが重要か

スコアが低いのは、攻撃者がすでにアクセス権を持っていたからだ — それが侵入条件であり、このバグが新たに与えるものは何もない。このバグが与えるのは持続時間であり、それは被害者自身が操作できる唯一の制御を破壊することによってなされる。

  • すべてのアカウント乗っ取りのランブックはパスワードをリセットすることから始まる。すべての製品がユーザーに同じことを伝える。
  • それが静かに失敗すると、被害者には問題が解決したと伝えられ、探すのをやめる — これによりアカウント乗っ取りにおいて最も重要な検知シグナル、すなわちユーザーが気づくことがオフになる。
  • 持続ウィンドウはリフレッシュクレデンシャルの有効期間である: デフォルトで30日、ローテーションにより無期限に更新可能。 test_persistence_lasts_as_long_as_the_refresh_credential は7日間のシミュレートされた時間を辿ってそれを示す。
  • ユーザーが取れる第二のアクションはない。二度目のパスワード変更は一度目とまったく同じ効果しかない。

封じ込めパスにおける Low スコアのバグは、機能パスにおける Low スコアのバグよりもコストが高い。なぜならそのコストはインシデントの最中に支払われ、そのとき誰もアドバイザリを読んでいないからだ。


素朴な検出器

最初に書くルール:```text IF credential.issued_at < credential_change.timestamp: ALERT

これは愚かなルールではない。安価で、フィールドが1つで済み、問題の定義のように読め、そして**単純なケースについては正しい**——リセット後に盗まれた*アクセス*トークンを使う攻撃者は捕まる。
`test_the_naive_rule_catches_the_simple_case` はそれが機能することを主張している。

どちらのルールも、同じクレデンシャルについて同じ問いを立てている。答えを出すために異なるフィールドを読み、その2つのフィールドは食い違う:

![2つの行、フィールドごとに1つ。credential.issued_at は 10:00:03、変更の3秒後を読み取り、クレデンシャルはクリーンに見えると結論づける。lineage.root_issued_at は 09:00:00、変更の1時間前を読み取り、アラートを出す。](https://raw.githubusercontent.com/het-p301204/afterlife/main/docs/figures/two-fields.svg)

**3秒後、それとも1時間前——同じクレデンシャル、同じ瞬間。** 素朴なルールは攻撃者が制御するフィールドを尋ねており、1回の `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

3amに本当に重要なのはその違いだ。素朴なルールはチェーンが境界を越える
瞬間を一度だけ捉え、残り29日間は痕跡を見失う——そしてそれが名指しする
クレデンシャルは*すでにローテーションされ、サーバーによって失効させられている*。
それを失効させても何の意味もない。殺すべき対象は`lin-001`だ。

**そして素朴なルールはテレメトリに飢えていたわけではない。** 同じイベント
ストリーム、同じリネージインデックス、同じトレランス、同じ重複排除、
同じ有界状態を使用している。ただ1つのメソッドをオーバーライドするだけだ:```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 がそれを証明している。失敗は 比較にあり、ログ記録にあるのではない。


ルールパック

1つのログに対する3つのルール。それぞれ異なる問いに答え、インシデントが実際に展開する順序で発火する。

ルール重大度答える問い発火
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
は変更が着地した瞬間、攻撃者が何かに触れる3秒前に発火する。なぜなら、それが
必要とする証拠はすでに完全だからである。ログはどの系統が稼働状態で入ったかを
示しており、それらが失効されたとは示していない。

被害者も悪用も必要としない。ユーザーが最初に実行するパスワードリセットで
欠陥を報告する——つまり、待つべき攻撃者がいないステージング環境で実行する
べきものである。AFTERLIFE-001は侵害が進行中であることを伝え、
AFTERLIFE-003は封じ込め制御が壊れていることを伝える。

![2枚のアラートカード。10:00:00のAFTERLIFE-003はverdict no_containment、watermark not recorded、scope none、lin-001 survivingを報告する。10:00:03のAFTERLIFE-001は、変更の1時間前にrootが発行したcredential rt-002を報告する。](https://raw.githubusercontent.com/het-p301204/afterlife/main/docs/figures/findings-vulnerable.svg)

`application recorded watermark: no` は、インシデント対応者を症状ではなく
*欠陥*へと導くフィールドである。

### ルールが使用するウォーターマークは、アプリケーションが報告するものではない

資格情報変更イベントは `revocation_watermark` フィールド——アプリケーションが
書き込んだ `credentials_valid_after` 値——を運ぶ。**脆弱な実装ではこれが
`null` である。なぜならアプリケーションは一度も書き込まなかったからである。**
それがバグである。

したがって、そのフィールドに基づくルールは、まさにそれが捕まえるために存在
するケースに対して盲目となる。ルールはイベント自身の `timestamp` に
アンカーしており、これはアプリケーションがその役割を果たしたかどうかに
かかわらず真であり、欠落したフィールドを証拠として報告する。
ツールをダウンロード