Slide 1

Slide 1 text

脆弱性から学ぶシリーズ CVE-2024-34341 XSS Vulnerabilities in Trix Editor 2024.11.18 Kashiwa.rb #5 LT Koji NAKAMURA (@kozy4324)

Slide 2

Slide 2 text

Koji NAKAMURA ● 𝕏: @kozy4324 ● GitHub:@kozy4324 ● Classi株式会社所属 ● Kashiwa.rb主催 自己紹介

Slide 3

Slide 3 text

脆弱性から学ぶシリーズとは? ● kozy4324 が個人的に取り組んでいる営み ● 過去の脆弱性報告とその対応から何かしら学ぶ ● アウトカム:LT ネタに困らなくなる

Slide 4

Slide 4 text

アジェンダ ● CVE-2024-34341 XSS Vulnerabilities in Trix Editor ● 問題を抽象化してみる ● 得られる教訓

Slide 5

Slide 5 text

CVE-2024-34341 XSS Vulnerabilities in Trix Editor

Slide 6

Slide 6 text

● Rails の Action Text で利用されるリッチテキストエディタ ○ https://github.com/basecamp/trix ○ https://railsguides.jp/action_text_overview.html ○ これ ↓ Trix Editor とは?

Slide 7

Slide 7 text

● https://github.com/basecamp/trix/security/advisories/GHSA-qjqp-xr96-cj99 ● エンドユーザーがコピー&ペーストした際に任意コード実行の脆弱性 ● 攻撃ベクトルは2つあった ○ noscript を利用する ○ data-trix-* 属性を利用する ● この LT では noscript の方だけ取り上げます 脆弱性の内容

Slide 8

Slide 8 text

● 以下 JavaScript でコピーされる内容を Trix Editor にペーストする ● HTML 部分だけを整形すると以下の通り 脆弱性の内容 - noscript を利用した攻撃ベクトル document.addEventListener('copy', function(e){ e.clipboardData.setData('text/html', '
'); e.preventDefault(); });

Slide 9

Slide 9 text

● 実際にペーストしてみると alert(1) が発動する 脆弱性の内容 - noscript を利用した攻撃ベクトル

Slide 10

Slide 10 text

● 期待される DOM ツリー の構造はこう ● ペーストした結果の構造はこうなっていた XSS が発生する機序
<div class="123456

Slide 11

Slide 11 text

● onerror=alert(1) のような DOM Based XSS はサニタイズにより除去・無効化さ れてペーストされるのが正しい振る舞いだった Trix Editor の期待される振る舞い

Slide 12

Slide 12 text

● Sanitize noscript to prevent copy and paste XSS #1147 ○ https://github.com/basecamp/trix/pull/1147 ● DEFAULT_FORBIDDEN_ELEMENTS に noscript を追加している ○ noscript を許可しないという対応 この脆弱性に対する修正内容

Slide 13

Slide 13 text

● まず内部処理 ○ 表示ドキュメントの DOM ツリー追加前にサニタイズ処理がある ○ HTMLSanitizer クラス ■ https://github.com/basecamp/trix/blob/v2.1.0/src/trix/models/html_sanitizer.js ○ 入力された HTML 文字列から、表示ドキュメントとは別に DOM ツリーを作成 し、その DOM ツリーから許可されない要素や属性を除去する ○ 処理済みの DOM ツリーが表示ドキュメントに追加される なぜ noscript タグが作用するのか?(1)

Slide 14

Slide 14 text

● 表示ドキュメントとは別に DOM ツリーを作成する実装(抜粋) ● まず HTML 文字列をブラウザの HTML パーサーに処理させている ○ 文字列から onxxx 属性を正規表現で除去、とかはカオスなのでこれは正しい ● createHTMLDocument("") したものに追加 ○ 表示ドキュメントの DOM ツリーに追加すると script タグがその時点で評価・実行さ れるので、これも正しい ○ が、ここに落とし穴がある なぜ noscript タグが作用するのか?(2) const doc = document.implementation.createHTMLDocument("") doc.documentElement.innerHTML = html

Slide 15

Slide 15 text

● ここからは HTML の Spec を読むと機序が理解できる ○ https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody ● `` が出現すると scripting flag による分岐がある ○ > A start tag whose tag name is "noscript", if the scripting flag is enabled Follow the generic raw text element parsing algorithm. ○ scripting flag が enabled の場合は raw text の扱いになる (!) ■ なので `` の並びまでが noscript タグの content になる ■ script タグの中で `` が出てきたら問答無用で script タグが終 了するアレです なぜ noscript タグが作用するのか?(3)

Slide 16

Slide 16 text

● なのでこう解釈されてほしかった HTML は、 ● scripting flag によってこう解釈されうる可能性もある なぜ noscript タグが作用するのか?(4)
<div class="123 456

Slide 17

Slide 17 text

● scripting flag とは? ○ browsing context が non-null であれば scripting flag が enabled になる ○ browsing context がある状態とは JavaScript のグローバルオブジェクトであ る window がある状態 = スクリプトが実行できる状態 ■ (ここの説明がやや微妙だが、一旦そういうことで ...) ● spec にコレっていう言及がある ○ > A Document created using an API such as createDocument() never has a non-null browsing context. ○ Trix Editor のサニタイズ処理では scripting flag は disabled で処理されてい たと言える なぜ noscript タグが作用するのか?(5)

Slide 18

Slide 18 text

● Trix Editor の内部処理ではこう解釈される、 img 要素は認識できない ● 表示ドキュメントの DOM ツリー追加時には img 要素が認識される なぜ noscript タグが作用するのか?(6)
<div class="123 456

Slide 19

Slide 19 text

問題を抽象化してみる

Slide 20

Slide 20 text

● Trix Editor では scripting flag が enabled/disabled という差異があることでサニ タイズ処理がバイパスされる振る舞いに繋がっていた ● 実際に処理される方法とは全く別のやり方で事前の処理、例えばバリデーション処 理をしたりってよくありませんか? ● 例えば何かのパーサーに渡す入力文字列を正規表現でチェックとか 事前の処理と本来の処理に差異がある問題

Slide 21

Slide 21 text

● CVE-2024-45048: XXE in PHPSpreadsheet encoding is returned ○ https://github.com/advisories/GHSA-ghg6-32f9-2jp7 ○ PHPSpreadsheetライブラリにおいて細工した xlsx ファイルを処理させることで XXE(XML外 部実体攻撃)が可能という脆弱性 ○ 事前の処理で XML の文字コード判定を /encoding="(.*?)"/ という正規表現で文字列抽出し て行っていた ○ XML の仕様としてはシングルクォーテーションによるクォーテーションも認められている ○ 文字コード判定をミスることで結果として XXE のサニタイズがバイパスされる ○ 「正規表現による処理」と「 XML パーサーによる処理」の差異 実際にあった似たような「問題」(1)

Slide 22

Slide 22 text

● CVE-2024-8372: AngularJS srcsetへの不適切なサニタイズによるコンテンツ・スプーフィ ング脆弱性 ○ https://www.herodevs.com/vulnerability-directory/cve-2024-8372 ○ ○ xyz の部分は本来は幅記述子もしくはピクセル密度記述子が入る ■ e.g.) 640w, 960w, 1024w, 1x, 2x, 3x ○ 正規表現による事前処理が幅記述子とピクセル密度記述子しか期待できていなかっ たためサニタイズ処理がバイパスされた ○ ブラウザの HTML パーサー的には xyz と入っていても画像の表示処理はする ○ 「正規表現による処理」と「HTML パーサーによる処理」の差異 実際にあった似たような「問題」(2)

Slide 23

Slide 23 text

得られる教訓

Slide 24

Slide 24 text

● 事前の処理と本来の処理に差異がある状況に遭遇したら気をつけよう ○ 特に正規表現を使って何かの事前処理をするのは人類やりがち ○ Trix Editor のように両方 HTML パーサーで処理させればOK!ということもな く scripting flag という普通は気づかない要素があることもある ○ 仕様や本来の処理と本当に差異がないかは注意深く! ● 脆弱性から学ぶと LT ネタが無限に生成される ○ 関連する事象を調べ上げることで「へ〜なるほど!」って思えることに割と出く わすのでオススメ 得られる教訓

Slide 25

Slide 25 text

EOF