Walking the Stack
Permissions from the Caller’s Perspective
October 30, 2009
SecureASP.NET
LANGUAGES: ALL
ASP.NET VERSIONS: 1.1
Walking the Stack
Permissions from the Caller s Perspective
By Don Kiely
In the last column (ProtectingResources with Permission Objects), I took a brief look at .NET permissionsand how you might use them when your code is responsible for protecting avaluable resource. It all boils down to writing the code that tells the CLR tomake sure that whoever calls the code to access the resource has a certain typeof permission. As we saw last time, most often the called code instantiates apermission of the appropriate type and calls that permission object s Demandmethod. That causes the CLR to set off to check the call stack to make surethat everyone in the stack has the specified permission. There are lots ofvariations on how you can do that, including using attributes rather thanwriting code, but that s the basic idea.
This time around I ll look at permissions from theperspective of the calling code. The crucial concept here is that when a pieceof code Demands a permission, the CLR stops execution and walks the stack tomake sure that every caller in the stack has the required permission (unlessthe walk is modified in some way, which I ll discuss later in this column). Thepurpose of the stack walk is to prevent luring attacks, in which an attackerattempts to con trusted code into making a call to other code that protects aresource in an attempt to get illicit access to the resource. This is anextremely common attack, justifying all of Microsoft s hard work to implementthese security features.
Let s look at an example, which I ve taken from a code-generationutility that a friend wrote. In the image below, I show the call stack when thecode is somewhere in the AppendIfExists procedure (see Figure 1). Let s saythat this procedure is appending something to a file in a protected location onthe disk. That code might Demand a FileIOPermission. As soon as AppendIfExistscalls that method, the CLR starts walking the stack. In this case it checks theGetAllStoredProcXML procedure first. Does that have the proper FileIOPermissionpermission? Yes, it does, so the CLR continues its walk. Does the CreateMetaDatahave the required permission? Yes, it does. Then it checks the Run method,which happens to reside in another component. Maybe that component is runningfrom some location across the intranet, and local policy on the machine whereAppendIfExists is running doesn t trust intranet applications very much. Oops!Say it finds that the Run method doesn t have the necessary FileIOPermission.At that point the CLR stops the stack walk and throws a security exception soyou d better have code somewhere that handles that exception gracefully!
Figure 1: The call stack when thecode is somewhere in the AppendIfExists procedure.
Most of the time when called code demands a permission, thisis the scenario that plays out hundreds or thousands of times during typicalprogram execution. You might be concerned about performance, and rightly so.This is a lot of cycles that it is burning up, but Microsoft did a lot of workto optimize the process. I believe that it is a trivial price to pay for thesecurity it gives .NET applications.
But what if you want to influence the stack walk? Say youknow for a fact, because this code only executes in very controlled situations,that whoever calls CreateMetaData is trusted. Is there any way to circumventthe stack walk?
Of course there is! This is .NET, after all!System.Security.CodeAccessPermission, the mother of most permission objects in.NET, exposes four important methods that calling code can use to modify howthe CLR performs its stack walk:
Assert.Asserts that callers of the caller, which is executing the Assert method, havethe required permission.
RevertAssert.Can shorten duration of an Assert, by causing any previous Assert to be removedand no longer in effect.
Deny.Fails a stack walk of the specified permission, preventing code higher in thestack to access the protected resource.
PermitOnly.Fails any non-matching stack walk.
These can be a bit confusing, but it s not as bad as itseems. The good news is that you ll rarely need to use any of them. Even when youdo, you re most likely to use Assert. This method, called in any method up thecall stack from the code protecting the resource, effectively says, CLR, youlook tired. Let me do you a favor. I trust all the code that calls me, as wellas any code that calls the code that calls me, all the way up the stack. So youdon t need to do all that work of checking all that other code for the requiredpermissions. You go back now, and let that code that accesses that protectedfile execute, so I can get my work done.
That should be a scary scenario! What we ve done, assumingthat the CLR honors the Assert call, is circumvent the protection built into.NET to prevent luring attacks. If some code in the call stack isn t as saintlyas the Assert caller asserts, you have a security breach. So it is only in therarest circumstances that you should use Assert. When you do, you are takingfull responsibility for ensuring that a luring attack is impossible throughthis security hole you ve opened.
Fortunately, the .NET Framework provides protectionagainst malicious use of Assert. The code that calls Assert must itself havethe SecurityPermission permission with the SecurityPermissionFlag.Assertionflag set. This is a dangerous permission to have; if you ve carefully designedyour app to have only the permissions it absolutely requires, it shouldn t havethis permission. In the pre-defined ASP.NET trust levels, only the Full, High,and Medium trust levels have the Assertion form of SecurityPermission.
The other three methods are fairly esoteric refinements ofthe stack walk and Assert. The RevertAssert method lets you limit the damagepotentially done by using Assert by removing the Assert as soon as you nolonger need it. So you might call Assert immediately before calling the methodthat accesses the protected resource, then call RevertAssert immediatelythereafter. That way, any other code in the caller that executes thereafterwill have a normal stack walk. Deny and PermitOnly are rare enough that there sa good chance you won t have a need for them in your .NET programming career.
I have to emphasize an important point here: Thisdiscussion assumes that the calling code is not running with Full Trust. Fullytrusted code is dangerous code. I know that it s more work to write initially,but that is a tiny amount of effort compared to the risk you re exposing yourusers to, the time you ll spend on the help desk when your code is used inhacker attacks, and the angst you ll feel at being uncool. I ve written a lotabout this topic and least privilege here in asp.netNOW and in my blog at http://www.sqljunkies.com/weblog/donkiely/.There are a lot of resources available to help you with the job!
Don Kiely is senior technology consultantfor Information Insights, a business and technology consultancy in Fairbanks,AK. E-mail him at mailto:[email protected].
About the Author
You May Also Like