
Найдите серверы Plex Media Server, затронутые Plex2Shell (CVE-2026-96652 и ещё тремя уязвимостями)
Находит Plex Media Server, подверженные Plex2Shell — цепочке из четырёх уязвимостей (CVE-2026-96652, CVE-2026-96654, CVE-2026-96655, CVE-2026-96656), которая позволяет злоумышленникам захватить Plex Media Server старше 1.43.3.10861 без входа в систему. Часть проекта shouldipanic.ch.
Plex2Shell эксплуатируется с 17 октября 2026 года (криптомайнеры, прокси) и входит в список Known Exploited Vulnerabilities CISA. Каждый Plex Media Server старше 1.43.3.10861, доступный из интернета, находится под угрозой.
plex2scan существует в двух формах:
plex2scan.py: один файл Python без зависимостей для проверки
собственных серверов: диапазоны IP, сканирование портов, включая порт Plex 32400, обнаружение vhost
и проверка версии Plex.
Каждый Plex Media Server отвечает на GET /identity без входа в систему и сообщает
там свою версию. plex2scan загружает стартовую страницу (чтобы распознать Plex по
заголовку X-Plex-Protocol или по странице Plex Web) и один раз запрашивает /identity.
Больше ничего не отправляется: ни входа, ни эксплойта.
curl -LO https://github.com/akaihigurashi/plex2scan/releases/latest/download/plex2scan.py
python3 plex2scan.py 203.0.113.0/24
Python 3.8 или новее, ничего устанавливать не нужно. Примеры:
python3 plex2scan.py 203.0.113.10 # 21 ports incl. 32400 + every vhost on the IP
python3 plex2scan.py 203.0.113.10:32400 # only Plex's own port
python3 plex2scan.py plex.example.ch # a Plex behind a reverse proxy
python3 plex2scan.py 203.0.113.0/24 --names domains.txt # + hostnames from your own data
python3 plex2scan.py 203.0.113.10 -p all -o out.csv # all 65535 ports, CSV output
python3 plex2scan.py -h # all options
| Статус | Значение |
|---|---|
VULNERABLE | Plex Media Server старше 1.43.3.10861 |
POSSIBLY VULNERABLE | Plex Media Server найден, версия скрыта |
PATCHED | Plex Media Server 1.43.3.10861 или новее |
NOT DETECTED | Plex Media Server не обнаружен |
Результаты перечислены от худших к лучшим с краткой причиной. Скрытые результаты (закрытые порты,
ошибки, vhosts, показывающие только сайт по умолчанию) отображаются с -a, а доказательства — с -v.
| Опция | Что делает |
|---|---|
-p LIST | Порты: web (20 распространённых портов + 32400, по умолчанию), all или 80,443,32400 |
-n | Без сканирования портов, только 443 и 80 |
--names FILE | Свой список имён хостов, проверяемых как vhosts |
--no-vhosts | Не искать другие сайты на том же IP |
-a / -v | Показать скрытые результаты / показать доказательства |
-o FILE | Также записать все результаты в CSV |
-d | Отладка: каждый запрос, заголовок и совпадение |
-q | Без баннера (для скриптов) |
-V | Вывести версию |
-h | Все опции |
myawesomeproxy,
mylovelyminer или x12345, неизвестные файлы .so/.dll в папке Codecs Plex,
подключения к proxystream.st, высокая нагрузка CPU, когда ничего не воспроизводится. Обновление
не удаляет злоумышленника, который уже проник в систему.AlienVault OTX и HackerTarget работают без ключей. VirusTotal, Shodan и SecurityTrails требуют API-ключ, который читается из переменных окружения:
| Переменная | Источник |
|---|---|
PANIC_VT_KEY | Пассивный DNS VirusTotal |
PANIC_SHODAN_KEY | Имена хостов Shodan |
PANIC_SECURITYTRAILS_KEY | Обратный IP SecurityTrails |
Храните их в файле .env, доступном только вам, и загружайте его только для сканирования:
( set -a; . ./.env; set +a; python3 plex2scan.py 203.0.113.10 )
--vt-key, --shodan-key и --securitytrails-key также работают, но аргументы командной строки видны другим локальным пользователям (ps) и попадают в историю вашей оболочки. Значения ключей маскируются в сообщениях об ошибках. (Спасибо Jonas Hüsser за это.)
docker run -d --name plex2scan --restart unless-stopped \
-p 127.0.0.1:8091:8091 \
-e PANIC_ORIGIN=https://plex2scan.example.ch \
-v plex2scan-data:/data \
ghcr.io/akaihigurashi/plex2scan:latest
Или с помощью Compose: скачайте docker-compose.yml, задайте
PANIC_ORIGIN, затем выполните docker compose up -d. Контейнер слушает только
localhost; разместите перед ним обратный прокси с TLS
(пример nginx).
| Переменная | По умолчанию | Назначение |
|---|---|---|
PANIC_ORIGIN | – | Публичный адрес. Запросы с других origin отклоняются. Задайте его. |
PANIC_OPERATOR / PANIC_CONTACT | – | Необязательный раздел контактов внизу страницы |
PANIC_IMPRINT_URL | – | Необязательная ссылка на существующий импрессум |
PANIC_TRUSTED_PROXY | 127.0.0.1,::1 | Прокси, чей заголовок X-Real-IP считается доверенным |
PANIC_DENY_HOSTS / PANIC_DENY_IPS | – | Никогда не проверять эти домены / адреса |
PANIC_AUDIT_DIR | /data/audit | Файлы ежедневного журнала аудита |
PANIC_RETENTION_DAYS | 30 | Файлы аудита старше этого срока удаляются |
Страница имеет те же средства защиты, что и php2scan: флажок согласия, журнал аудита, отказ клиентам VPN/Tor/дата-центров, ограничение частоты запросов, кэш результатов, проверка только публичных имён хостов с привязкой соединения к проверяемому адресу, сайты, которые никогда не проверяются (известные сервисы, 100 самых посещаемых сайтов, государственные сайты, страны под санкциями), и отсутствие доступа из стран под санкциями. Помимо самого сайта (443, затем 80) страница обращается только к порту 32400, и только если он открыт.
Движок сканера (загрузка, фингерпринтинг, сканирование портов, обнаружение vhost,
веб-сервер) находится в panic-core.
Всё, что специфично для Plex2Shell, находится в check.py.
plex2scan.py и web.py генерируются из обоих:
git clone https://github.com/akaihigurashi/panic-core ../panic-core
python3 ../panic-core/bundle.py check.py
GPL-3.0, см. LICENSE. Шрифты: Inter и JetBrains Mono (SIL Open Font License). Не связан с Plex, Inc. и не одобрен ею; «Plex» является их товарным знаком.