RequestOptional and RequestRefuse

The other day Eric Wilson asked how to ensure his code never ran with FullTrust. I replied that the "best" way was to refuse permissions you didn't want, and then Nicole Calinoiu replied that maybe requesting optional permissions was better.

Nicole is right -- requesting optional permissions is the "better" way to do this because you are "white listing" the permissions you need, not "black listing" the permissions you don't need, and from a security perspective white listing is always safer. The idea is that you do know what permissions you do need (it's a fixed set, determined by you) but you don't know all the permissions you don't need (it's a potentially infinite set, determined by the CLR and any 3rd party code installed on your system).

The trade-off, of course, is that white listing tends to be harder to manage then black listing, which is why most security measures use black lists even though they are less secure. The idea here is that users prefer functionality over security, and so it's better to assume that all unknown entities are "safe" and let them get their job done (with some amount of additional risk) rather than have them get frustrated and just turn off the system altogether (a really secure system that is turned off is much worse than a somewhat-secure system turned on!). For example, think of a virus scanner that blocks "known bad" code rather than allowing "known good" code, or an e-mail client that blocks "known bad" file extensions rather than allowing "known good" file extensions. How many people would leave their virus scanner or e-mail attachment blocker on if it didn't let you get any work done?

So, back to the point at hand, if you have some code that does various privileged things (read a database, display dialogs on the screen, etc.) but you know you never need to access the file system, maybe it is easier for you to just refuse FileIOPermission and be done with it. Yes, you take on some risk that somewhere, somehow your code can be tricked into doing bad stuff with (eg) the Registry, but if the rest of your code is well written it is unlikely.

On the other hand, if you have some code that only does one privileged thing (like display a message box) it is probably easier to simple request UIPermissionWindow.SafeSubWindows and be done with it. Now you will be secure against any potential luring attacks, but if you later decide to add more functionality to your application you may have to go back and re-visit your requests (although some of the new tools in Whidbey should help here -- argh! no links for permcalc.exe).

One thing to note is that RequesOptional will always grant you Execution (permission to execute), even if you don't ask for it. You'd be out of luck otherwise 😉

Thanks Nicole!

Comments (9)

  1. Stephane Rodriguez says:

    I am having a hard time figuring out what is the true intent of your post. It appears so much like you are saying that non-.NET apps are insecure, dismissing pretty much all applications out there.

    I am sorry but the operating system right now grants access by default as a consequence of the inability of MS to engineer an OS which would be useable without admin rights. Whenever you install a third party, the same story again. So what now, will you pretend that all third parties are insecure, and that developers are responsible for that ? What is the true intent of that, even more integration/coupling with the OS?

  2. Peter Torr says:

    Stephane, I am sorry but I don’t understand your comment. The intent of the post was to point out that yes, requesting *optional* permissions is a more secure way of writing code than refusing permissions, but that it is hard to manage.

    This post isn’t about 3rd party software being insecure, or about non-.NET apps being insecure, or about running on Windows with non-admin privileges.

    If there is something else you would like me to address, please post again.

  3. Stephane Rodriguez says:

    Denying access b y default, ie the Java sandbox security model, is fine for a fraction of applications out there, and completely irrelevant for others. If you read between the line, changing yes by default to no by default breaks compatibility. Net net, some completely irrelevant application security model is supposed to take over everyone’s app provided it’s running on top of the CLR. if this doesn’t hurt, particularly for new projects, fine, but that is probably a major limitation of internal Redmond views, they refuse to see the existing software. And not only because new projects are sexier.

  4. Eric Wilson says:

    Thanks for the post Peter. This helped me a lot.

  5. Peter Torr says:

    No worries. Glad someone liked it 😉

  6. Dave THomas says:

    A sample of the "best" way to implement this would clear things up for me…

  7. Nicole Calinoiu says:

    Thanks for the clarification. It’s good to know I haven’t been inadvertently pooching all my apps by taking what I perceive as the lazy route. <g>

    I’m very curious as to why you consider that the RequestOptional approach might be more work. If the goal is simply to not run with full trust, then I’d agree since all that’s necessary is to refuse one permission. However, is anyone who actually cares about security likely to aim for anything quite so trivial? It seems far more desirable to request the minimum necessary permission set. IMO, screening out permissions that aren’t required is a far more difficult route to the latter goal, even if one ignores (which one probably shouldn’t <g>) the possibility of extension of the available permission set outside the initial development environment.

    If one starts the development of any given assembly with execution permissions only, it’s a reasonably trivial task to add required permission requests as functionality is added. If one fails to request a required permission before release, then one obviously also failed to test the affected functionality properly, so it’s probably for the best that the functionality fails anyway. If one needs to add new functionality for a new release, what’s the difference in workload between adding a new RequestMinimum and dropping an old RequestRefuse?

    Using the white list approach also makes it much simpler to sort out security exceptions for deployed applications. Since the request list is self-documenting, it becomes reasonably trivial to compare it to the grant list for a deployed assembly in order to discover why security exceptions are occuring in environments that are outside the developer’s control.

  8. Peter Torr says:

    It’s just my opinion ;-). In a well-managed development cycle that has thought about security from the start, it might very well be easier to go with RequestOptional. But for customers trying to ship a product (or just customers who want to "do the right thing" but don’t have enough time or resources for a thorough analysis — remember not all code is shrink-wrapped, sold-to-the-public code; much of it is internal-only LOB code) refusing a few choice permissions that you know you don’t need is better than nothing.

    Either way, you still have issues though where you need a permission one day, but then you change the design and you don’t need it the next day (and who is going to update all the permission requests?). And if you are *really* going for "least privilege" then you have to be very fine grained, down to the exact files / reg keys / database tables / etc. you want to manipulate.

    This is where tools come in, such as the permcalc tool in Whidbey. It’s just too much work to expect the average developer (even a security-consious developer) to get it right all the time.

    Strictly speaking, just saying "I want to read/write the temp directory" is not good enough if you only need to read/write one (or ten or even one hundred) files out of it. And often times you don’t know ahead of time what requirements you have (eg, you create a temp file with a random name supplied by the system; there’s no way you can add a declarative attribute requesting the right permission in that case).

    Also it should be noted that even without any attributes, your code is _unlikely_ to be lured into doing something really bad. The two most likely avenues for attack are LinkDemands that you are silently (and unknowingly) satisfying, or delegates that are being used for nefarious purposes (which is mitigated by not having "normal" methods that match delegate signatures).

    I am by no means saying that refusing permissions is a bad idea; just that you aren’t automatically insecure because you failed to refuse / opt-in to any permissions.

    Basically, as always, it comes down to risk analysis. Cost-benefit trade-offs.

Skip to main content