flawopen.com/Teardowns/cve-2026-61500-rejetto-hfs-predictable-session-key
CVE-2026-61500:Rejetto HFS の予測可能なセッション署名鍵
Rejetto HFS 3.0.0~3.2.0 は、セッション署名とログインに Math.random() 由来の値を使用していました。Horizon3 は、その漏えいによりセッションを偽造できたと報告しています。VulnCheck によると、10 月 1 日から悪用活動が観測されました。3.2.1 以降へ更新してください。特定の被害者の侵害は確認されていません。[1], [4], [5]
Cookie の署名は、管理者証に押す封蝋の印のようなものです。HFS は予測可能な数列から印の秘密を作り、ログイン処理では同じ数列の別の値も見える状態でした。秘密を推測できれば印を偽造できます。修正では Node.js の暗号学的乱数を使います。[1], [3]
主要な概念と専門用語
PRNG 状態- 次の擬似乱数出力を決める内部状態です。同じ生成器を秘密値と観測可能な値に使うと、両者の関係が露呈することがあります。[4]
発見の経緯- Horizon3 は、Mythos を用いたマルチエージェント研究システムがこの HFS の脆弱性連鎖を発見・検証したと説明しています。これは研究者による発見の経緯であり、Mythos 自体の脆弱性でも、実環境への AI 自律攻撃の証拠でもありません。[4]
フレームワーク対応
- このガイドで説明する弱点の CWE 参照: CWE-338
根本原因の分析 (Root Cause)
CVE レコードは影響範囲を HFS 3.0.0~3.2.0 とし、CWE-338 に分類しています。上流コミット 59472e5 では、脆弱なコードが Koa に [randomId(30)] を渡しており、randomId() は Math.random() を使用していました。修正では node:crypto の [randomBytes(32).toString('base64url')] に変更しています。同じコミットで、公開されるログイン・ハンドシェイク識別子も Math.random() から randomUUID() に変更されました。Horizon3 は、認証不要で取得できるログイン応答から関連する出力が漏れ、V8 PRNG の状態と Cookie 署名鍵を導出できたと報告しています。偽造した管理者セッションから、HFS の管理機能を通じてサーバー上のコード実行に至る可能性があります。本記事はこの連鎖を高いレベルで説明し、復元手順、リクエスト、ペイロードは掲載しません。VulnCheck によると、Canary Intelligence は 2026 年 10 月 1 日に悪用活動の観測を開始し、その内容は 10 月 2 日のレポートで報告されました。このテレメトリは、侵害された HFS 環境を特定していません。[1], [3], [4], [5]
ステップ・バイ・ステップの攻撃フロー
弱点がセッション境界を越える
Horizon3 によると、出力から PRNG 状態を復元でき、セッション署名を偽造して管理者権限を得られる可能性がありました。具体的な復元手順は省略しています。[4]
ソースコード比較:脆弱 vs 堅牢化
このコードは実際の上流コミットを反映しています。randomBytes(32) は Node.js の暗号モジュールから 256 ビットを鍵に提供し、randomUUID() は公開ログイン識別子の生成元を置き換えます。セッション認証用の秘密は暗号学的乱数源から生成し、アプリケーション PRNG の観測可能な出力から独立させる必要があります。HFS 3.2.1 以降のサポート対象版へ更新してください。この抜粋は修正を説明するもので、単独で適用するパッチではありません。 これは自動生成されるフォールバック値だけを保護します。COOKIE_SIGN_KEYS を設定している場合、指定する各キーも個別に暗号学的乱数で生成し、秘密として管理し、漏えい時にローテーションしてください。[3], [1]
ソース抜粋: src/index.ts(Cookie 署名キー)および src/api.auth.ts(ログインハンドシェイク ID、上流コミット 59472e5)
import { httpStream, randomId } from './misc'
const keys = process.env.COOKIE_SIGN_KEYS?.split(',')
|| [randomId(30)]
export const app = new Koa({ keys })
const sid = Math.random()
import { randomBytes, randomUUID } from 'node:crypto'
const keys = process.env.COOKIE_SIGN_KEYS?.split(',')
|| [randomBytes(32).toString('base64url')]
export const app = new Koa({ keys })
const sid = randomUUID()
エンジニアリング&システム堅牢化チェックリスト
- ✓HFS 3.0.0~3.2.0 を 3.2.1 以降へ更新します。最新のサポート対象安定版を優先してください。[2], [1]
- ✓Windows ホスト、コンテナ、テスト環境、インターネット公開のファイル共有を含む全 HFS を棚卸しし、バージョンと公開状態を記録します。[4]
- ✓すぐに更新できない場合は、更新計画中に信頼できるネットワークだけにアクセスを制限し、公開到達性をなくします。これは露出を下げますが、弱い鍵生成を修正するものではありません。[4]
- ✓脆弱な期間にインターネットからアクセス可能だったインスタンスを更新したら、既存の全セッションを無効化し、設定済みの
COOKIE_SIGN_KEYSをローテーションしてください。調査で不正な管理者操作が見つかった場合は、管理者の認証情報も変更してください。ログは調査用に保全します。[1], [4] - ✓観測された探索は調査のきっかけであり、侵害の証明ではありません。ログを保全し、不正な設定変更やコード実行の兆候を調べます。[5], [4]
- ✓Node.js アプリでは、設定済みの
COOKIE_SIGN_KEYSの各値が暗号学的乱数で個別に生成され、秘密として管理され、漏えい時にローテーションされることを確認してください。安全なフォールバックは上書き値を検証しません。他の秘密情報にはrandomBytes()などnode:cryptoAPI を使用してください。署名キー、リセットトークン、認可値をMath.random()から生成しないでください。[3], [6]