Skip to content
KitploitKITPLOIT
ツールブログ
Log in
提出
ツールブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
cve-2023-5217-poc — ブラウザの WebCodecs または MediaRecorder インターフェースから CVE-2023-5217 をトリガーする PoC。 | Kitploit
ツール/GitHubGitHub/ut-security/cve-2023-5217-poc
脆弱性分析エクスプロイトウェブアプリケーション悪用ファジング学習と教育バイナリエクスプロイト
GitHubut-security/cve-2023-5217-poc

cve-2023-5217-poc

ブラウザの WebCodecs または MediaRecorder インターフェースから CVE-2023-5217 をトリガーする PoC。

リポジトリを見る
163172年前未レビュー

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2023-5217: libvpx VP8 エンコード ヒープ オーバーフロー PoC

CVE-2023-5217 は、実際に悪用された libvpx の脆弱性であり、Google の Threat Analysis Group の Clément Lecigne によって、Chrome を標的とした攻撃に使用されていることが発見されました。

このリポジトリは、WebCodecs と MediaRecorder API を使用してブラウザで CVE-2023-5217 をトリガーする方法を示しています。CVE-2023-5217 は、制御可能なオーバーフロー長と、繰り返される小さな 4 バイト値の上書きを伴うヒープバッファオーバーフローを引き起こします。CVE-2023-5217 が現実の攻撃でどのように悪用されたかは、現在のところ不明です。

公開時点では、CVE-2023-5217 を修正する libvpx への 2 つのパッチと Chromium への 1 つのパッチがありました。libvpx のパッチには、VP8 のスレッド数変更の無効化と、マルチスレッドエンコード用のテストが含まれていました。Chromium のパッチは、WebCodecs でのスレッド数調整を無効化しました。

libvpx v1.13.0 Ugly Duckling の根本的な問題

概要

libvpx は VP8/VP9 のエンコードとデコードを処理するライブラリです。

CVE-2023-5217 の核心的な問題は、libvpx の VP8 エンコードセッションにおいて、フレーム高を大きくしながらスレッド数を減らすと、制御可能な長さの線形ヒープオーバーフローと、繰り返される小さな 4 バイト値の制御可能な上書きが発生することです。フレーム高の差が上書きの長さを制御し、新しいフレーム幅が繰り返し書き込まれる 4 バイト値を制御します。この脆弱性は、後続の各設定で高さを減らすことにより、異なる小さな 4 バイト値を連続して書き込むために複数回悪用される可能性があります。

詳細

libvpx VP8 エンコーダーは、エンコーダースレッドが現在処理中の列を格納する mt_current_mb_col という配列を保持します。この配列はスレッドが 2 つ以上の場合にのみ割り当てられ、そのサイズは mb_rows に依存します。ここで mb_rows = frame_height >> 4 であり、frame_height は 16 の倍数に切り上げられます。

// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/common/alloccommon.c#L85
// The width and height are rounded up to a multiple of 16 and then assigned to `mb_rows` and `mb_cols`
int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height) {
    ...
    // Round up the width/height up to the nearest multiple of 16
    if ((width & 0xf) != 0) width += 16 - (width & 0xf);
    if ((height & 0xf) != 0) height += 16 - (height & 0xf);
    ...
    oci->mb_rows = height >> 4;
    oci->mb_cols = width >> 4;
    ...
}
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/onyx_if.c#L1232
// This snippet shows the allocation of `mt_current_mb_col`
void vp8_alloc_compressor_data(VP8_COMP *cpi) {
  ...
  // Only allocate if we have more than 1 thread
  if (cpi->oxcf.multi_threaded > 1) {
    int i;

    vpx_free(cpi->mt_current_mb_col);
    // sizeof(*cpi->mt_current_mb_col) is 4
    CHECK_MEM_ERROR(&cpi->common.error, cpi->mt_current_mb_col,
                    vpx_malloc(sizeof(*cpi->mt_current_mb_col) * cm->mb_rows));
    for (i = 0; i < cm->mb_rows; ++i)
      vpx_atomic_init(&cpi->mt_current_mb_col[i], 0);
  }
  ...
}

libvpx がフレームのエンコードを完了すると、エンコードされた列数に mt_sync_range を加えた値を mt_current_mb_col に格納します。

// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/onyx_if.c#L1212
// Snippet where the mt_sync_range value is set, based on the width.
void vp8_alloc_compressor_data(VP8_COMP *cpi) {
    ...
#if CONFIG_MULTITHREAD
  if (width < 640) {
    cpi->mt_sync_range = 1;
  } else if (width <= 1280) {
    cpi->mt_sync_range = 4;
  } else if (width <= 2560) {
    cpi->mt_sync_range = 8;
  } else {
    cpi->mt_sync_range = 16;
  }
#endif
  ...
}
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/encodeframe.c#L560
// Function where the attacker chosen value is written
static void encode_mb_row(...) {
  ...
  const int nsync = cpi->mt_sync_range; // This value is set in vp8_alloc_compressor_data
  vpx_atomic_int rightmost_col = VPX_ATOMIC_INIT(cm->mb_cols + nsync);
  ...
  if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) {
    current_mb_col = &cpi->mt_current_mb_col[mb_row];
  }
  ...
  if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) {
    // current_mb_col is a reference to mt_current_mb_col
    vpx_atomic_store_release(current_mb_col,
                             vpx_atomic_load_acquire(&rightmost_col));
  }
  ...
}

mt_current_mb_col をオーバーフローさせるには、3 つのエンコード設定が必要です。

  1. configinit: 初期化中、libvpx は initial_width と initial_height を設定します。これらは後続の設定で指定可能な最大の境界です。ここでのスレッド数は関係ありません。後続の幅/高さの組み合わせは初期値より大きくなり得ないため、中間の設定が必要です。
  2. configvuln: 再構成中、スレッドが 2 つ以上使用されている場合、libvpx は configvuln.height に基づいて脆弱な mt_current_mb_col の割り当てを作成します。この新しい高さは configinit.initial_height より小さくなければなりません。そうしないとエラーが発生します。
  3. configattack: 再構成中、スレッドが 1 つだけの場合、libvpx は mt_current_mb_col を再割り当てしないため、脆弱な状態のままになります。次の条件が成り立つ場合、libvpx は以前に割り当てられた境界の外側に値 (configattack.width >> 4) + 1 を繰り返し書き込みます (ここで 1 は変数 mt_sync_range であり、幅は 16 の倍数に切り上げられます)。
\text{ceil}(\text{config}_{\text{init}}.\text{height}/16) \geq \text{ceil}(\text{config}_{\text{attack}}.\text{height}/16) \gt \text{ceil}(\text{config}_{\text{vuln}}.\text{height}/16)$$

mt_current_mb_col overflow

より具体的には、configinit で幅 = 1200、高さ = 1200、スレッド = 4 の VP8 エンコード設定を初期化するとします。攻撃は次のようになります。

  1. configvuln は、幅 = 500 (512 に切り上げ)、高さ = 700 (704 に切り上げ)、スレッド = 2 でエンコーダーを再構成します。mb_rows は 704/16 = 44 に設定され、配列 mt_current_mb_col は (44)*4 = 176 バイトで割り当てられます。mt_current_mb_col に書き込まれる値は 512/16 + 1 = 33 です。
  2. configattack は、幅 = 18 (32 に切り上げ)、高さ = 1000 (1008 に切り上げ)、スレッド = 1 でエンコーダーを再構成します。mt_current_mb_col はスレッドが 2 つ以上の場合にのみ再割り当てされるため、サイズは同じままですが、mb_rows は 1008/16 = 63 に設定されます。libvpx が encode_mb_row を呼び出すと、mt_current_mb_col の割り当てを (63-44)*4 = 68 バイト超えて上書きし、値 32/16 + 1 = 3 を繰り返し書き込みます。ここで、32 は切り上げ後の幅、1 は mt_sync_range の値です。
  3. 攻撃者は、configattack より小さいが configvuln より大きい高さを使用してこの脆弱性を再悪用し、別の値を書き込むことができます。たとえば、攻撃者は幅 = 34、高さ = 990 の configattack' を作成し、mb_rows = 992/16 = 62、mb_cols = 48/16 = 3 に設定して、元の割り当てから (62-44)*4 = 64 バイトだけ超えて値 4 を書き込むことができます。

悪用

この脆弱性を悪用するには、攻撃者はエンコードの高さ、幅、スレッド数を制御できる必要があります。前者 2 つは簡単ですが、後者にはエンコードスレッド数が再構成される場所を見つける必要があります。

// https://github.com/webmproject/libvpx/blob/67bfb41ed8598edfb25bd6f245f9c39a68808548/vp8/vp8_cx_iface.c#L301
static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
 ...
  oxcf->multi_threaded = cfg.g_threads;

Firefox

Firefox では、VP8TrackEncoder でエンコードするフレーム領域を調整することでスレッド数を制御できます。フレーム領域が 307,200 (640x480 フレーム) より大きく、マシンのコア数が 2 より多い場合、複数のスレッドが使用されます。

// https://searchfox.org/mozilla-central/source/dom/media/encoder/VP8TrackEncoder.cpp#97
nsresult CreateEncoderConfig(...) {
  ...
  int32_t number_of_cores = PR_GetNumberOfProcessors();
  if (aWidth * aHeight > 1920 * 1080 && number_of_cores >= 8) {
    config->g_threads = 4;  // 4 threads for > 1080p.
  } else if (aWidth * aHeight > 1280 * 960 && number_of_cores >= 6) {
    config->g_threads = 3;  // 3 threads for 1080p.
  } else if (aWidth * aHeight > 640 * 480 && number_of_cores >= 3) {
    config->g_threads = 2;  // 2 threads for qHD/HD.
  } else {
    config->g_threads = 1;  // 1 thread for VGA or less
  }
  ...

MediaRecorder API は VP8TrackEncoder に依存していることがわかりました。録画中のキャンバスのサイズを変更することで、幅と高さを調整できます。呼び出し方法については、下記の MediaRecorder セクションを参照してください。

Chrome

Chrome も同様に、エンコードされるフレーム領域とコア数に基づいてスレッド数を調整します。

// https://source.chromium.org/chromium/chromium/src/+/main:media/video/vpx_video_encoder.cc;l=84
EncoderStatus SetUpVpxConfig(...) {
  ...
  // Set the number of threads based on the image width and num of cores.
  config->g_threads = GetNumberOfThreadsForSoftwareEncoding(opts.frame_size);
}
ツールをダウンロード