I’ve moved this blog to my old domain, check it out:
May 20, 2008
September 19, 2007
Here’s a short guide for those who want to know some of the relevant security technology in the new IIS7 and ASP.NET.
- Attack Surface Reduction – even more locked down than IIS6 (default disabled)
- No more metabase – it’s all about applicationHost.config which can be stored centrally on a UNC share and shared among a web farm.
- Supports compatibility mode for IIS6 and “classic mode” ASP.NET
- Support for PHP and Perl via FastCGI
- Delegated Admin to application owners.
Enough about those areas, let’s focus on these new things:
- Integrated Request Processing Pipeline
- ASP.NET integration right smack in the pipeline
- REQUEST FILTERING (REPLACES URLSCAN)
- IIS7 URL AUTHORIZATION
- USING ENCRYPTION TO PROTECT PASSWORDS
- THE STAGES OF A REQUEST/RESPONSE – SERVER PIPELINE
NEW Integrated request processing pipeline and WCF
The integrated request processing pipeline architecture is a huge improvement. It used to be effectively two separate server pipelines, making it near impossible for ASP.NET developers to interact with the HTTP pipeline as they’d like to do.
Windows process Activation Service (WAS) now handles communication between listener adapters and application pools. WCF (Windows Communication Foundation) everywhere – WCF services can be hosted anywhere, in a console app, a forms app, a WPF UI, and:
- IIS can host non-HTTP services, utilizing WCF through
- Look forward to a lot of web services over net.tcp (think Silverlight and .Net 3.5)
The IIS6 Model:
The IIS7 Model – WAS starts up w3wp.exe and handles messaging. The following diagram illustrates the changes.
Custom Modules can extend or replace IIS functionality (replaces old ISAPI model) – such as replacing the Basic auth module with a custom authentication provider. These dll’s get stored in %WinDir%\System32\Inetsrv.
In IIS 6, HTTP modules could only be written in managed code and could only process ASP.NET requests. In IIS7, modules can be written in native code, and process any Web requests.
NEW ASP.NET Integration
ASP.NET now plugged right into the server pipeline, no more hanging off the ISAPI engine. Basically developers now have tons of power to extend request/response processing that wasn’t possible before. ASP.NET has been set free.
New collections ASP.NET now has access to:
Leveraging Integrated ASP.NET mode:
- Forms-auth, Membership and Role-mapping
- ASP.NET modules and functionality now available to all content, used to be only aspx pages and other ASP.NET content-types.
Check for “preconditions” that limit ASP.NET functionality to only managed handlers.
<modules> <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" preCondition="managedHandler" /> <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" />
Now if you remove the “precondition” (set by default) you can ensure AuthN and AuthZ is enforced for all content in the application. Otherwise only managed modules are handled.
NEW Request filtering (replaces URLScan)
Here’s a config to 1) normalize URL’s by disallowing double escaping, 2) disallow high bit characters, and 3) set a deny all file extension list.
These are set in the global applicationHost.config and can be overridden per application.
<fileExtensions allowUnlisted="true" > <add fileExtension=".asp" allowed="false"/> </fileExtensions> </requestFiltering> </security> </system.webServer></configuration>
Control things like:
- Which VERBs are allowed
- If double encoding allowed
- High-bit ASCII allowed or not
- File extensions allowed
- URL sequences (e.g. “..”) or use to set a default “deny all” policy and include explicit directories
Microsoft Ops story from dogfooding Microsoft.com the other week:
Gotcha for Microsoft.com: If filename includes “+” then allowDoubleEscaping must be set to “true“
Allow or disallow specific file extensions and verbs
<add fileExtension=”.exe” allowed=”false” />
<add sequence=”./” />
<add sequence=”/.” />
NEW IIS7 URL Authorization
Provides declarative access controls for the entire application – no code needed.
- Can be used with machine accounts or domain accounts
- Can be used with ASP.NET Membership and Roles and also for custom identities
- Stored in web.config files for easy distribution
- Can be configured through UI (not in ASP.NET UrlAuthorization)
- Implemented in assembly %windir%\System32\inetsrv\urlauthz.dll<add
- Applies to all content, not just .aspx or .asmx pages like the old ASP.NET UrlAuthorization
- ASP.NET UrlAuthorization was very developer focused, new IIS7 UrlAuthorization is more Administrator focused
Configuration section system.webServer/security/authorization – looks like:
<authorization lockElements="clear"> <add accessType="Deny" users="*" /></authorization>
- * = anonymous users ? = authenticated users
- Rules evaluated from Parent-level first, Deny rules first. With the lockElements=”clear” setting you force inheritance to lower levels so nobody can override the setting. * ASP.NET UrlAuthorization would evaluate from the bottom up, so this wouldn’t work.
NEW Using Encryption to Protect Passwords
WAS service runs as LOCALSYSTEM and needs access to identity passwords to launch Application Pools under. Still appears similar to IIS6 but there’s now a GUI and a different way of doing it. Basic steps:
- Create a new RSA key that only LOCALSYSTEM and Administrators have access to. This key will be used to encrypt passwords for every application pool. From the command line:createProvider.exe iisWasKey RsaKeyForWAS Rsa_WAS
- Create the application pools and encrypt their passwords. First set the default provider:setProvider.exe Rsa_WAS
Then configure the application pools to run with those accounts. Take a look at applicationHost.config and you’ll see the encrypted passwords.
- Lock down the encryption providers!!! By default IIS_IUSRS has read access to the keys when they are created. Remove that access so only LOCALSYSTEM and Administrators have access.cd /d %systemroot%
aspnet_regiis.exe -pr iisWasKey IIS_IUSRS
The stages of a request/response – Server Pipeline
The stages of the server pipeline, exposed as HttpApplication events in ASP.NET:
- BeginRequest. The request processing is starting.
- AuthenticateRequest. The request is being authenticated. IIS and ASP.NET authentication modules subscribe to this stage to perform authentication.
- AuthorizeRequest. The request is being authorized. IIS and ASP.NET authorization modules check whether the authenticated user has access to the resource being requested.
- ResolveRequestCache. Cache modules can check whether the response to this request exists in the cache, and return it instead of proceeding with the rest of the execution path. Both ASP.NET Output Cache and the new IIS Output Cache features execute here.
- MapRequestHandler. This stage is internal in ASP.NET, and is used to determine the request handler.
- AcquireRequestState. The state necessary for the request execution is being fetched. ASP.NET Session State, and Profile modules obtain their data here.
- PreExecuteRequestHandler. Any tasks before the execution of the handler can be performed here.
- ExecuteRequestHandler. The request handler executes here. ASPX pages, ASP pages, CGI programs, and static files are served here.
- ReleaseRequestState. The request state changes are saved, and the state is cleaned up here. ASP.NET Session State and Profile modules use this stage for cleanup.
- UpdateRequestCache. The response can be stored in the cache for future use here. The ASP.NET Output Cache and IIS Output Cache modules execute here to save the response to their caches.
- LogRequest. This stage is used to log the results of the request, and is guaranteed to execute even if errors occur.
- EndRequest. This stage is used to perform any final request cleanup, and is guaranteed to execute even if errors occur.
Checklist and Questions for Security Review
- Did you remove access to decryption keys so that only LOCALSYSTEM and Administrators have access?
- Did you remove the “precondition” so that ASP.NET AuthN and AuthZ applies to all content?
- Are you creating native code HTTP modules?
* is it Global or request-level
Are you creating a Hosted Web Core application?
* gets its own ApplicationHost.config separate from IIS
* it won’t inherit IIS process monitoring, health and recycling features
- Are you using the Runtime State and Control API (RSCA) for monitoring/management?
- Are you running a legacy application on IIS7?
- Dynamic Configuration – are you modifying system or application pool configurations in the code? (AppHostAdminLibrary)
IIS 7.0 Extend Your WCF Services Beyond HTTP With WAS
September 16, 2007
To understand the main concepts that will affect host and application security in IIS 7.0, I’ve done some research and compiled a small paper. This should help break the ice and give security consultants like myself, developers and architects a quick view into some of the important security concepts around configuration and development in IIS7.
ETA 1 day.
September 14, 2007
Okay it’s on, I ran the preparation tool fine, rebooted, turned Bitlocker on (the TPM was already on via the BIOS). The TPM ownership password was set during TPM initialization, which I might change later, but there’s not much point now. I set the PIN I’ll use to boot up the computer, and copied the Recovery Key to a USB drive. The Recovery Key is useful if the computer has problems and I need to move the drive to a new machine.
All in all, so far it’s smooth. The drive is currently encrypting which takes a while – at about 11% one hour later. I have a 7200 rpm 200 GB drive. Even unallocated space gets encrypted but they’ve optimized performance in that area – http://blogs.technet.com/bitlocker/
Been running 64 bit Vista for a few weeks now, my reliability score’s pretty low (lots of red-balls and app crashes). But things overall seem pretty normal and fast. Running on a Thinkpad T61.
I didn’t prepare for Bitlocker though, only creating a single huge partition. Luckily the Bitlocker Drive Preparatin Tool handles this. As I’m writing it just finished preparation – it took some free space from C: and created an S: partition of 1.5gb which will be the active partition. Hopefully I’ll reboot and things will work.
I’m interested in Bitlocker’s affect on speed and performance. So I’ve created a few informal tests to time things, though I expect the difference to be low – as the product team says, it’s in the single digit percentages.
September 8, 2007
Good article on using the System.Reflection Assembly classes ReflectionOnlyLoad* methods to specify an assembly should be load, well, for reflection only! As in, not to execute anything in the assembly. This helps overcome some issues with reflection, and lets 32 bit code investigate a 64 bit assembly.
September 7, 2007
Historians and classicists check it, the British Library has a unique collection of rare and ancient books, available online not in your buttoned-up PDF but in a purely digital-lifelike form. One of the coolest applications of .Net 3.0, or only for that matter… but if you’re not there yet you can still view the Flash version (not as cool). Mozart’s notebook, Da Vinci’s diaries, Medieval works, the 15th century Libson Hebrew Bible… what could you possibly do with this? I dunno but turning the pages was pretty damn cool for a few minutes.
April 23, 2007
Maybe you’re building internationalized code and wondering how to build a whitelist filter that will support all the different character sets your planning to support. If you support more than ten, especially some of the larger east Asian sets, this might seem like an unwieldy or tricky process.
Well luckily it’s easier than most people would think. Building a good input validation filter can be simplified with .Net’s GetUnicodeCategory. But use the method from the System.Globalization namespace as the other one in System.Char looks like it may become the subordinate.
With GetUnicodeCategory you can simply build a whitelist supporting the character categories you want to allow. So get away from thinking you have to write a regEx filter and list out all the character ranges you want to allow in each character set, it’s much simpler than that!
The Unicode standard assigns ever character to one of about 31 categories. They make sense too, for example Other Control charactes (Cc) , Lowercase Letter (Ll), Uppercase Letter (Lu), Math Symbol (Sm). So for example you might want to only allow letters, numbers, and punctuation in your whitelist. This could be achieved with the following snippet:
char cUntrustedInput; // the untrusted user-input
UnicodeCategory cInputTest = CharUnicodeInfo.GetUnicodeCategory(cUntrustedInput);
if (cTestCategory == UnicodeCategory.LowercaseLetter ||
cTestCategory == UnicodeCategory.UppercaseLetter ||
cTestCategory == UnicodeCategory.DecimalDigitNumber ||
cTestCategory == UnicodeCategory.TitlecaseLetter ||
cTestCategory == UnicodeCategory.OtherLetter ||
cTestCategory == UnicodeCategory.NonSpacingMark ||
cTestCategory == UnicodeCategory.DashPunctuation ||
cTestCategory == UnicodeCategory.ConnectorPunctuation)
// character looks safe, continue
// character is not allowed, fail
Not too bad eh.
April 4, 2007
ScottGu from Microsoft responds as to why ASP.NET AJAX is not so vulnerable to this issue. Doesn’t look like the best solution (basically the server requires an HTTP header Content-Type: application/json or it ignores the request).
The recent Windows .Ani file stack overflow has a lot of people asking the same question. How did Microsoft’s SDL process miss or punt this bug? Why did the compiler’s /GS not protect the function?
Michael Howard gives explanation as to why /GS did not protect this type of function, and how it can actually be made to.