Return to SecurityGuidanceFeedback


Security Guidance General Feedback Page

This page is for general comments, thoughts, ideas regarding patterns & practices security guidance.




Customer Feedback


RE: How To: Create a Service Account for an ASP.NET 2.0 Application

I followed these instructions to the letter, but when I try to invoke the app from my browser after adding it to the pool (with identity set to a domain user -- same domain as server), it challenges me for a password and then refuses to accept valid domain account information. It’s like the pool account doesn’t have access to validate my security token. I say this because my domain account never gets locked out even though it usually would after three failed attempts. I take that to mean the browser is authenticating me okay, but the server is unable to validate the security token.

If I don’t put it in the test pool, it runs fine and says “NT AUTHORITY\NETWORK SERVICE” as expected. Aspnetregiis.exe for .NET 2.0 ran successfully and the pool user is in the IISWPG group. Is there something else needed that is missing from this How To?

This is on Windows 2003 Server with the .NET 2.0 SDK installed.





RE: Security Question List Asp.Net 2.0 and Managed Code (.Net 2.0)

These should be great resources, but they're fundamentally flawed in their mistakes, ommissions and unneccesary additions. Their core value would be that you could print them out and use them straight away as a code-review guide, but you can't because they're not right. If I have to re-sub edit it myself, much of the value is lost (and I'm not going to get any updates you make)

Specific points that spring up are:

Duplication between ASP.Net 2.0 and the Managed Code checklist.
Which should one use? The ASP.Net one does not include everything from the Managed Code one, so it can't be used in isolation, but duplicates enough that you have to waide through most things twice. Make your mind up guys.

Ommisions from the checklist
You don't even 'mention' ASP.Net request validation, and what it provides (despite an earlier article by many of the same authors http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000004.asp), yet you talk about sanitising input from cookies or querystring.
Nor do you adequately explain when XSS is and isn't an issue when using ASP.Net controls, or even provide a link.

Errors in the checklist
"Review static class constructors to verify that they are not vulnerable
if two or more threads access them simultaneously. If necessary, synchronize
the threads to prevent this condition"

This is wrong, the framework does this for you:
"The Framework internally guarantees thread safety on static type initialization"
as per http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/singletondespatt.asp
"The static constructor for a class executes at most once in a given application domain"
as per http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/vclrfcsharpspec1011.asp

Relevance in the checklist
As a C# programmer I don't really care about how printf can be misused, nor do I care about dangerous unmanaged API's when we're not doing any P/Invoke.

What's really needed here is a way that I can filter the checklist by relevance; when I uncheck 'I use a SQL database', 'I call out into unmanaged code', 'I use C++' I want a smaller checklist to print. The 'How to perform a security code review...' guide makes the point about focus and clear objectives, yet we have to go though the checklist with a pair of scissors to remove the chuff.

Hey I don't mean to be down, but I just can't use these checklists as-is. I guess I'm just disappointed.

-- Piers7




RE: How To: Use ADAM for Roles in ASP.NET 2.0

How To: Use ADAM for Roles in ASP.NET 2.0
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000018.asp

Something very strange here. I followed the article to a tee and got a persistent ERRORFILENOT_FOUND on the line:

protected void Page_Load(object sender, EventArgs e)
		    {
		        if (!Roles.RoleExists("TestRole"))
		        ...
	

To troubleshoot connecting to the AzMan store, I used the following initialization code found in this article:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000019.asp

AzAuthorizationStoreClass AzManStore = new AzAuthorizationStoreClass();
AzManStore.Initialize(0, ConfigurationManager.ConnectionStrings
		            ["LocalPolicyStore"].ConnectionString, null);
	
IAzApplication azApp = AzManStore.OpenApplication("AzManDemo", null);

The ERRORFILENOTFOUND persisted. The AzAuthorizationStore.Initialize documentation (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/azauthorizationstoreinitialize.asp) says that when 0 is passed for param lFlags, the system expects the policy store to exist and will otherwise fail with ERRORFILENOT_FOUND.

To troubleshoot AzAuthorizationStore.Initialize, I passed AZAZSTOREFLAG_CREATE and the method succeeded. The next line, AzAuthorizationStore.OpenApplication failed with error,

Element not found. (Exception from HRESULT: 0x80070490)

which is to be expected if the policy store was created there at runtime. But here's the puzzle:

I can open the policy store with Authorization Manager using the connection string passed to AzAuthorizationStore.Initialize. Moreover, after the change to pass AZAZSTOREFLAG_CREATE, the store still cannot be opened at a later time. So, what the heck is it creating? What is going on here?




RE: Security Question List: Managed Code (.NET Framework 2.0) - Impersonation

I believe the advice for cleaning up properly when using impersonation - see the Impersonation topic at Security Question List: Managed Code - doesn’t completely explain the vulnerabilities related to exceptions, specifically exception filter attacks. My understanding is that the .NET exception mechanism is a 2-pass mechanism with exception filters evaluated on the first pass and finally blocks executed on the second pass. The following code is therefore safe if, and only if, ""FileException"" or a subclass of ""FileException"" is the only exception thrown by ReadSecretFile():

		 try
		 {  
		   [ElevatePrivilege();]
		   [ReadSecretFile();]
		 }
		 [catch(FileException] fe)
		 {
		   [ReportException();]
		 }
		 finally
		 {
		   [LowerPrivilege();]
		 }
	

If this is incorrect then the code can be attacked by the following Visual Basic code if we assume that the C# code is a callee of CallMethodThatElevatesPrivileges()

		 Try
		   [CallMethodThatElevatesPrivilege()]
		 Catch When [ElevateMyPrivilege()]
		   ' Do nothing; we simply want to run the exception filter.
		 End Try
	

		 Private Function [ElevateMyPrivilege()] As Boolean
		   ' This code now has the privileges elevated by [ElevatePrivilege()] in C# code above.
		   Return False
		 End Function
	

A more realistic scenario would be when the C# code doesn’t know precisely what exceptions will be thrown by ReadSecretFile() or how to handle them. To properly protect against this in C# you need to add a “catch all” block, which calls LowerPrivilege() and re-throws the exception. This also means that LowerPrivilege() must be robust to multiple invocations.

		 try
		 {  
		   [ElevatePrivilege();]
		   [ReadSecretFile();]
		 }
		 catch
		 {
		   [LowerPrivilege();]
		   throw;
		 }
		 finally
		 {
		   [LowerPrivilege();]
		 }
	

If written in Visual Basic, the code can be protected using an exception filter. This removes the need to actually handle and re-throw the exception but requires that LowerPrivilege() return a Boolean result. Another way of protecting the impersonation code is to take it out of ElevatePrivilege() and place it in the same stack frame as the reverting code. This is because the CLR annotates the stack frame where the impersonation code was executed. In this mode the impersonation is reverted automatically by the CLR before the first pass of the exception mechanism so we can remove the catch block altogether. Of course, this only works if the stack frame with the CLR annotation still exists when the exception is thrown. This isn’t the case in the code above because the annotation occurs somewhere in ElevatePrivilege(), and this annotation has gone by the time ReadSecretFile() is called.

I think this shows that you need to update this section to correctly show the best practice for securing impersonation code. I don’t think the scenario where all possible exceptions are explicitly known and handled is realistic. For more information, Shawn Farkas wrote a series of blogs about this in March 2005 - see .NET Security Blog: How to Impersonate as a starting point.

-- KAW



Return to SecurityGuidanceFeedback
Microsoft Communities