
Drupal 11.4.8 - 高 - リモート - XSS - AttributeXss は依然として HTMX 属性を許可する
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · drupal-htmx-attr
クラス: 格納型 XSS 到達範囲: リモート
Drupal core 11.4.8 (61044508) - Drupal
SA-CORE-2026-011 は Xss::attributes() 内の HTMX 属性を塞いだ。リンクおよびメニュー属性は AttributeXss::sanitizeAttributes を経由するが、そのスキップリストは依然として style と on* のみを除外している。
Link フィールド(またはメニューリンク)を設定できるコンテンツ編集者は、hx-on-click または data-hx-on-click を格納できる。Standard と BigPipe は core/htmx を読み込む。管理者または他の閲覧者がそのノードを開いてリンクをクリックすると、HTMX は格納された JS をサイトのオリジンで実行する。
| ID | CVE 未採番 |
| クラス | 格納型 XSS(HTMX イベント属性) |
| 到達範囲 | リモート(認証済みの Link フィールド / メニュー書き込み者。被害者が閲覧してクリック) |
| CWE | CWE-79 |
| CVSS | High: 8.7 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N |
| 製品 | Drupal core |
| 影響を受けるバージョン | 11.4.8 (61044508071749629aaf3380aa85971e94df9e84) |
| 認証 | Link フィールド(またはメニューリンク)を書き込める認証済みユーザー。被害者がページを閲覧してクリックする。 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ |
書き込み者: リンクの options.attributes(Link フィールド、メニューリンク、JSON:API)を設定できるコンテンツ編集者。被害者: ページが HTMX を読み込むすべてのユーザー(Standard + BigPipe は core/htmx を読み込む)。リンクをクリックするサイト管理者を含む。
| 権限 | メソッド / パス | 種類 | ラボ実証済みまたは推測 |
|---|---|---|---|
| リンクに HTMX イベント属性を永続化 | POST /jsonapi/node/article に field_link.options.attributes.hx-on-click と data-hx-on-click を指定 | 格納フィールドの完全性 | ラボ実証済み。JSON:API 201、格納された属性には依然として hx-on-click が含まれる |
ノードの <a> にそれらの属性を出力 | LinkFormatter -> AttributeXss::sanitizeAttributes | HTML の完全性 | ラボ実証済み。GET /node/1 の HTML に hx-on-click とマーカー window['DRUPAL-HTMX-ATTR-WITNESS']=1 が含まれる |
| 被害者がクリックしたときにその JS を被害者のオリジンで実行 | HTMX が hx-on-* をバインド | 被害者セッションの完全性 | HTMX とページが core/htmx を読み込むことから推測。ラボではブラウザのクリックを実行していない |
| 閲覧者として行動(セッション Cookie、管理 UI のクリック) | 同じ格納型 XSS | 被害者セッションの完全性 | 推測。ラボは HTML に属性が残るところで止まる |
否定: Xss::filter | Xss::filter('<a ... hx-on-click=...>') | 塞がれている | ラボ実証済みで塞がれている。xss_keeps_hx=False |
| リンクの未認証書き込み | セッションなしの JSON:API | 塞がれている | ラボはまず uid 1 でログインした。アカウントを持たない第三者はフィールドを設定できない |
| PHP RCE / LPE | 該当なし | 塞がれている | この残存物はブラウザ JS であり、サーバー上の PHP ではない |
同じピンでの残存物: Move Block sibling markup。
SA-CORE-2026-011 の後、drupal/drupal 11.4.8 をピン留めした。5 つの調査: XSS/HTMX、file/MIME/oEmbed、JSON:API/unserialize/SQLi、auth/CSRF/Host、REST/media/Views。JSON:API アクセス、EntityQuery の IN キー(SA-004)、シリアライズフィールドの POI(SA-005)、rebuild.php の Host(SA-007)はパッチ済みのままである。HTMX スキップリストは Xss.php にのみ入った。
$skip = (
in_array($attribute_name, ['style', 'srcdoc']) ||
str_starts_with($attribute_name, 'on') ||
str_starts_with($attribute_name, 'data-hx') ||
str_starts_with($attribute_name, 'hx') ||
str_starts_with($attribute_name, '-') ||
strlen($attribute_name) > 96
);
AttributeXss.php の残存物:
$skip = (
$attribute_name == 'style' ||
str_starts_with($attribute_name, 'on') ||
str_starts_with($attribute_name, '-') ||
strlen($attribute_name) > 96
);
呼び出し元には LinkFormatter.php と MenuLinkContent::getUrlObject() が含まれる。
すでに記録済みの誤った道: Xss::filter を残存物とみなすこと(それは対照である)、未認証の JSON:API 書き込み、PHP RCE、リバースシェル。茶番である。オラクルはノード HTML に残る属性と、core/htmx が読み込まれていることである。
python3 drupal-htmx-attr-Abraxas-Labs.py
または
cd lab
./run.sh
対象は http://127.0.0.1:19480 のみ。ライブの drupal:11.4.8-apache、Standard プロファイル、ラボ用に JSON:API 書き込みを有効化。Compose プロジェクト drupal-htmx-attr。
SUCCESS drupal-htmx-attr how=live write=jsonapi nid=1 hx-on-click=kept jsonapi-stored=1 xss-filter=stripped htmx=loaded marker=1 version=11.4.8 DRUPAL-HTMX-ATTR-WITNESS
hx / data-hx / srcdoc の拒否リストを AttributeXss にコピーする。クラスの docblock がすでに述べているように、それを Xss に統合する。
61044508071749629aaf3380aa85971e94df9e84)AttributeXss.php · Xss.phpGNU Affero GPL v3.0。LICENSE を参照。ループバックラボのみ。無保証。