Sunteți pe pagina 1din 13

Sitelocking ActiveX Controls for the Web

by

c-q-r

eVision, March 7th 2010


Foreword

The following content assumes a basic knowledge of COM components, some proficiency in C++
development and an intermediate level of understanding of security concepts.

Introduction

Sifting through a pile of articles on ActiveX security led me through mazes of abominable sizes. I
emerged with this basic premise: ActiveX controls, especially those provided as part of web applications,
are risky business. To really assess the trouble, however, we need to step through these mazes together.
Let us begin at the door-step of Microsoft:

A Microsoft® ActiveX® control is a COM object that supports the IUnknown interface, and is self-
registering. Many ActiveX controls, particularly those used in Web pages, support the IDispatch
interface, which allows scripting languages, such as Microsoft JScript® development system (JScript)
and Microsoft Visual Basic® Scripting Edition (VBScript) to access the control easily. (5)

So what are COM objects? Let’s break that down: Component Object Model objects. COM objects are a
way to allow for modularization and reuse of software parts, just like in other engineering fields where
you have small parts that could be plugged-in or replaced.(9)

From the above excerpt we understand that ActiveX controls can possibly interact with the container
that they run in. This happens through the interface that the control exposes for use by the container
(for a containing Webpage to interact with your ActiveX control, you implement the IDispatch Interface
for the control describing the methods and properties it exposes). In addition to declaring what they
can do, COM objects are expected to register themselves by adding their GUID to the system registry.

What then is the danger of ActiveX controls? Well, to begin with, they run natively on the machine,
meaning they are not bound by a Virtual Machine or a sandboxing environment (unless a platform is
specifically targeted). Apart from the usual client-side attack that is expected with most applications,
repurposing by the container is another security aspect that must be taken in to account. Repurposing
involves a website exploiting a faulty ActiveX control that is already installed (trusted) and running on
the client machine to attack the client.

To cater for this possibility, Microsoft provides a safety mechanism for any ActiveX control that is meant
to run on the web. The mechanism ensures nothing in-and-of-itself of course, but it does bring up the
issue of security. Any ActiveX control hoping to be loaded by Internet Explorer is required to indicate
whether it is safe to run on the web or not. This is done by allowing ActiveX controls to indicate two
types of safety parameters: Initialization and Scripting.

Initialization and Scripting Safety

Initialization safety means that if the control declares itself Safe for Initialization, IE will allow a
webpage (the webpage containing and invoking the control) to provide initialization data for the control
through the DATA attribute or the PARAM tag.
<object ID=MyObj
classid="clsid:12345678-1234-1234-5678-ABCDEF012345"
width=50 height=50 data="http://www.acme.com/ole/clock.stm">
<param name="CustomProperty1" value="Attacker's Data">
<param name="CustomProperty2" value="Untrusted Input">
</object>

Of course if you are going to indicate that your control is safe for Initialization (we’ll see how to do that
later), you have to be really sure that it truly is safe for your control to handle tainted or malicious data
handed to it by the website. Meaning, you must consider initialization as a possible entry-point to your
control and accordingly validate data obtained in this manner. For example, you should ensure that your
control does not mishandle data by writing them to a constant sized buffer without checking the buffer
size (buffer overflow).

Scripting safety means that IE will allow any script on any webpage hosting your control to interact with
your control. This interaction includes firing methods that are exposed by your control and manipulating
the parameters at will. Again, as with Initialization, your control indicates whether this is safe behavior.
If your control indicates that it is Safe for Scripting, then it had better be ready to handle malicious
scripts trying to exploit its presence on a user machine. This means that methods exposed by your
control need to be scrutinized closely for possible abuse cases.

<object ID=MyObj
classid="clsid:12345678-1234-1234-5678-ABCDEF012345"
width=50 height=50>
<script>
//Calling Methods
MyObj.MethodName("Parameter1", 7);

//Getting and setting properties


alert(MyObj.Property1);
MyObj.Property2 = "NewPropertyValue";
</script>

The code above shows how the script on the page can interact with the object instance of your control.

So, should you indicate that your control is safe?

Well it goes back to what your control needs to accomplish. If it is absolutely necessary for it to interact
with the container page, then you will need to declare and ensure safety. In my opinion, if your control
can do without interacting with the container then it is best not to allow any such interaction from a
defense-in-depth perspective. (In fact, if your website can do without the ActiveX control altogether
then that’s a bucket-worth of troubles that you could spare yourself).

Should your control require interaction with the container, then a critical review of the security of your
exposed methods is in order. Furthermore, any unnecessary interaction should not be made possible,
meaning, you should keep the scope of your IDispatch implementation as narrow as possible for the
desired functionality to be available and nothing more. You should enumerate all possible entry points
to your control and assess the abuses possible from those directions.
Additionally, you should make use of the Site-lock template made available by Microsoft (10). The
Sitelock template allows the control to query its container and find out where the host webpage
originated from, if the webpage came from a domain other than those the control is expected to run
from, the control will block Initialization and Scripting through the SetInterfaceSafetyOptions() method
implemented as part of the template.

Finally, as with any application, privileges required to run your code should be the minimum a system
can afford so that your application is not blocked by the operating system from doing anything the OS
perceives as illegal in the context of the executing process running your control. For instance in Vista,
Internet Explorer runs with user permissions, if the control running in Internet Explorer tries to write to
a system folder, it will be blocked on the OS layer (reference monitor) and your control will not
complete its operation.

How to make your control safe

So assuming that you’ve done your homework and defensively coded your application such that any
untrusted data or untrusted callers are dealt with appropriately, let’s see how you would indicate this to
IE.

There are two methods of indicating safety to IE. You could either use the Component Categories
Manager to create registry entries that identify the safety of your control, or, you could implement the
IObjectSafety Interface in your control. (3)

Component Categories Manager

With this method you implement the registration/deregistration procedures in the DllRegisterServer()
and DllUnregisterServer() functions. To register as safe for either scripting or initialization your code
should add a standard set of keys (also specified elsewhere by the system) in the registry key
“HKEY_CLASSES_ROOT\CLSID\{your-control-GUID}\Implemented Categories\” of your control (see fig 1).
The standard set of categories is defined under HKEY_CLASSES_ROOT\Component
Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4} and HKEY_CLASSES_ROOT\Component
Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}.

Fig 1. Implemented Categories for the Tabular Data Control (just an example)
Fig 2. Standard system component categories

The exact code for doing this can be copied out of the reference article from Microsoft (3).

IObjectSaftey Method

This method, though it seems more complicated, provides you with better “control” of your control’s
behavior. To define safety here, we use two constant bit flags defined in Objsafe.h,
INTERFACESAFE_FOR_UNTRUSTED_DATA and INTERFACESAFE_FOR_UNTRUSTED_CALLER, and
implement the GetInterfaceSafetyOptions and SetInterfaceSafetyOptions methods.

GetInterfaceSafetyOptions retrieves the default capabilities of the control. SetInterfaceSafetyOptions


configures the control, if possible, for safety. The container then used the return value of the
SetInterfaceSafetyOptions to decide on how to behave.

As attested to by the Microsoft (3) and from experimentation with a debugger (12), IE as a container
does not really utilize the GetInterfaceSafetyOptions. (Though this is not documented anywhere, I’ve
found while attaching to an ActiveX process that IE will call GetInterfaceSafetyOptions on scripting
requests from the containing webpage and then follow that up with a call to SetInterfaceSafetyOptions).
Generally, IE calls the SetInterfaceSafetyOptions method whenever it is at a scripting/initialization
junction. If a script on the containing webpage tries to access your ActiveX object, IE calls
SetInterfaceSafetyOptions and depending on the return from that function, E_FAIL or S_OK, IE blocks or
allows the operation. The same thing happens when the container webpage tries to initialize your
control.
The SiteLock template mentioned earlier uses the IObjectSafety method to allow you to control the
safety parameters of your control depending upon the domain from which your control is being loaded.

ActiveX Control Download and Installation

Before we delve into the SiteLock template, we need to briefly discuss signed and unsigned controls. By
default IE 8 is set not to allow unsigned controls to download and install.

Fig 3. Disabled Unsigned Control Download

To change this setting (and I don’t think you should do this unless you’re testing and remember to
change it back), take a look in IE at Tools-> Internet Options -> Security -> Custom Level. There you can
set the option “Initialize and Script ActiveX controls not marked safe for scripting” to “prompt”. Having
changed this setting you will get the warning below in figure 4 instead of the one shown in figure 3.
Now, IE simply informs you of what control the website is trying download and install on your machine
and the publisher/vendor of the ActiveX control.

Fig 4. Install Warning


Should you need to do this during testing, to remove an ActiveX control from your machine ( installed by
IE 8 on an XP SP3 machine), you can do so by browsing to you C:\Windows\Downloaded Program Files\
folder, Right-Clicking on the control and selecting Remove.

Figure 5. Removing an ActiveX control installed by IE.

Signed and Unsigned

To sign a control you will need a public/private key-pair certified by one of the big certificate authorities
out there (13). Thawte (http://www.thawte.com/) seems to be well received by many people in the
field. Signing is done on the CAB file that you generate for you control. The CAB file is how your website
packages and distributes the ActiveX control. To create a CAB file you will need a companion INF file
with your OCX file. You will then feed these files to the cabarc tool found in the Microsoft Cabinet
Software Development Kit (http://support.microsoft.com/kb/310618). Details on how to do this are
found in the CodeProject mentioned in the next section (8).

The SiteLock Template

To really understand security with any system, one must experience that system and be familiar with its
ins-and-outs. I started exploring ActiveX controls through an online article on CodeProject titled “A
Complete ActiveX Example” (8). The example walks you through creating an MFC-based ActiveX control
and using it on a webpage. The article describes the different classes that need to be built and uses a lot
of the code generation capabilities provided by Microsoft Visual Studio to create the ActiveX control.
Once I had my ActiveX control I began looking into how I would integrate it with the SiteLock template.
The sitelock documentation (found in the install folder) describes two methods of implementing safety;
one involves inheriting from the IOleObject and the other from the IObjectWithSite, exclusively. Taking
the seemingly simple route and implementing IObjectWithSite didn’t bear fruit for me. After searching
high and low I discovered that the sitelock template provided by Microsoft addresses ATL-based ActiveX
controls. Further searching directed me to a CodeGuru thread, “ActiveX and
IObjectSafetySiteLock,IObjectWithSite” (11), that shed light on my problem.

MFC ActiveX controls inherit from the COleControl class which essentially exposes the IOleObject
interface. Remember the sitelock documentations mentions that you should either implement
IOleObject or IObjectWithSite, exclusively. My code in this instance had implemented both interfaces.
Unfortunately when you implement both interfaces, the methods implemented for IObjectWithSite are
ignored and precedence goes to the IOleObject interface which in my case did nothing. Thus, if you are
using MFC-based ActiveX controls, you are automatically forced down the route of implementing the
IOleObject interface and not the IObjectWithSite one. Following CodeGuru advice to get passed this I
eventually got things working with the MFC-based ActiveX control.

You will need to download the modified version of Sitelock.h that the commentators provide in their
thread. Next, you will need to change your control’s <control-name>ctrl.h and <control-name>ctrl.cpp
files to implement the IObjectSafetySiteLock Interface methods. You may receive a few compiler errors
and will most likely need to add a DECLARE_INTERFACE_MAP() in your <control-name>ctrl.h file.
Additionally, you must declare the type of safety you think your control affords, for example:

DWORD C<control-name>Ctrl::XObjSafe::dwSupportedSafety = INTERFACESAFE_FOR_UNTRUSTED_CALLER;

Testing my ActiveX control, I found the code either locking all sites out or allowing all sites the same
level of safety. To fix this I had to change the GetInterfaceSafetyOptions function to specify that sites not
on the approved list do not get the safety support indicated by dwSupportedSafety.

Fig 6. Patch to GetInterfaceSafetyOptions

With the above change in the code, IE will only apply your safety settings when the container webpage
is coming from a domain specified in your approved list. On all other pages coming from domains
outside your approved list, IE will not allow the ActiveX to load/script/initialize (IE 8 loads but blocks
operations, IE 6 disallows the loading). This means that if an illegitimate site tries to invoke your ActiveX
control, IE will block it. Also, if an approved site tries to do something that is not indicated as “safe”,
(that is, you have not set the dwSupportedSafety to INTERFACESAFE_FOR_UNTRUSTED_CALLER or
INTERFACESAFE_FOR_UNTRUSTED_CALLER), the respective activity will be blocked.

To better demonstrate this, I will step through an example. The following is the approved list identified
in my code:

The list thus “Allows” the 192.168.1.75 and localhost domains to interact with the control.

The above variable indicates that my control is safe for scripting and that IE should allow it to interact
with scripts on approved sites.

Loading a sample page that tests both scripting and initialization with the control from the legitimate
site we see the following:

Fig 7. PARAM initialization of an ActiveX Control

Notice that the webpage attempts to pass PARAM values to the ActiveX object through the Object tag.
The “Blocked” message indicates that IE blocked this action since in my code I only specified “scripting”
as safe.

What happens when the webpage tries to script the control? Let’s see:
Fig 8. Script interacting with ActiveX object

The webpage contains Javascript that interacts with the MyActiveX1 object setting the InputParameter
Property and invoking the LoadParameter() function. This happens when the submit button on a form
on the webpage is clicked:

Fig 9. Form

The LoadParameter code merely copies the input back out to the output.

The control then fires an event that is caught by another script on the page that writes it out to the
client:

So if we type “cool” in the form field on the webpage and hit submit, this is what we get:

Fig 10. Script handling ActiveX event


Fig 11. Result page of displaying output from ActiveX object

Thus, IE allowed the script to run and interact with the ActiveX control. This makes sense since the
domain the page is running from is approved and the safety flag indicates scripting is allowed in this
context.

What about if we run from another domain? I changed the IP address on the virtual machine I was using
to 192.168.1.38, loaded the page and submitted the form again.

Fig 12. Blocked access to control from illegitimate website


Notice how an error is reported and the activity is blocked. This is because the control does not include
the invoking domain in its list of approved domains. * Without the proposed patch I mentioned earlier in
GetInterfaceSafetyOptions, IE would not have blocked the scripting (it would have applied the same
safety settings to both approved and unapproved sites. This bug appears to exist also in the original
Microsoft sitelock.h code).

A final note on Site-locking: it is stated that if a website from an approved domain (which uses your
ActiveX control) is in any way vulnerable (say you have a Cross-Site-Scripting Vulnerability) then all bets
are off since the attacker can then utilize the legitimate domain’s website to attack users. The argument
for site-locking is defense-in-depth and not the fact that it might be the illusive silver armor/bullet.

Conclusion

This article has focused mainly on using the sitelock template to provide an added layer of security to
the use of ActiveX controls on the web. Since not all ActiveX controls need to interact with the
container, it is important to state this explicitly in the control’s code so that processes that load that
control are notified of permissible interactions with the control. The loading process in the example
discussed in this article was Internet Explorer. The ActiveX control in our example notified IE that it was
safe for scripting but not for Initialization. Accordingly, IE blocked initialization attempts to the control
from websites. The Sitelock template was then used to help further granularize safety-specification
making it specific to an approved list of domains from which the control can be loaded. An experiment
was set up to test interaction with the control from an approved domain and then from an unapproved
domain (ip address).

Having focused much of my attention on basic security concepts of ActiveX development I would like to
note here what has yet to be discussed and is likely to be the topic of future articles. COM components
are a novel idea for software re-use and have been very lightly discussed in this article, further
discussion is warranted in describing the COM framework and how COM components fit in to the bigger
picture of software development. Operating System interlocks on a deeper layer provide the possibility
of setting permissions for COM objects using the dcomcnfg.exe tool. It is important to understand how
the Operating System can be configured to place restrictions on the capabilities of COM components on
the user system. Finally, Zone-locking deserves some exploration with respect to how they can further
increase the general security of an ActiveX control.

You may find the example code I worked up here.

This document should be obtainable from the following links:

 http://www.evision.ws/ActiveXTest.pdf
 http://securedevelopment.blogspot.com/2010/03/sitelocking-activex-controls-for-
web.html
References

1. Designing Secure ActiveX controls (http://msdn.microsoft.com/en-


us/library/aa752035(VS.85).aspx)

2. Introduction to ActiveX controls (http://msdn.microsoft.com/en-


us/library/aa751972(VS.85,lightweight).aspx#Overview)

3. Safe Initialization and Scripting for ActiveX controls (http://msdn.microsoft.com/en-


us/library/aa751977(VS.85,loband).aspx)

4. ActiveX Security: Improvements and Best Practices (http://msdn.microsoft.com/en-


us/library/bb250471(VS.85,lightweight).aspx)

5. Developing Secure ActiveX controls (http://msdn.microsoft.com/en-us/library/ms885903.aspx)

6. How to tell if ActiveX vulnerabilities are exploitable in Internet Explorer


(http://blogs.technet.com/srd/archive/2008/02/03/activex-controls.aspx)

7. (Kill-Bitting) How to stop an ActiveX control from running in Internet Explorer


http://support.microsoft.com/kb/240797

8. CodeProject: A Complete ActiveX example


(http://www.codeproject.com/KB/COM/CompleteActiveX.aspx)

9. Hunting Security Bugs

10. SiteLock (A Safe-for-Scripting Template) (http://msdn.microsoft.com/en-


us/library/42a01w2f(VS.71).aspx)

11. CodeGuru thread: ActiveX and IObjectSafetySiteLock,IObjectWithSite


http://www.codeguru.com/forum/showthread.php?t=463703

12. Debugging ActiveX controls: (http://msdn.microsoft.com/en-us/library/w54zfak1(VS.71).aspx)

13. Introduction to Code Signing: (http://msdn.microsoft.com/en-


us/library/ms537361(VS.85).aspx#Ensuring_Integrity_a)

S-ar putea să vă placă și