I recently received this request for a post from Channel9:


I'm really interested ClickOnce and how it deals with security settings. I'm planning on creating C# game that uses managed direct3d. However even though its managed direct3d it is still treated, security wise, as unmanaged code.

I love how ClickOnce is able to recognize the app version and download a new version when available. I'd like to know more about this and how it might be used to only download certain sections of an application when they are needed. For instance, you might want the client to only download Level 2 after he has completed Level 1.


So lets talk ClickOnce security… [Things I talk about below may not be true tomorrow, or the day after that, or the day after that. Until you double click on that infinity icon and start publishing apps, this is subject to change.]

Manifest Integrity

First stop: manifest security. ClickOnce is based on 2 manifest files, the application manifest and the deployment manifest. The deployment manifest contains information about the deployment aspect of your application: is the app installed to the start menu and Add/Remove Programs (ARP for those who like to save keystrokes)? How does it update itself? What’s the name of the shortcut for the start menu (if it’s installed)? Finally, a reference to the application manifest. The application manifest contains information about the contents of your application: entry point assembly (your exe), assembly dependencies (dll’s that your app includes in its deployment), assembly prerequisites (stuff that has to be there or your app won’t run), loose files, satellite assemblies, etc.

Both of these manifests must be strong named signed in order for the ClickOnce runtime to even consider them. Our toolset will be more than happy to help you sign your manifests just like we’re happy to generate them for you. This is the first step in securing you ClickOnce app.

Code Access Security

ClickOnce security is based on the Code Access Security system that has shipped with .Net since the beginning. It’s pretty complex but here’s the 5 minute version:

Actions are guarded with permission objects. If an API needs to perform a certain action that it deems guardable, it demands the permission that guards it. The security system scans the current stack and if all the code there has the permission demanded then the call continues. Otherwise, a security exception is thrown. How do apps get these permissions? Your app comes with certain evidence (where it came from, it’s identity, etc.) and the security system compares that to the policy setup by your machine admin. There are 2 states your app can be in: Full Trust (where you pass all permission checks) and Partial Trust (where you have a delimited set of permissions). For example, an exe from http://foo.com gets a limited set of permissions (named ‘Internet’) on a default install of the framework: it can’t write to disk, it can only open files using common dialogs, etc. If it tries to perform an action it doesn’t have permission for, like access the registry, the API call it makes will demand that permission and the security system will check the call stack and throw an exception when it reaches the code that doesn’t have the permission.

This is a super-simplified version of a complex system. For further reading, check out: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcodeaccesssecurity.asp

And:

http://msdn.microsoft.com/msdnmag/issues/04/04/SecurityBriefs/

How does ClickOnce plug into this? Pretty simply: the application manifest lists the permission set, in XML, that the application requires to run. The app is given those permissions only, no more, no less. It’s up to the manifest author to determine what permissions are needed and put them in the manifest. Don’t worry, VS provides a nice UI and some assistance in determining what permissions you application needs. This is done to help enforce the principle of least privilege: your app should only be able to do what it needs to do. If your app is compromised, then the malicious code can only be as damaging as the app could be itself.

Runtime

When you click on a deployment manifest to run (and optionally install, depending on the manifest) your application, the evidence your application provides comes back into play. That evidence is given to the security system to determine what permissions you would normally get. That set is compared to the set is listed in your manifest. If the manifest set is a subset of the permissions you would normal get, the app runs/installs without a security prompt; the user’s machine is configured to allow you to do whatever it is that you want to do (note that you still only get the permissions in the manifest, even if your evidence would get you more permissions than you listed).

If you’re asking for more than you would normally get, then the user will receive a security escalation prompt warning them that this app could cause damage to their PC. If you ask for unlimited file IO and you’re downloaded from http://someshadyurl.com then a user has to take an overt act to let your app go to town.

There are ways to suppress this security prompt in a trusted setting but I’ll leave that for a future post (so this one doesn’t become 6 pages).

Download on Demand

Certain files can be marked in the application manifest as “Optional.” Those files are not downloaded when the app is first run. The developer of the app uses the API’s in System.Deployment.dll to download these files at a later date. The developer can also use these APIs to programmatically check if an update is available, download the update, etc. So, as to the scenario mentioned above, a developer would put some code at the end of each level to go and see if there is another level and download it. He can configure his application to automatically get the latest version before the app is run, at specified intervals, or when the user hits the “Update” button in his app. Rolling back is also available if a developer discovers a nasty bug in the latest version. The app can be pointed to a different URL to get it’s updates from (for example, you can distribute and app on a CD rom that looks for updates at http://yoursite.com).

Any other questions about ClickOnce? Comment below!