Note: these are early notes based on some initial experiments with the Silverlight 5 beta, apply a pinch of salt to what you read.
For the longest time I’ve been talking about Silverlight’s sandboxing abilities by saying something like;
- “There are 3 different kinds of applications with Silverlight”
- In Browser
- Out of Browser
- Trusted Out of Browser
and I’ve always been able to say that the first two run in the same strong security sandbox while the last one runs in a weakened security sandbox and only after the user has explicitly granted the application the permission to do so having been warned ( using one of two dialogs depending on the application’s signature ) that the application could be malicious.
With Silverlight 5 this changes such that it’s now also possible to run an application in the browser and have it run with elevated permissions. Thankfully, it still requires explicit user consent
I wrote this amazing UI;
<Grid x:Name="LayoutRoot" Background="White"> <Viewbox> <TextBlock x:Name="txtStatus" /> </Viewbox> </Grid>
and a little piece of code;
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); this.Loaded += (s, e) => { this.txtStatus.Text = string.Format("I am {0}elevated", Application.Current.HasElevatedPermissions ? string.Empty : "not "); }; } }
and all was good in that I ran it in the browser and it said;
I then wondered how I would go about requesting elevated permissions for this application without specifying that it is an out-of-browser application but that’s not the route to take.
The route to take is to use the usual settings dialog in Visual Studio to mark the application as offering out-of-browser and requiring full trust.
so then I re-ran my application in the browser and saw;
Wow – I nearly had a heart-attack However, it’s not as bad as it seems. The runtime does not ( of course ) simply elevate an application because it asks for it. This is a special “developer” case because my application is coming from localhost (or 127.0.0.1). If I move my application to my real web server then I see;
Great – ok, so a real app coming from a real web server is not going to be elevated by default. How does it then become elevated?
It needs two more things;
- It needs the XAP file to be signed with a certificate that is present in the Trusted Publishers certificate store.
- A registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Silverlight\AllowElevatedTrustAppsInBrowser needs to be set to a value of 1 in order to allow this to work (NB: I don’t know at the time of writing how this translates to OS X).
I found on my machine that the registry key mentioned in step (2) wasn’t present on my machine.
So, walking through this from start to finish, how can I get my new application to run elevated in browser?
Making a Signing Certificate
The first thing I did was to make my own signing certificate. Of course, you should really go and buy one but I didn’t want to incur the cost just for this blog post.
I made my own root CA certificate;
makecert -n "CN=testRootCA" -r -sv testRootCA.pvk testRootCA.cer
and then I opened up MMC and went to the CurrentUser\Trusted Root Certification Authorities store and I imported my testRootCA.cer file into that store. There’s probably a command line flag that would avoid this step.
Then I made a signing certificate from that CA;
C:\temp\certy>makecert -sk testSigning -iv testRootCA.pvk -n "CN=testSigning" -ic testRootCA.cer testSigning.cer -sr currentuser -ss My
and that command line is installing that certificate into the personal store and it should be trusted because it chains up to the testRootCA.
But I need to make sure that my signing certificate is also in my CurrentUser\Trusted Publishers store so I go back to MMC and import that certificate into that store (my file is called testSigning.cer).
Signing the XAP
Now I can use this certificate to sign my XAP;
>signtool.exe sign /v /n testSigning SilverlightApplication10.xap
The following certificate was selected:
Issued to: testSigning
Issued by: testRootCA
Expires: Sun Jan 01 00:59:59 2040
SHA1 hash: 479DA92C472521332477F41F2CE58A900109A2E5
Done Adding Additional Store
Successfully signed: SilverlightApplication10.xapNumber of files successfully Signed: 1
Number of warnings: 0Number of errors: 0
which I might want to use as a post-build step in Visual Studio but, anyway, my XAP file is now signed.
Changing the Registry
Then I went and edited my registry as below;
and closed down any IE9 instances and then browsed to my application again;
and so there we have an elevated application running in the browser based on a registry setting and a signature for the XAP file that builds a trust relationship between the publisher and the installer of the XAP.
Browser and OS Control
It’s worth remembering that even though the Silverlight application is now trusted in the browser, it doesn’t mean that it can go beyond the reach of the browser itself.
One aspect would be around Internet Explorer’s Protected Mode. This has been in operation since IE7 and is well documented here and takes advantages of operating system changes that came in with Windows Vista whereby a process can be assigned an integrity level which limits its access to any securable OS objects (files etc) that are stamped with a higher integrity level.
Let’s see an example of this – let’s say I change the code in my app to do;
this.Loaded += (s, e) => { try { File.Create("c:\\temp\\foo.txt").Close(); this.txtStatus.Text = "Made file"; } catch { this.txtStatus.Text = "Failed"; } };
and then I re-sign and run it inside of IE9 then I see;
but if I switch IE9 to running in protected mode;
then the process runs in a low integrity level and so I see;
and so it’s worth being aware that “elevated” might not always mean “elevated” – there is an element of control here that remains with the browser process.
Beyond that, I think you should be able to do “whatever you like” and I certainly was surprised to have my in-browser application pop up a NotificationWindow just fine although I think there are still APIs which are the exclusive domain of the out-of-browser application such as Application.MainWindow and so on but that’s probably fairly intuitive.