Hi! Manuel Caballero here.

I had the pleasure of penetration testing (pen-testing) the previous versions of Microsoft Silverlight, and now, for the last three weeks, I’ve been playing around with the beta version of Silverlight 3. When I say, "the pleasure", I really mean it. Playing with Silverlight means to play with a plug-in that, from a security point of view, was born being already mature. It is obvious that the Silverlight team invested a great amount of time building Silverlight in such a way as to avoid a lot of security issues that other plug-ins had in the past. No question about that.

When you read about the security in Silverlight, undoubtedly you will find the term "Transparency" in reference to the Transparency Model (a concept borrowed from the .Net Framework 2.0). However, I want to borrow the term "Transparency" and use it from a completely different point of view.

I’ve been playing with the communication between Silverlight and its host, and the word “Transparent” came to my mind almost on every try. Let me explain why. When speaking about communication, Silverlight seems to be as secure as its host. My pen-test was done using Windows Internet Explorer 8 as the host and the plug-in was the Silverlight 3 Beta.

From a communication point of view, having the Silverlight plug-in on a page is like having another piece of JavaScript code. How safe is the JS code executed using Silverlight? It is as safe as executing JS straight from the browser. That’s why I say that the communication between Silverlight and its host is transparent -- because it is as if Silverlight were doing nothing at all, except for executing JS code just like the host would do.

Even if that seems to be obvious, it is not. Let’s take, for example, a well known plug-in: Adobe Flash. Flash has many ways to communicate with the host (ExternalInterface.call, fsCommand, Get/SetVariable, etc.) but legacy methods like getURL remain there, ready to use. Now, what is the problem with methods like getURL? The getURL is a method to load a URL in a window, frame, or IFRAME. The historic problem was that the implementation (the binary code used to load the URLs) was parallel to the one used by the browsers. It means that Flash bypassed the safe-implementation of the browser to load URLs, making the restrictions imposed by the host useless. For example, popup blockers could be bypassed using the getURL because the method to open a new window was not in the complete control of the host. In other words, using the Flash getURL method completely fooled the browser, bypassing a lot of the restrictions. Here’s a short example of an xDomain:

getURL("javascript:alert(document.cookie)", "IFRAME_NAME", "POST");

The getURL’s JavaScript code was executed inside the IFRAME with no domain restrictions at all. The xDomain policy of the browser was completely bypassed allowing the evil site to access the full DOM of the foreign (good guy) site.

This version of the xDomain worked great from Flash 7.x to Flash 9.0.115.0. It was fixed by Adobe when patching a different issue with the same root cause, but the bug comes long before Flash 7: a simple variation (GET instead of POST) used to work in older Flash versions.

To make the story short, the plug-in introduced a way to execute JS in the browser that was independent of the browser security policies. In fact, it bypassed many restrictions imposed by the browser. So why do plug-ins need to introduce new ways to load a URL when the host itself already has safe-methods to do that?

The getURL would have been much better if it only called the original browser method to load URLs, and not a native one. That, IMHO, would be transparent -- like not being there at all.

Now, what is the difference with Silverlight? The difference is clear: Silverlight calls the safe-browser methods straight, except in some rare cases where it parses the data before calling those same safe-browser methods. From a communication point of view, Silverlight is just a servant of the browser. If the browser is safe, so is Silverlight.

Let’s see two clear examples:

Example 1

One of the ways to access the host with Silverlight is through the HtmlPage class. For example, an HtmlPage.Window.Alert ("Hello") in Silverlight will call the alert method of the window object in the browser. It will not call the User32!MessageBox nor the MessageBox.Show of the .Net Framework. It will really call the alert method of the browser. In fact, if we override the original window.alert() in the host, Silverlight will call the new/overridden version of it. That’s good. That means that Silverlight is doing exactly what it has to do -- call the alert method and nothing more. No checks, no reinventing the wheel, no funny stuff. Just call the alert method that is already coded in the browser!

So, if we override the alert method in the browser using JavaScript:

window.alert = function(strText){document.write(strText);}

And then call the alert method through Silverlight:

HtmlPage.Window.Alert("Hello");

The result will be a document.write("Hello") in the host window. Exactly what is expected from a “Transparent” plug-in. The same happens with other methods such as Eval, Prompt, etc.

Example 2:

Now, to see how far this goes, let’s consider a scenario where the communication between the host and Silverlight is closed. We can do that by setting to false the enableHtmlAccess param in the OBJECT tag:

<object data="data:application/x-silverlight," […]>

<param name="enableHtmlAccess" value="false" />

</object>

Imagine that Silverlight is in a banner ad. So when the user clicks on it, the advertiser wants to open a popup window with their homepage inside. Because communication is closed, you can’t call the host native methods. However, Silverlight developers added a simple way to allow the plug-in to open a popup window (besides the HyperlinkButton which is a different story). It is the HtmlPage.PopupWindow() that works only when the AllowHtmlPopupWindow param is set to true or html access is permitted.

<object data="data:application/x-silverlight," […]>

<param name="AllowHtmlPopupWindow" value="true" />

<param name="enableHtmlAccess" value="false" />

</object>

From now on, the Silverlight object can call and successfully open a popup window using the HtmlPage.PopupWindow() method.

In this scenario, it seems that it would be logical for the Silverlight team to open the popup using a native method (just like the getURL in Flash) bypassing browser restrictions. I mean, step in the shoes of the guy who coded the HtmlPage.PopupWindow method. I’m sure the idea of forgetting about security for a second and "just open the damn popup window with whatever handy method I can" was in his mind. However, the Silverlight team has chosen once again to lessen the chances of new security bugs being introduced in the host by using the browser method.

Check it by yourself. Let’s override, via JS, the open method of the window object:

window.open = function(a, b, c){alert(a + ", " + b + ", " + c);}

Now disallow communication between the host and Silverlight, set to true the AllowHtmlPopupWindow, and then call the PopupWindow() from Silverlight:

HtmlPage.PopupWindow(new Uri("http://www.cracking.com.ar"),

tbHyperLinkTarget.Text, new HtmlPopupWindowOptions());

Enjoy the alert instead of the popup J.

So even when all bets are off, Silverlight plays by the rules and does only what is necessary to get the job done. That, IMHO, is very good!

Manuel Caballero.

Independent Security Researcher - http://www.cracking.com.ar

 

Share this post :