Thursday 17 January 2008

Fuzzing ActiveX? Don't Forget The Property Bags


(Note: I have a back log of posts so I'll be posting a fair amount over the next month)


There are several tools out there to fuzz ActiveX controls. COMRaider is one such tool, which is a useful addition to any bug hunter's toolkit. I am going to discuss a limitation that you should be aware of if you are testing ActiveX controls, namely that it doesn't fuzz property bags.


I was going to start by reproducing the definition of the OBJECT tag from the HTML DTD but its pretty big, so here's an example instead:


<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" width="300" height="120">
<param name="movie" value="flash.swf">
<param name="quality" value="high">
<param name="bgcolor" value="#FFFFFF">
</object>


In order to investigate the methods and get/set-able properties of a particular ActiveX control such as the Shockwave plugin, we can fire up the Microsoft OLE/COM Object Viewer (oleview), or programmatically create the object and ask it what it does through the IDispatch interface.


But methods and properties are not the only way we can interact with ActiveX controls. What about the name value pairs supplied via the PARAM tag above (movie, quality and bgcolor)? What other parameters might our target control accept, and how do we determine these? Well we have three options:


  1. Search for web pages that instantiate the control and note the parameters they pass (or the control's documentation in the case of a control like Shockwave). This approach is fine for obtaining the normal use parameters, but what if the control has interesting debug parameters that are undocumented?

  2. Run "strings" over the binary and treat each character string as the name of a parameter. This approach is viable but depending on the number of strings returned, may result in an unrealistic amount of test cases.

  3. Implement the required ActiveX container interfaces and let the control tell us what parameters it will accept. Clearly an optimal approach, this is what we shall focus on.

The parameter mechanism is implemented by the IPropertyBag interface in the container (i.e. Internet Explorer, your fuzzer, TstCon) and the IPersistPropertyBag interface in the control itself. There are also enhanced versions of these interfaces, IPropertyBag2 and IPersistPropertyBag2 though most controls I've seen don't use these (in fact the QuickTime plugin is one of the only controls I've seen with an IPersistPropertyBag2).


So in order to enumerate a control's parameters, also we have to do is implement IPropertyBag. This is actually pretty simple, since the interface only exposes two methods:


ReadTells the property bag to read the named property into a caller-initialized VARIANT.
WriteTells the property bag to save the named property in a caller-initialized VARIANT.


Time for an example. A while back when first looking into property bags I discovered a bug in the version of Yahoo! Messenger I happened to have installed. As it turned out, I had an outdated version and newer versions had fixed the issue, which had been reported to Yahoo! by iDefense.


There was a heap overflow in ymmapi.dll within the safe-for-scripting ymmapi.ymailattach.1 component. The vulnerable version of the control is still hosted on Yahoo.com here in a signed CAB file, though I warned them of this in November '06. The idea of flawed but signed code floating around the Internet is a scary one though the logistics of dealing with this are more of a Microsoft ActiveX design problem which I will discuss another time.


Back to the example in hand. Let's see how we can programmatically enumerate the supported parameters, pass a long string to each of them, locate the overflow and generate some equivalent HTML. I'm not going to give you the actual code (where's the fun in that?) but here's the set of steps required:


1. Initialise COM via CoInitialize.


2. Convert the supplied ProgID into a CLSID via CLSIDFromProgID if you don't already have it.


3. Create an instance of the ActiveX control via CoCreateInstance.


4. Call QueryInterface to request the IPersistPropertyBag interface.


5. Call the Load method of this interface passing it a pointer to our IPropertyBag implementation. Implementing a rudimentary IPropertyBag is simple - if you're happy to break the rules of COM for a simple PoC just implement stubs for QueryInterface, AddRef, Release and Write (obviously not recommended if you want to write anything more than a PoC). The only method that actually needs to do anything is Read.


6. The Read method of our IPropertyBag will be called each time the control requests the value of a specific parameter. We must reply with a VARIANT of type BSTR. Supply an empty string if you just want to enumerate the parameters or return your fuzz string. Once we trigger heap corruption, our process will AV so its best to run it in a debugger (and enable page heap with gflags).


If you go through the above steps and run your code on the ymmapi.ymailattach.1 control (having registered the control with regsvr32 first if you downloaded the CAB), you should find it breaks soon after receiving a long string in response to the Read for the "TextETACalculating" property.


Generating an HTML test case to reproduce this is easy - use JavaScript to dynamically create an OBJECT tag and the following function to build a string of suitable length (which I borrow from here):


String.prototype.repeat = function(l)
{
return new Array(l+1).join(this);
}

var fuzzstring = "a".repeat(50000);>


Giving you something like this when you load it into IE and your debugger kicks in:


The obligatory OllyDbg shot


So that's it for now. I'll be posting more on ActiveX in future posts. I want to cover killbits, ActiveX design limitations, and how to detect and handle sitelocking when fuzzing.


Cheers

John

No comments: