<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.iis.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:cs="http://blogs.iis.net/"><channel><title>Wade Hilmo</title><link>http://blogs.iis.net/wadeh/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Debug Build: 20510.895)</generator><item><title>Dynamic IP Restriction Proxy Mode</title><link>http://blogs.iis.net/wadeh/archive/2012/08/01/dynamic-ip-restriction-proxy-mode.aspx</link><pubDate>Wed, 01 Aug 2012 20:26:14 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:4992460</guid><dc:creator>wadeh</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=4992460</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2012/08/01/dynamic-ip-restriction-proxy-mode.aspx#comments</comments><description>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Last week, we released the final version of our &lt;a href="http://blogs.iis.net/shauneagan/archive/2012/07/26/final-release-of-application-initialization-and-dynamic-ip-restrictions-extensions-are-now-available.aspx"&gt;Dynamic IP Restrictions module for IIS 7.x&lt;/a&gt;.&amp;#160; The feature is also built into IIS 8.0, which is included with Windows 8 and Windows Server 2012.&lt;/p&gt;  &lt;p&gt;At the highest level, Dynamic IP Restrictions works by looking at incoming client IP addresses and allowing the server administrator to restrict either the maximum number of concurrent connections, or throttle the rate of incoming requests.&lt;/p&gt;  &lt;p&gt;For information on how to configure and use Dynamic IP Restrictions, we have published a help topic &lt;a href="http://learn.iis.net/page.aspx/1093/iis-80-dynamic-ip-address-restrictions/"&gt;here&lt;/a&gt; with screen shots that show all of the settings.&lt;/p&gt;  &lt;h1&gt;Requests behind a proxy&lt;/h1&gt;  &lt;p&gt;We’ve been showing this feature for some time now at various events, like Tech Ed, and one question invariably comes up:&amp;#160; What about clients behind a proxy?&lt;/p&gt;  &lt;p&gt;To handle that situation, Dynamic IP has a checkbox near the bottom of the page in Internet Services Manager entitled “Enable Proxy Mode”.&amp;#160; But what does this setting actually do?&lt;/p&gt;  &lt;p&gt;Proxy Mode allows Dynamic IP Restrictions to work with the client request header X-Forwarded-For to determine the IP address of the original client.&amp;#160; Wikipedia has a pretty good description of the header &lt;a href="http://en.wikipedia.org/wiki/X-Forwarded-For"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The way it works in general is that, when a proxy server gets a request from a client, it adds the client’s IP address to the end of a comma separated list of client IPs.&amp;#160; Assuming that a request goes though multiple proxies, you would get an X-Forwarded-For header that looks something like this (where you’d see IP addresses in place of the names below):&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;X-Forwarded-For: original-client, first-proxy, second-proxy&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Dynamic IP Restrictions can therefore determine the IP address of the original client.&lt;/p&gt;  &lt;h1&gt;But how can you trust data from the client?&lt;/h1&gt;  &lt;p&gt;Right after we explain support for the X-Forwarded-For header, the immediate next question is: How can you trust data from the client?&lt;/p&gt;  &lt;p&gt;This is actually a pretty insightful question, and I really enjoy hearing questions that demonstrate the knowledge of our users.&amp;#160; The ultimate answer to this question is that we can’t trust data from the client request without help from the server administrator.&amp;#160; And this is where the behavior of Proxy Mode is not as intuitive as it could be.&amp;#160; In order for it to be useful (or even functional), there is another configuration setting that needs to be made.&lt;/p&gt;  &lt;p&gt;Specifically, we look at the X-Forwarded-For header only if Proxy Mode is enabled *and* we recognize the IP address of the client as a known safe proxy.&amp;#160; A proxy server is considered safe only if its IP address is registered in the Allowed IP Address list.&amp;#160; The logic works like this:&lt;/p&gt;  &lt;p&gt;1) A new request arrives at the server.&amp;#160; We get the IP address of the client from the network stack.&amp;#160; This address is trusted, since it came from the local machine’s network software and not from the HTTP request.&lt;/p&gt;  &lt;p&gt;2) If that IP address is on the Allowed list, we then know that it was the last entity to touch the X-Forwarded-For header and we consider the last entry on X-Forwarded-For to be a valid client IP address.&amp;#160; If the network stack IP address is not on the Allowed list, then we consider the client IP address to be the value from the network stack and will use it.&amp;#160; Otherwise, we go on to step 3.&lt;/p&gt;  &lt;p&gt;3) We know that the last entry on X-Forwarded-For is valid, so we then check to see if it is on the Allowed list.&amp;#160; If it is, then we know that the next-to-last entry on X-Forwarded-For was put there by a trusted proxy and we consider it valid.&amp;#160; If the last entry is not on the Allowed list, then we consider it to be the IP address and use it.&lt;/p&gt;  &lt;p&gt;We keep working our way from the end of X-Forwarded-For, towards the beginning until we reach an IP address that is not on the Allowed list.&amp;#160; In this way, we know which entries to trust because of the proxy servers listed in the Allowed IP List.&lt;/p&gt;  &lt;h1&gt;Some examples&lt;/h1&gt;  &lt;p&gt;Now let’s look at an example.&amp;#160; Consider the following value for X-Forwarded-For:&lt;/p&gt;  &lt;p&gt;X-Forwarded-For: 23.34.45.56&lt;/p&gt;  &lt;p&gt;Further, let’s assume that this request came through a load balancing proxy with the IP address 1.1.1.1, which is included on the Allowed list.&lt;/p&gt;  &lt;p&gt;When the request arrives at our server, we can see that it came from the proxy with the IP address 1.1.1.1.&amp;#160; Since this address is on the Allowed list, we look at the last entry in X-Forwarded-For and get 23.34.45.56.&amp;#160; Since this address is not on the allowed list, we will use 23.34.45.56 as the IP address for applying dynamic IP restrictions.&lt;/p&gt;  &lt;p&gt;----------&lt;/p&gt;  &lt;p&gt;Let’s look at another example.&amp;#160; In this case, let’s assume that the client is trying to bypass dynamic IP restrictions by forging an X-Forwarded-For header.&amp;#160; Finally, let’s say that Proxy Mode was enabled, but the request didn’t come through any proxy.&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;X-Forwarded-For: 9.9.9.9&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;When the request arrives at our server, we’ll get the client’s actual IP address; let’s say it’s 23.34.45.56.&amp;#160; Since 23.34.45.56 is not in the Allowed IP Addresses list, we don’t even look at the X-Forwarded-For header.&amp;#160; We use the client’s actual IP address for dynamic IP restriction processing.&lt;/p&gt;  &lt;p&gt;----------&lt;/p&gt;  &lt;p&gt;Finally, let’s look at a more complicated scenario, with a malicious client that is using your internet facing IP address in a fraudulent X-Forwarded-For header.&amp;#160; This is a clever thing to do because it assumes that your internet facing server is a proxy.&amp;#160; And let’s say that this assumption is correct.&amp;#160; To complete the scenario, let’s say that they are going through 2 proxies, both of which are trusted by inclusion on then Allowed IP Address list and have the addresses 2.2.2.2 and 1.1.1.1.&amp;#160; The X-Forwarded-For header now looks like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;X-Forwarded-For: 2.2.2.2, 23.34.45.56, 2.2.2.2&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;When the request arrives at our server, we can see that it came directly from the proxy with the IP address 1.1.1.1.&amp;#160; Since that IP address is on the Allowed list, we know that the last entry appended to X-Forwarded-For was put there by our trusted proxy.&lt;/p&gt;  &lt;p&gt;So now we know that the last entry on X-Forwarded-For can be trusted.&amp;#160; This entry is 2.2.2.2.&amp;#160; We look up this value in the Allowed IP Address list and find it there.&lt;/p&gt;  &lt;p&gt;We now know that the entry just before the previous one can be considered valid.&amp;#160; This entry is 23.34.45.56.&amp;#160; When we look it up on the Allowed IP Address list, we do not find it.&amp;#160; We Therefore use 23.34.45.56 as the IP address for dynamic IP restrictions.&lt;/p&gt;  &lt;p&gt;----------&lt;/p&gt;  &lt;p&gt;As you can see from these examples, we will never look at an entry in X-Forwarded-For unless we can validate its legitimacy by using the Allowed IP Address list.&lt;/p&gt;  &lt;h1&gt;How do I find the IP address of trusted proxies?&lt;/h1&gt;  &lt;p&gt;In our research on this topic, we’ve found that the majority of trusted proxies are going to be load balancers and reverse proxies that are owned by the same owner as the IIS server.&amp;#160; In these cases, the IP addresses will be well known.&lt;/p&gt;  &lt;p&gt;Finding the IP addresses of forward proxies out on the internet is a bit tougher question.&amp;#160; I’ve spoken with a number of people concerned that many of their web site visitors are coming from within corporations or other places where a large number of users are behind such a proxy.&amp;#160; This is. admittedly, a harder problem to solve.&lt;/p&gt;  &lt;p&gt;My suggestion to address this would be to use the IIS logs to find cases where Dynamic IP Restriction has been triggered.&amp;#160; This is easy to do by searching to logs for specific substatus codes.&amp;#160; In particular, Dynamic IP Restrictions uses the following substatus codes:&lt;/p&gt;  &lt;p&gt;501: Dynamic IP Restrictions rejected the request due to too many concurrent requests&lt;/p&gt;  &lt;p&gt;502: Dynamic IP Restrictions rejected the request due to too many requests over time&lt;/p&gt;  &lt;p&gt;Of course, these substatus codes may appear in combination with other HTTP status codes.&amp;#160; This is because Dynamic IP Restrictions allows you to customize the HTTP response in the case of rejection.&lt;/p&gt;  &lt;p&gt;Another very handy feature of Dynamic IP Restrictions is that you can use Logging Only Mode.&amp;#160; In Logging Only Mode, Dynamic IP Restrictions runs its normal logic but does not reject any requests.&amp;#160; Instead of rejecting requests, it will return the normal response and include one of the above substatus codes in the log to indicated that what it would have done in normal mode.&amp;#160; With this feature, you can test out settings without actually interrupting your traffic.&lt;/p&gt;  &lt;p&gt;The good news on this topic is that the anecdotal evidence we are seeing from early adopters is that this is not a common issue.&amp;#160; What we are hearing is that traffic volumes subject to this issue are generally not high enough to trigger errant rejections.&amp;#160; Of course, your specific situation may vary and you will need to tune your settings to find the proper balance.&lt;/p&gt;  &lt;h1&gt;Conclusion&lt;/h1&gt;  &lt;p&gt;The key takeaway here is that checking the “Enable Proxy Mode” box is only part of the process of supporting proxy server with Dynamic IP Restrictions.&amp;#160; You also need to specify the IP addresses of proxies that you wish to trust.&amp;#160; Also, you can be confident that when properly configured, Dynamic IP Restrictions works well with the X-Forwarded-For header and that clients cannot escape your restrictions by forging a bogus header.&lt;/p&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=4992460" width="1" height="1"&gt;</description></item><item><title>Application Initialization Part 2</title><link>http://blogs.iis.net/wadeh/archive/2012/05/01/application-initialization-part-2.aspx</link><pubDate>Tue, 01 May 2012 16:38:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:4960281</guid><dc:creator>wadeh</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=4960281</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2012/05/01/application-initialization-part-2.aspx#comments</comments><description>&lt;P&gt;In my &lt;A href="http://blogs.iis.net/wadeh/archive/2012/04/16/re-introducing-application-initialization.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2012/04/16/re-introducing-application-initialization.aspx"&gt;last post&lt;/A&gt;, I gave a bit of background on the &lt;A href="http://www.iis.net/download/ApplicationInitialization" mce_href="http://www.iis.net/download/ApplicationInitialization"&gt;Application Warm-Up module&lt;/A&gt;, now called Application Initialization.&amp;nbsp; This week, I would like to go into more detail as to what the Application Initialization module does, and how you should think about using it.&lt;/P&gt;
&lt;P&gt;As I mentioned earlier, the idea behind Application Initialization is that we want to provide a way that IIS can prepare an application to serve requests without having to wait for an actual client to make a request.&amp;nbsp; With Application Initialization, we break the problem down into 3 parts:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;How can I start the worker process that hosts my application without waiting for a request?&lt;/LI&gt;
&lt;LI&gt;How can I get the worker process to load my application without waiting for a request?&lt;/LI&gt;
&lt;LI&gt;How can my application send some kind of response so that clients don't see the browser hang until the application is ready?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I would like to address the first two questions here.&amp;nbsp; The third question is a bit more complex and I will save it for my next post.&lt;/P&gt;
&lt;H1&gt;Starting a worker process without waiting for a request&lt;/H1&gt;
&lt;P&gt;This is something that's not strictly speaking a part of Application Initialization in that we added this capability as a built-in feature of IIS, starting with IIS 7.5.&amp;nbsp; I will go over it here because it works hand in hand with Application Initialization to make the application available as soon as possible after starting IIS.&lt;/P&gt;
&lt;P&gt;This feature is controlled by a the startMode property for the application pool, described (along with other application pool properties) &lt;A href="http://www.iis.net/ConfigReference/system.applicationHost/applicationPools/applicationPoolDefaults" mce_href="http://www.iis.net/ConfigReference/system.applicationHost/applicationPools/applicationPoolDefaults"&gt;here&lt;/A&gt;.&amp;nbsp; The default value for startMode is OnDemand, which means that IIS will not spin up any worker processes until needed to satisfy a client request.&amp;nbsp; If you set it to alwaysRunning, IIS will ensure that a worker process is always running for the application pool.&amp;nbsp; This means that IIS will spin up a worker process when the World Wide Web Service is started, and it will start a new worker process if the existing one is terminated.&lt;/P&gt;
&lt;P&gt;Note that this property should not be confused with the autoStart property.&amp;nbsp; Understanding autoStart requires a bit of background knowledge.&amp;nbsp; Both application pools and worker processes can be started and stopped.&amp;nbsp; If an application pool is started, it means that IIS will accept requests for URLs within the pool, but it does not necessarily mean that there are any worker processes started.&amp;nbsp; If an application pool is stopped, IIS will return a "503 Service Unavailable" for any requests to the application pool and it will not start any worker processes.&amp;nbsp; The autoStart property is essentially a flag that IIS uses to know which application pools should be started when the World Wide Web Service is started.&amp;nbsp; When you stop an application pool in IIS Manager, autoStart is set to false.&amp;nbsp; When you start an application pool, autoStart is set to true.&amp;nbsp; In this way, IIS ensures that the same set of application pools are running after the World Wide Web Service is started and stopped (or through a machine reboot.)&lt;/P&gt;
&lt;P&gt;Now let's take a quick look at the configuration for an application pool that is set to be always available.&amp;nbsp; This application pool will start when the World Wide Web Service starts and it will immediately spin up a worker process.&lt;/P&gt;&lt;PRE style="BACKGROUND-COLOR: #ffffff; COLOR: black" id=codeSnippet&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;system.applicationHost&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;  &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;applicationPools&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;add&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="DefaultAppPool"&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;autoStart&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="true"&lt;/SPAN&gt; &lt;SPAN style="BACKGROUND-COLOR: #ffff00; COLOR: #ff0000"&gt;startMode&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND-COLOR: #ffff00; COLOR: #0000ff"&gt;="alwaysRunning"&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;  &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;applicationPools&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;system.applicationHost&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;With this configuration, the Default Application Pool will immediately spin up a worker process when IIS is started, and it will spin up a new worker process when the existing one exits.&lt;/P&gt;
&lt;P&gt;With IIS 7.5, this property was not exposed in IIS Manager.&amp;nbsp; It can be set by editing the &lt;A href="http://learn.iis.net/page.aspx/124/introduction-to-applicationhostconfig/" mce_href="http://learn.iis.net/page.aspx/124/introduction-to-applicationhostconfig/"&gt;applicationhost.config&lt;/A&gt; file directly or by one of IIS's scripting or programming APIs, or by the &lt;A href="http://technet.microsoft.com/en-us/edge/Video/ff710902" mce_href="http://technet.microsoft.com/en-us/edge/Video/ff710902"&gt;Configuration Editor&lt;/A&gt; UI tool.&amp;nbsp; In IIS 8, we have added the startMode property to the advanced properties page for the application pools UI.&lt;/P&gt;
&lt;H1&gt;How can I get the worker process to load my application without waiting for a request?&lt;/H1&gt;
&lt;P&gt;Now that you can see how to get IIS to spin up a worker process without waiting for a request, the next thing to address is how to get an application loaded within that worker process without waiting for a request.&amp;nbsp; The Application Initialization module provides a solution here, and as above, it is controlled by a single configuration property.&lt;/P&gt;
&lt;P&gt;The Application Initialization module extends the IIS configuration by adding a new property to the application settings called preloadEnabled (in IIS 8, this property is built-in.)&amp;nbsp; Let's take a look at what this looks like in the configuration where I've added a new application to the default web site and enabled it for preload:&lt;/P&gt;&lt;PRE style="BACKGROUND-COLOR: #ffffff; COLOR: black" id=codeSnippet&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;system.applicationHost&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;  &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;sites&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;site&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Default Web Site"&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;id&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="1"&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;      &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;application&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;path&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="/"&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;virtualDirectory&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;path&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="/" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;physicalPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="%SystemDrive%\inetpub\wwwroot"&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;      &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;application&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;      &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;application&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="AppInit" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;applicationPool&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="DefaultAppPool" &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND-COLOR: #ffff00; COLOR: #ff0000"&gt;preloadEnabled&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&lt;SPAN style="BACKGROUND-COLOR: #ffff00"&gt;="true"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;virtualDirectory&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;path&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="/AppInit" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;physicalPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="c:\inetpub\wwwroot\appinit"&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;      &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;application&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;site&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;  &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;sites&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;system.applicationHost&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Here's how Application Initialization uses this property.&amp;nbsp; When a new worker process spins up, Application Initialization will enumerate all of the applications that it will host and checks for this property.&amp;nbsp; For any application where preloadEnabled="true", it will build a URL corresponding to the default page for the application and run it through the pipeline.&amp;nbsp; This request does not go through the network, and there is no client listening for a response (IIS discards any data that would have gone to the client.)&lt;/P&gt;
&lt;P&gt;This "fake" request accomplishes a few key things.&amp;nbsp; First, it goes through the IIS pipeline and kicks off an application start event.&amp;nbsp; This initializes a number of parts inside of IIS, and if the request is for ASP.NET, it will cause global.asax to run.&amp;nbsp; It also reaches the application, which will see it is the first request after starting.&amp;nbsp; Typically, I expect that applications will just handle this request just like any other request from a real client, but we do set some server variables into our "fake" request, so an application with awareness of this feature could implement special processing if it chose to do so.&lt;/P&gt;
&lt;P&gt;There is another important aspect to this process.&amp;nbsp; When IIS spins up a new worker process, there is two way communication between &lt;A href="http://technet.microsoft.com/en-us/library/cc735229(v=ws.10).aspx" mce_href="http://technet.microsoft.com/en-us/library/cc735229(v=ws.10).aspx"&gt;WAS&lt;/A&gt; and the new process.&amp;nbsp; This allows WAS to know precisely when the worker process is ready to accept new requests.&amp;nbsp; It also allows the worker process to get information from WAS as to whether it is going to be a new process to start taking requests, or whether it's a replacement process to take over for an older process that's being recycled.&lt;/P&gt;
&lt;P&gt;This is an important distinction.&amp;nbsp; In the case of a new worker process, we want to start taking client requests as soon as possible, which is the way that things work outside of Application Initialization.&amp;nbsp; In the case of a replacement process, though, Application Initialization will prevent the new process from reporting itself ready for new requests, until all of the preload requests (and any warumup requests, which I will discuss later) have completed.&amp;nbsp; This means that no client will ever have to wait for a process recycle to complete - because the old process will continue to take requests until the new one has completed all application initialization.&lt;/P&gt;
&lt;P&gt;In my experience, many applications with a slow startup will do their work even for a simple request to the default page.&amp;nbsp; For such applications, you can take advantage of improved application recycling simply by setting preloadEnabled="true" for that application.&amp;nbsp; Similar to the startMode property above, IIS 7.5 requires you to make this setting via direct edits or applicationhost.config, or via scripting or one of our config APIs, or via the Configuration Editor UI tool.&amp;nbsp; In IIS 8, we have added "Enable Preload" as a checkbox in the UI for application settings.&lt;/P&gt;
&lt;H1&gt;Next time...&lt;/H1&gt;
&lt;P&gt;The two topics that I've covered here should get you started with Application Initialization.&amp;nbsp; The ability to handle worker process recycles has been a highly requested feature.&lt;/P&gt;
&lt;P&gt;In my next post, I'll tackle the topic of what it means to initialize an application and what things an application developer can do to make things responsive during the time everything is warming up.&amp;nbsp; This is where we've made major changes and added a lot of stuff since the original beta release.&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=4960281" width="1" height="1"&gt;</description></item><item><title>(Re)introducing Application Initialization</title><link>http://blogs.iis.net/wadeh/archive/2012/04/16/re-introducing-application-initialization.aspx</link><pubDate>Mon, 16 Apr 2012 20:25:51 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:4935425</guid><dc:creator>wadeh</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=4935425</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2012/04/16/re-introducing-application-initialization.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;“IIS is a demand-driven web server, i.e. IIS does things only when asked for…”&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This was the start of a &lt;a href="http://blogs.iis.net/thomad/archive/2009/10/14/now-available-the-iis-7-5-application-warm-up-module.aspx"&gt;blog post&lt;/a&gt; back in late 2009 announcing the beta for the IIS 7.5 Application Warm-Up module.&amp;#160; The idea behind this module is to address a common customer need.&amp;#160; Specifically, the demand driven nature of IIS is such that it doesn’t load application code until it’s needed to handle a request.&lt;/p&gt;  &lt;p&gt;Many applications do a significant amount of work when they first start.&amp;#160; And in many cases, the framework needed to run the application is loaded in the same way.&amp;#160; Finally, it may be necessary for the application framework to compile some or all of the application code before it can handle that first request.&amp;#160; All of this leads to an all too common situation where the unlucky client that makes the first request the application has to endure a long wait before they see the first response.&lt;/p&gt;  &lt;p&gt;So back before IIS 7.5 was released, we asked ourselves what functionality would be needed to help to address this problem.&amp;#160; The results of that thinking were two new features in IIS 7.5, one of them an administrative feature, and one of them a new interface in the IIS pipeline.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;I’d like to talk about the pipeline change first.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The IIS pipeline is the heart of the IIS runtime – the part that determines how an IIS worker process responds to events, like the arrival of a request that needs to be served.&amp;#160; The pipeline is a collection of event notifications and application programming interfaces (APIs) that modules can plug into and do work when things happen.&amp;#160; The IIS product team uses these events an APIs to implement all of the interesting parts of what people think of as IIS in the form of modules.&amp;#160; For example, IIS uses a module called StaticFileModule to be able to serve plain files.&amp;#160; It uses a module called DefaultDocumentModule to know how to serve the default document for virtual directory or application.&amp;#160; Modules are also used for things other than serving request.&amp;#160; The WindowsAuthenticationModule implements Windows authentication, and the UriCacheModule implements certain caching that you don’t see, but improved the performance of the pipeline.&amp;#160; If you are a programmer interested in the pipeline, one of the coolest decisions that we made for IIS 7.0 was to make the same interfaces that we use on the product team available to anyone.&amp;#160; You can get started taking a look at it &lt;a href="http://msdn.microsoft.com/en-us/library/bb757040.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;So what does all of this have to do with warming up applications?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;IIS 7.5 introduced a new event to the pipeline called GL_APPLICATION_PRELOAD.&amp;#160; This event fires when the worker process is first starting up.&amp;#160; A module plugged in here can register for the event to do work before the worker process notifies &lt;a href="http://technet.microsoft.com/en-us/library/cc735229(v=ws.10).aspx"&gt;WAS&lt;/a&gt; that it is ready to handle requests.&amp;#160; At the same time, we added a new pipeline interface that allows a module to create requests and drop them into the pipeline.&amp;#160; These requests work just like requests from a client, except that there is no client, no network connection etc.&amp;#160; Unless they specifically look for it, modules don’t see a difference between these “fake” requests and requests with a live client on the other end.&amp;#160; Data that would normally be sent back to the client is discarded.&lt;/p&gt;  &lt;p&gt;These two things together create the opportunity to solve part of the problem that I mentioned at the start of this post.&amp;#160; When a worker process starts up, it can create a bunch of “fake” requests and send them through the pipeline.&amp;#160; These requests will run through their respective applications without having to wait for a live client to create the demand to start.&lt;/p&gt;  &lt;p&gt;So this looks good, but there is still a catch.&amp;#160; IIS worker processes (which each host there own pipeline) are themselves demand started.&amp;#160; Prior to IIS 7.5, the only way to start the worker process was for a client to make a request.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Start Mode&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The second new IIS 7.5 feature makes it possible to automatically start an IIS worker process without waiting for a requests.&amp;#160; This feature is pretty straightforward.&amp;#160; To enable it, just go to the advanced properties for the application pool in Internet Information Services Manager, and set “Start Automatically” to “True”.&amp;#160; Once you do this, worker processes for the application pool will be started up as soon as the IIS service starts.&amp;#160; You can do the same thing by setting the startMode property in applicationhost.config to alwaysRunning.&lt;/p&gt;  &lt;p&gt;So now, if you have a module that can send a list of requests through the pipeline, and you have the application pool set to auto start, all of the applications represented by the list of requests will be touched as soon as IIS starts.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Application Warm-Up Module&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The Application Warm-Up module that I first mentioned at the top of this post was to be the module to send the warmup requests.&amp;#160; Why do I say this in the past tense?&amp;#160; Back in March last year, we pulled the beta release and pointed the download page to a notice explaining that it was temporarily removed.&lt;/p&gt;  &lt;p&gt;There were a couple of things that happened leading up to the removal.&amp;#160; The first thing is that the functionality that I’ve listed above only solves a part of the problem.&amp;#160; The remaining puzzle piece is that, even under the best of circumstances, there is still a period of time after starting the application where it cannot respond to client requests.&amp;#160; If you need to restart the IIS service for any reason, even enabling Start Automatically does not help requests that arrive at the moment that the service starts.&amp;#160; To address that, there needs to be a way for IIS to actually send a response during the warmup period.&amp;#160; And there needs to be a way that an application can participate in what that response looks like.&amp;#160; If we wanted to solve that problem, we needed to make a deeper investment in the module.&amp;#160; And since we were fully engaged in the development of &lt;a href="http://blogs.iis.net/steveschofield/archive/2011/09/15/win8-iis-8-are-available.aspx"&gt;IIS 8&lt;/a&gt;, we were able to do just that as a part of the next major IIS release.&lt;/p&gt;  &lt;p&gt;The other factor is that, when we looked at how the beta module worked, we realized that we would need to make some changes to the new pipeline functionality that we introduced in IIS7.5.&amp;#160; Normally, when we introduce new APIs to IIS, we do so only when we are either going to use them ourselves or when we have a partner that is committed to using them before release.&amp;#160; The pipeline changes for warmup were an exception to this because we didn’t have time to do the module before IIS 7.5 released.&amp;#160; As sometimes happens when there is no code that depends on a new interface, we discovered that there were some things that would need to be fixed before Application Warm-Up could be made ship ready.&amp;#160; This meant that, over and above the new functionality in the module, we would need to ship a QFE for IIS 7.5 (which is included in the setup package for Application Initialization).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Where are we now?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Finally, after almost a year after we pulled the beta, we were able to release the &lt;a href="http://learn.iis.net/page.aspx/1089/iis-80-application-initialization/"&gt;Release Candidate version of Application Initialization&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;So that is the history up to this point for the Application Warm-Up/Initialization module.&amp;#160; There are still questions that I’d like to answer:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;- What is new in the RC?      &lt;br /&gt;- What’s the &lt;em&gt;easiest&lt;/em&gt; way to start using it?       &lt;br /&gt;- What about advanced usage and troubleshooting?       &lt;br /&gt;- Why did the name change?&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;I am going to address these questions and more in my next few blog posts.&lt;/p&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=4935425" width="1" height="1"&gt;</description></item><item><title>How IIS blocks characters in URLs</title><link>http://blogs.iis.net/wadeh/archive/2011/04/20/how-iis-blocks-characters-in-urls.aspx</link><pubDate>Wed, 20 Apr 2011 12:53:41 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:4390433</guid><dc:creator>wadeh</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=4390433</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2011/04/20/how-iis-blocks-characters-in-urls.aspx#comments</comments><description>&lt;p&gt;Recently, the question came up about why it is not possible for IIS to handle a URL that contains a ‘%’ character that is not part of an escape sequence.&amp;#160; The resulting discussion produced some informative references to the relevant RFC documents and also included some anecdotes on URL canonicalization.&lt;/p&gt;  &lt;p&gt;I would like to share my response to the question.&amp;#160; I hope that you find it informative.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;u&gt;Disclaimers and Assumptions&lt;/u&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Discussing how URLs is processed can be somewhat confusing because common usage of the term “URL” does not reflect the fact that there are different parts in the string that are processed differently.&amp;#160; Consider the following URL:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;i&gt;http://www.myserver.com/somefolder/somepage.aspx?morestuff&lt;/i&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It can be though of as 4 distinct parts that are each subject to their own rules and processing.&amp;#160; The first part is the protocol specification: “&lt;i&gt;http://&lt;/i&gt;”.&amp;#160; This information is used by the client to know what protocol to use when contacting a server to handle the request.&amp;#160; The second part is the hostname: “&lt;i&gt;www.myserver.com&lt;/i&gt;”.&amp;#160; This information is used by the client to resolve the IP address of the client and connect.&amp;#160; It may optionally include IP port information by using a colon to delimit the port ID: “&lt;i&gt;www.myserver.com:80&lt;/i&gt;”.&amp;#160; Notably, neither of these two parts of the URL are typically sent to the server.&amp;#160; They are consumed directly by the client and never put on the wire.&amp;#160; The exception to this is when your browser is configured to use a proxy server.&amp;#160; In that case, the client will sent them because the proxy server will need the information to know how to connect to the downstream server.&lt;/p&gt;  &lt;p&gt;The third and fourth parts of the URL are the path: “&lt;i&gt;/somefolder/somepage.aspx&lt;/i&gt;” and the query string: “&lt;i&gt;morestuff&lt;/i&gt;”.&amp;#160; This is the information that a web server deals with.&amp;#160; The URL canonicalization rules discussed in this post are applied to the path only.&amp;#160; The query string is generally considered opaque by the web server and left to the application that handles the request to process (ie. somepage.aspx in this example.)&lt;/p&gt;  &lt;p&gt;Next, I would like to note that there are many different components involved in processing a typical HTTP request that may apply their own rules regarding what is allowed in a URL and what is not.&amp;#160; In the case of IIS, the first component to see the request is http.sys.&amp;#160; This is the driver component that picks up the raw request from the wire and parses the HTTP protocol.&amp;#160; Next, the request goes to user mode and the IIS core server which sends the request through our pipeline.&amp;#160; In the pipeline, the request may be handled by any number of modules that can each get a look at the request.&amp;#160; In the case of this conversation, the module of interest is the &lt;a href="http://www.iis.net/ConfigReference/system.webServer/security/requestFiltering"&gt;RequestFilteringModule&lt;/a&gt;.&amp;#160; The request is then dispatched to a handler, which is a special module that is responsible for the heavy lifting work of processing the request and producing a response.&amp;#160; Some common handlers in IIS are the static file handler, which serves plain old static pages; ASP.NET which provides its own development platform and gives access to the .NET framework; and FastCGI, which provides a platform to support things like PHP.&lt;/p&gt;  &lt;p&gt;My expertise lies in IIS and the modules that ship with it.&amp;#160; Some of the common handlers, like ASP.NET and PHP can and do implement their own checks for URL validity, but I am not going to try and explain them because I don’t know their internals well enough.&amp;#160; I also would not consider myself an expert on http.sys, but I do know some things about how it validates URLs which I will explain here.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;HTTP.SYS&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Http.sys is the first component that looks at the incoming URL.&amp;#160; One of its jobs is to parse the HTTP request according to a well defined set of rules.&amp;#160; Strictness is important here as http.sys needs to protect itself from malformed requests.&amp;#160; For the URL, http.sys applies &lt;a href="http://www.ietf.org/rfc/rfc2396.txt"&gt;RFC 2396&lt;/a&gt;.&amp;#160; Http.sys also has a documented registry setting called &lt;a href="http://support.microsoft.com/kb/820129"&gt;AllowRestrictedCharacters&lt;/a&gt;, which opens things up a bit.&amp;#160; In the case of the original question that started this discussion, even this setting will not allow requests through with an ‘%’ character that is not part of an escape sequence.&amp;#160; The reason comes directly from RFC 2396, which as this to say in section 2.4.4 entitled “When to escape and unescape”:&lt;/p&gt;  &lt;p&gt;&lt;i&gt;Because the percent &amp;quot;%&amp;quot; character always has the reserved purpose of being the escape indicator, it must be escaped as &amp;quot;%25&amp;quot; in order to be used as data within a URI.&amp;#160; Implementers should be careful not to escape or unescape the same string more than once, since unescaping an already unescaped string might lead to misinterpreting a percent data character as another escaped character, or vice versa in the case of escaping an already escaped string.&lt;/i&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Request Filtering&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Once a request moves from http.sys to the IIS core server, the RequestFilteringModule will get a look at it.&amp;#160; This happens in the RQ_BEGIN_REQUEST notification.&amp;#160; The behavior of the request filter is pretty clearly called out by its schematized configuration, where we’ve tried to name the properties as clearly as possible.&amp;#160; I won’t go over all of the details here, but I do want to call out one property that generates some confusion:&amp;#160; allowDoubleEscaping.&amp;#160; &lt;/p&gt;  &lt;p&gt;The allowDoubleEscaping feature maps to an old &lt;a href="http://www.iis.net/download/urlscan"&gt;UrlScan&lt;/a&gt; feature called VerifyNormalization.&amp;#160; The original intent of VerifyNormalization was to ensure that any URLs passed to applications were reduced to their canonical form (see the caution above in the quote from RFC 2396 about misinterpretation of a ‘%’ character.)&amp;#160; Guaranteeing that a URL is in canonical form protects against the case where an application naively does its own unescape on a URL that has already been unescaped.&amp;#160; Strictly speaking, there is nothing in any RFC that disallows URLs that produce different results when decoded more than once, but proper process mandates that the application handling the request does the right thing.&amp;#160; As such, this check is a defense in depth measure.&amp;#160; We turn it on by default because misinterpreting non-canonical URLs is probably the most common type of bug that leads to security problems.&lt;/p&gt;  &lt;p&gt;So allowDoubleEscaping/VerifyNormalization seems pretty straightforward.&amp;#160; Why did I say that it causes confusion?&amp;#160; The issue is when a ‘+’ character appears in a URL.&amp;#160; The ‘+’ character doesn’t appear to be escaped, since it does not involve a ‘%’.&amp;#160; Also, RFC 2396 notes it as a reserved character that &lt;i&gt;can&lt;/i&gt; be included in a URL when it’s in escaped form (%2b).&amp;#160; But with allowDoubleEscaping set to its default value of false, we will block it even in escaped form.&amp;#160; The reason for this is historical:&amp;#160; Way back in the early days of HTTP, a ‘+’ character was considered shorthand for a space character.&amp;#160; Some canonicalizers, when given a URL that contains a ‘+’ will convert it to a space.&amp;#160; For this reason, we consider a ‘+’ to be non-canonical in a URL.&amp;#160; I was not able to find any reference to a RFC that calls out this ‘+’ treatment, but there are many references on the web that talk about it as a historical behavior.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;The IIS Core Server&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Ok, so getting back to the components that might be checking for URLs, I would like to say just a bit about the IIS core server itself.&lt;/p&gt;  &lt;p&gt;In general, the IIS core server does not enforce any restrictions on URLs - but there are a couple of things it does with the physical file mappings that are produced from URL mappings.&amp;#160; The core pipeline API exposes the IHttpFileInfo interface that allows modules to work with files in the IIS file cache.&amp;#160; The static file handler, for example, uses this interface.&amp;#160; Also, when you configure a handler to verify the existence of a file, the core itself uses this.&amp;#160; The file cache API will not work with file paths that contain a ‘:’ character.&amp;#160; The reason for this is that the colon is used by NTFS to specify alternate data streams.&amp;#160; It is possible to use alternate data stream syntax as a non-canonical way to get file data.&amp;#160; The most infamous case of this was the ancient &lt;a href="http://www.microsoft.com/technet/security/bulletin/ms98-003.mspx"&gt;::$Data bug&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The other notable thing that the IIS core does in any cases where it works with physical file names is that it uses a special syntax.&amp;#160; Specifically, we prepend “\\?\” to any local filenames, or “\\?\UNC\” to UNC filenames.&amp;#160; This special syntax tells Win32 file APIs that they should not attempt to do their own canonicalization on the filename and should instead pass it directly to the file system layers below.&amp;#160; This ensures that when we open a file, we are using its canonical name.&amp;#160; If a filename gets past our canonicalization checks and is still non-canonical, this will cause the file operation to fail.&amp;#160; The downside to this is that the CLR (at least the last time I checked) does not support this syntax.&amp;#160; So if you are writing a .NET application that uses IIS server variables, you may need to strip out the above prepends.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Conclusion&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;So there you have it.&amp;#160; This covers the things that a URL must pass through in order to be processed by IIS.&amp;#160; I hope that you find it informative and useful.&lt;/p&gt;  &lt;p&gt;-Wade&lt;/p&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=4390433" width="1" height="1"&gt;</description></item><item><title>Understanding Versions of the IIS FTP Server</title><link>http://blogs.iis.net/wadeh/archive/2009/09/03/understanding-versions-of-the-iis-ftp-server.aspx</link><pubDate>Fri, 04 Sep 2009 04:04:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:3386766</guid><dc:creator>wadeh</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=3386766</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2009/09/03/understanding-versions-of-the-iis-ftp-server.aspx#comments</comments><description>&lt;P&gt;It’s been a busy few days on the IIS Security Team.&lt;/P&gt;
&lt;P&gt;Earlier this week, a vulnerability was found in the IIS FTP server.&amp;nbsp; We have been working with security teams across Microsoft to research the issue and formulate a response to best protect our customers.&lt;/P&gt;
&lt;P&gt;Unfortunately, this finder chose to release the details of the vulnerability directly to the public instead of bringing it to our attention first.&amp;nbsp; When this happens, we have competing priorities:&amp;nbsp; We want to research the issue as thoroughly as we can.&amp;nbsp; And at the same time, we want to get information out to our customers as soon as possible so that they can protect themselves.&lt;/P&gt;
&lt;P&gt;In response to this issue, Microsoft issued &lt;A href="http://www.microsoft.com/technet/security/advisory/975191.mspx" mce_href="http://www.microsoft.com/technet/security/advisory/975191.mspx"&gt;Microsoft Security Advisory (975191)&lt;/A&gt; on Tuesday.&lt;/P&gt;
&lt;P&gt;Earlier today, this same finder released information for a second vulnerability in the IIS FTP server.&amp;nbsp; Again, the finder chose to release his information directly to the public.&amp;nbsp; While this new finding is a different issue, the impact, migitations and workarounds are very similar to the first issue; similar enough that both issues are now addressed in the above advisory.&lt;/P&gt;
&lt;P&gt;One significant difference is that different versions of FTP are affected in different ways.&amp;nbsp; This has resulted in some confusion about determining whether a particular server is vulnerable or not.&amp;nbsp; I will now attempt to clear up some of that confusion.&amp;nbsp; Note that the primary source of information on the details is the security advisory.&amp;nbsp; I will not discuss those details here.&lt;/P&gt;
&lt;P&gt;I will cover the most straightforward cases first:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Windows 2000 includes IIS 5.0, which includes FTP 5.0.&amp;nbsp; All of the issues in the security apply to this version of the FTP server.&lt;/LI&gt;
&lt;LI&gt;Windows XP includes IIS 5.1, which includes FTP 5.1.&amp;nbsp; All of the issues in the security advisory apply to this version of the FTP server.&lt;/LI&gt;
&lt;LI&gt;Windows 7 and Windows 2008 R2 both include IIS 7.5, which includes FTP 7.5.&amp;nbsp; None of the issues in the security advisory apply to this version of the FTP server.&amp;nbsp; It is unaffected by both these vulnerabilities.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The confusion arises with Windows 2003, Vista and Windows 2008.&amp;nbsp; Windows 2003 contains IIS 6.0; Vista and Windows 2008 contain IIS 7.0.&amp;nbsp; All of these platforms contain a version of FTP that we call FTP 6.0.&lt;/P&gt;
&lt;P&gt;Only it’s not quite that simple.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;We did some maintenance to FTP 6.0 between Windows 2003 and Vista.&amp;nbsp; As a result of this work, the first of this week’s two findings applies only to the older flavor that ships with IIS 6.&amp;nbsp; The second of this week’s findings apply to FTP 6.0 on all 3 Windows versions.&lt;/P&gt;
&lt;P&gt;The version story is even more confusing because we released FTP 7.0 as an add-on component to Vista and Windows 2008 and has also made FTP 7.5 available for these operating system versions.&amp;nbsp; Both FTP 7.0 and FTP 7.5 are unaffected by this week’s findings described in the above security advisory.&amp;nbsp; If you are running the FTP server with Vista or Windows 2008 and have not yet upgraded the FTP server, we strongly recommend that you consider upgrading to FTP 7.5.&amp;nbsp; We offer this upgrade for free.&amp;nbsp; You can find details &lt;A href="http://www.iis.net/extensions/FTP" mce_href="http://www.iis.net/extensions/FTP"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;If you are running the IIS FTP server on Windows 2003 or earlier, or if you choose to run FTP 6.0 on Vista or Windows 2008, please see the &lt;A href="http://www.microsoft.com/technet/security/advisory/975191.mspx" mce_href="http://www.microsoft.com/technet/security/advisory/975191.mspx"&gt;security advisory&lt;/A&gt; for the most current information on mitigations and workarounds.&lt;/P&gt;
&lt;P&gt;I would like to touch on one other topic on the subject of IIS versions.&lt;/P&gt;
&lt;P&gt;The IIS FTP server is hosted in the same process as the IIS Admin Service.&amp;nbsp; In IIS 6.0 and earlier, all of the IIS services are dependent on this service.&amp;nbsp; Because both vulnerabilities have the potential to terminate this process, a successful denial of service attack to FTP will also shut down all IIS services, including the web server.&lt;/P&gt;
&lt;P&gt;IIS 7.0 has a different architecture and the IIS 7.0 web server is not dependent on the IIS Admin Service.&amp;nbsp; For this reason, a successful denial of service attack against FTP 6.0 will not affect the IIS 7.0 web server.&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=3386766" width="1" height="1"&gt;</description></item><item><title>Running Perl on IIS 7</title><link>http://blogs.iis.net/wadeh/archive/2009/04/13/running-perl-on-iis-7.aspx</link><pubDate>Tue, 14 Apr 2009 00:53:04 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:3085729</guid><dc:creator>wadeh</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=3085729</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2009/04/13/running-perl-on-iis-7.aspx#comments</comments><description>&lt;p&gt;We've had a few people on our forums asking about running Perl on IIS 7. This led to some discussion on the team about getting it to work with FastCGI.&lt;/p&gt;  &lt;p&gt;The team has been doing a lot of great work with the &lt;a href="http://www.microsoft.com/Web/downloads/platform.aspx"&gt;Web Platform Installer&lt;/a&gt; and &lt;a href="http://www.microsoft.com/web/gallery/"&gt;Windows Web App Gallery&lt;/a&gt; that feature popular PHP applications. Since PHP runs best on IIS with FastCGI, I suppose it was logical to turn to FastCGI for Perl as well.&lt;/p&gt;  &lt;p&gt;Sometimes, though, the right tool for the job is not the newest and flashiest thing. It turns out that this is the case for Perl. For many years, &lt;a href="http://www.activestate.com/"&gt;ActiveState&lt;/a&gt; has provided a free version of &lt;a href="http://www.activestate.com/activeperl/"&gt;ActivePerl&lt;/a&gt; that runs great on IIS using ISAPI instead of FastCGI.&lt;/p&gt;  &lt;p&gt;It's been a while since I've looked at ActivePerl, so I did some research last week to see the state of things and discovered that there are a few things you need to know in order to get it to work on IIS 7:&lt;/p&gt;  &lt;p&gt;ActivePerl is available as an ISAPI for 32 bits only. This does not prevent it from running on a 64 bit install of Windows. It just means that any application pool that contains Perl content must be configured to run as 32 bit. &lt;/p&gt;  &lt;p&gt;As of this writing, ActivePerl runs well on IIS 7, but its installer does not properly configure IIS 7 for running Perl scripts. After completing the ActivePerl installation, you will need to create handler mappings to associate requests for Perl scripts to the correct ISAPI based Perl interpreter. &lt;/p&gt;  &lt;p&gt;There are at least two different ISAPI extensions with ActivePerl. You should make sure that you use PerlEx30.dll with IIS 7. If you use perlis.dll, you may find that response headers sent from your Perl script are added to your response page instead of going back to the client as headers. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Given the above information, here are the steps to get ActivePerl running on IIS 7:&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. Install ActivePerl from http://www.activestate.com/activeperl/. At this time, there is a link to version 5.10 for Windows (x86) on this page. This link downloads an MSI installer to your machine which you can run. &lt;/p&gt;    &lt;p&gt;2. If you are running the 64 bit version of Windows 2008, ensure that your application pool is configured to run as 32 bit. Assuming that you will be using ActivePerl in the default application pool, these steps will do it: &lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;From the Windows 'Start' menu, pick run and type &amp;quot;inetmgr&amp;quot; (without the quotes). Click on 'OK&amp;quot;. &lt;/li&gt;      &lt;li&gt;In the left hand pane of IIS Manager, open up the settings for your server. Click on &amp;quot;Application Pools&amp;quot;. &lt;/li&gt;      &lt;li&gt;In the Application Pools page, select &amp;quot;DefaultAppPool&amp;quot;. &lt;/li&gt;      &lt;li&gt;In the right hand pane, under &amp;quot;Edit Application Pool&amp;quot;, click on &amp;quot;Advance Settings...&amp;quot; &lt;/li&gt;      &lt;li&gt;In the Advanced Settings dialog, ensure that &amp;quot;Enable 32-bit Applications&amp;quot; is set to &amp;quot;True&amp;quot;. &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;3. Create a handler mapping that associates &amp;quot;*.pl&amp;quot; requests with ActiveState's perlex30.dll extension using the following steps: &lt;/p&gt;    &lt;p&gt;4. In the left hand pane of IIS Manager, select your server. This will apply the following handler mappings on the entire server. If you would like to do this for just a specific site or application, you can open up the server and select any site or application. In the center pane, double click on the Handler Mappings icon. &lt;/p&gt;    &lt;p&gt;5. When the Handler Mappings pane is displayed, click on the &amp;quot;Add Module Mapping...&amp;quot; item in the Actions pane on the right. &lt;/p&gt;    &lt;p&gt;6. Fill out the Add Module Mapping dialog as follows: &lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;For Request Path, enter &amp;quot;*.pl&amp;quot;. &lt;/li&gt;      &lt;li&gt;For Module, select &amp;quot;IsapiModule&amp;quot; from the dropdown list. Note that the ISAPI module is a prerequisite. If it does not show up on this list, it will need to be installed an an IIS optional component. &lt;/li&gt;      &lt;li&gt;For Executable, enter &amp;quot;c:\perl\bin\PerlEx30.dll&amp;quot; (without the quotes.) Note that this assumes that you've installed ActiveState Perl using its default location. If you installed it in another location, you will need to look there for perlex30.dll. &lt;/li&gt;      &lt;li&gt;For Name, enter &amp;quot;ActiveState Perl for .pl&amp;quot;. Note that this name is just a label and does not affect functionality. It does need to be unique, though. If you are going to be associating other file extensions with ActiveState Perl, the names for those mappings will need to be different. &lt;/li&gt;      &lt;li&gt;You do not need to do anything with the &amp;quot;Request Restrictions...&amp;quot; button. If you wish to limit this mapping to specific HTTP verbs, etc., it can be done there. &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;7. Repeat the above steps for any additional file extensions you wish to be associated with Perl. On IIS 6, ActiveState Perl creates mappings for &amp;quot;*.pl&amp;quot;, &amp;quot;*.plx&amp;quot; and &amp;quot;*.plex&amp;quot;. Additionally, some applications are known to map &amp;quot;*.cgi&amp;quot; with Perl. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That's it. After doing this, ActiveState Perl should run on IIS 7.&lt;/p&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=3085729" width="1" height="1"&gt;</description></item><item><title>How IIS can help with SQL Injection</title><link>http://blogs.iis.net/wadeh/archive/2008/12/18/how-iis-can-help-with-sql-injection.aspx</link><pubDate>Thu, 18 Dec 2008 23:48:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2818938</guid><dc:creator>wadeh</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=2818938</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2008/12/18/how-iis-can-help-with-sql-injection.aspx#comments</comments><description>&lt;P&gt;2008 has been a busy year for attackers exploiting SQL Injection vulnerabilities in web applications.&amp;nbsp; Once again, I am finding questions about this subject in my inbox.&lt;/P&gt;
&lt;P&gt;Earlier today, I found myself reviewing the material that's been published by Microsoft and others.&amp;nbsp; I was searching for a single, concise link that I could send out to describe what IIS's various filtering tools can do and how to set them up for the job.&lt;/P&gt;
&lt;P&gt;It turns out that there are so many articles out there, that the core "what can I do about it" message has been lost in the deluge.&amp;nbsp; For someone new to the issue, who just wants to know what to do, there is no good starting place.&lt;/P&gt;
&lt;P&gt;This post is my attempt to provide that starting place.&lt;/P&gt;
&lt;P&gt;Before getting into the details, no discussion about SQL Injection filtering is complete without the following caveat:&amp;nbsp; &lt;EM&gt;Filtering for SQL Injection is nothing more than a tool to help mitigate the issue.&amp;nbsp; It is not the final solution and it is not foolproof.&amp;nbsp; The only complete solution to prevent SQL Injection over the web is to fix vulnerable web applications on the server.&lt;/EM&gt;&amp;nbsp; For lots of in-depth information about the root cause of SQL Injection vulnerabilities and strategies for fixing them, here are some suggested links:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ms161953.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms161953.aspx"&gt;Definition of SQL Injection&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/aa224806.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa224806.aspx"&gt;SQL Server Injection Protection&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/cc676512.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc676512.aspx"&gt;Preventing SQL Injections in ASP&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ms998271.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms998271.aspx"&gt;How To: Protect from SQL Injection in ASP.NET&lt;/A&gt; &lt;BR&gt;&lt;A href="http://forums.asp.net/t/1254125.aspx" mce_href="http://forums.asp.net/t/1254125.aspx"&gt;Coding Techniques for protecting against SQL Injection in ASP.NET&lt;/A&gt; &lt;BR&gt;&lt;A href="http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx" mce_href="http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx"&gt;Filtering SQL Injection from Classic ASP&lt;/A&gt; &lt;BR&gt;&lt;A href="http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx" mce_href="http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx"&gt;Security Vulnerability Research &amp;amp; Defense Blog on SQL Injection Attack&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;What that caveat out of the way, here is how IIS can help to mitigate against SQL Injection attacks:&lt;/P&gt;
&lt;P&gt;It is possible to filter input to IIS so that HTTP requests containing information deemed dangerous by the server administrator can be blocked before a web application is allowed to process them.&amp;nbsp; In the context of SQL Injection, this means that IIS can look for SQL statements in various parts of the request and shut them down before they become a problem.&lt;/P&gt;
&lt;P&gt;The actual tools and methods for doing this are different for different IIS versions.&amp;nbsp; Starting with IIS 7, request filtering is included as a core feature and is installed by default on all IIS 7 servers.&amp;nbsp; Prior to IIS 7, IIS did not have this feature built in, but it is available as an add-on component.&amp;nbsp; So for IIS 6 and earlier, request filtering is accomplished via the UrlScan tool available as a free download.&lt;/P&gt;
&lt;P&gt;I have prepared posts describing step-by-step instructions for setting up filtering for SQL Injection attempts at the following links:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;To set up SQL Injection filtering for IIS 7 and later, go &lt;A href="http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-7-and-later.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-7-and-later.aspx"&gt;here&lt;/A&gt;. &lt;/LI&gt;
&lt;LI&gt;To set up SQL Injection filtering for IIS 6 and earlier, go &lt;A href="http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-6-and-earlier.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-6-and-earlier.aspx"&gt;here&lt;/A&gt;. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Finally, it has become very clear to me today that the state of the art changes pretty rapidly.&amp;nbsp; I've seen many articles that talk about betas and other versions that were current at the time they were written - but are no longer current today.&amp;nbsp; I fully expect that the blog posts I'm writing today are going to fall victim to that same trend.&lt;/P&gt;
&lt;P&gt;To address that issue, I am going to see if we can set up an area on iis.net for security articles that are always kept current.&amp;nbsp; Once we have that, we can put a SQL Injection article there and let that be the canonical location for guidance from the IIS team on that topic.&amp;nbsp; With the holidays approaching, it will likely be well into January before I can make this happen, but it's now on my agenda.&lt;/P&gt;
&lt;P&gt;Thanks, &lt;BR&gt;-Wade&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2818938" width="1" height="1"&gt;</description></item><item><title>Filtering for SQL Injection on IIS 6 and earlier</title><link>http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-6-and-earlier.aspx</link><pubDate>Thu, 18 Dec 2008 23:47:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2818934</guid><dc:creator>wadeh</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=2818934</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-6-and-earlier.aspx#comments</comments><description>&lt;P&gt;This article is specific to IIS 6 and earlier.&amp;nbsp; If you are using IIS 7.0 or later, please see &lt;A href="http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-7-and-later.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-7-and-later.aspx"&gt;this article&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;The IIS team has created an add-on tool for IIS called UrlScan that is able to filter HTTP requests.&amp;nbsp; If a request is found to have contents deemed unacceptable to the administrator, it will be blocked before it is processed by a web application.&amp;nbsp; This feature is useful as a mitigation tool in defense of SQL Injection vulnerabilities.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Note that any scheme that filters SQL Injection attempts is only a mitigation.&amp;nbsp; The complete solution to the problem requires fixing vulnerable web applications.&amp;nbsp; For more information about SQL Injection vulnerabilities and strategies for fixing them, here are some suggested links:&lt;/EM&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ms161953.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms161953.aspx"&gt;Definition of SQL Injection&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/aa224806.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa224806.aspx"&gt;SQL Server Injection Protection&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/cc676512.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc676512.aspx"&gt;Preventing SQL Injections in ASP&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ms998271.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms998271.aspx"&gt;How To: Protect from SQL Injection in ASP.NET&lt;/A&gt; &lt;BR&gt;&lt;A href="http://forums.asp.net/t/1254125.aspx" mce_href="http://forums.asp.net/t/1254125.aspx"&gt;Coding Techniques for protecting against SQL Injection in ASP.NET&lt;/A&gt; &lt;BR&gt;&lt;A href="http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx" mce_href="http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx"&gt;Filtering SQL Injection from Classic ASP&lt;/A&gt; &lt;BR&gt;&lt;A href="http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx" mce_href="http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx"&gt;Security Vulnerability Research &amp;amp; Defense Blog on SQL Injection Attack&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Prerequisite&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Before getting started, you will need the current version of UrlScan.&amp;nbsp; As of the date of this writing, it is version 3.1.&amp;nbsp; Most of the information here will also work with UrlScan 3.0, but there are a number of bug fixes in 3.1 and it is strongly encouraged that you upgrade if you are running an earlier version.&amp;nbsp; A free download of UrlScan 3.1 can be found &lt;A href="http://www.iis.net/extensions/UrlScan" mce_href="http://www.iis.net/extensions/UrlScan"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Configuring UrlScan&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;UrlScan is configured via the urlscan.ini file.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Open the urlscan.ini file in the following path: &lt;/LI&gt;&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;%systemroot%\system32\inetsrv\urlscan\urlscan.ini&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;UL&gt;
&lt;LI&gt;Search the urlscan.ini file for "RuleList=" (without the quotes.) &lt;/LI&gt;
&lt;LI&gt;Add "SQLInjection" (without the quotes) to the end of the RuleList line.&amp;nbsp; If there is already an item or items in the RuleList, use a comma to separate them. &lt;/LI&gt;
&lt;LI&gt;Create the following new sections at the end of the urlscan.ini file: &lt;/LI&gt;&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;[SQLInjection] &lt;BR&gt;AppliesTo=.asp,.aspx &lt;BR&gt;DenyDataSection=SQLInjectionStrings &lt;BR&gt;ScanURL=0 &lt;BR&gt;ScanAllRaw=0 &lt;BR&gt;ScanQueryString=1 &lt;BR&gt;ScanHeaders= &lt;/P&gt;
&lt;P&gt;[SQLInjectionStrings] &lt;BR&gt;-- &lt;BR&gt;%3b ; a semicolon &lt;BR&gt;/* &lt;BR&gt;@ ; also catches @@ &lt;BR&gt;char ; also catches nchar and varchar &lt;BR&gt;alter &lt;BR&gt;begin &lt;BR&gt;cast &lt;BR&gt;create &lt;BR&gt;cursor &lt;BR&gt;declare &lt;BR&gt;delete &lt;BR&gt;drop &lt;BR&gt;end &lt;BR&gt;exec ; also catches execute &lt;BR&gt;fetch &lt;BR&gt;insert &lt;BR&gt;kill &lt;BR&gt;open &lt;BR&gt;select &lt;BR&gt;sys ; also catches sysobjects and syscolumns &lt;BR&gt;table &lt;BR&gt;update &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;UL&gt;
&lt;LI&gt;Save the changes to urlscan.ini. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;What effect does this have on my server?&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;With the above configuration in place, IIS will look at each incoming request for pages with .asp or .aspx extensions to search for specific strings in the request's query string.&amp;nbsp; If found, IIS will block the request and return a 404 Not Found page to the client.&amp;nbsp; If you want to change the file extensions, you can add or remove file extensions on the AppliesTo line.&amp;nbsp; The specific strings in the search are controlled by the entries in the [SQLInjectionStrings] section.&amp;nbsp; If you want to change the strings, you can do so by adding or removing entries here.&lt;/P&gt;
&lt;P&gt;It is worth noting that the above rule is fairly aggressive about blocking requests.&amp;nbsp; If this is an issue for your content, it is possible to make specific URLs exempt from UrlScan filtering.&amp;nbsp; To do this, search the urlscan.ini file for the [AlwaysAllowedUrls] section and add the exempt URLs (one per line.)&amp;nbsp; Note that URLs here should not include "http://hostname.com" or "https://hostname.com".&amp;nbsp; Follow the example in the urlscan.ini comments for this section.&amp;nbsp; Also note that the behavior of this section has changed with UrlScan 3.1.&amp;nbsp; If you are using UrlScan 3.0, you cannot bypass query string filtering in this manner.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Note that it is very important that you thoroughly check any URLs for SQL Injection vulnerabilities before adding them to the [AlwaysAllowedUrls] section!&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;How can I check my logs for SQL Injection attempts?&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;UrlScan logs all of the requests that it blocks in UrlScan log files.&amp;nbsp; The default location for these files is %systemroot%\system32\inetsrv\urlscan\logs.&amp;nbsp; Beginning with UrlScan version 3.1, these logs are in W3C compliant format.&amp;nbsp; Rejections triggered by the above SQL Injection rule will have "rule+SQLInjection+triggered" in the x-reason field.&lt;/P&gt;
&lt;P&gt;You can check these logs periodically to see if you've been getting requests with SQL Injection attempts and also to see if your rule may be blocking legitimate requests.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;In Conclusion&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This should be everything you need to know to get a quick start in filtering SQL Injection attempts with UrlScan on your server.&amp;nbsp; For more information about things UrlScan can do, check out the articles &lt;A href="http://learn.iis.net/page.aspx/473/using-urlscan" mce_href="http://learn.iis.net/page.aspx/473/using-urlscan"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Happy UrlScan filtering, &lt;BR&gt;-Wade&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2818934" width="1" height="1"&gt;</description></item><item><title>Filtering for SQL Injection on IIS 7 and later</title><link>http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-7-and-later.aspx</link><pubDate>Thu, 18 Dec 2008 23:47:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2818936</guid><dc:creator>wadeh</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=2818936</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-7-and-later.aspx#comments</comments><description>&lt;P&gt;This article is specific to IIS 7 and later.&amp;nbsp; If you are using IIS 6.0 or earlier, please see &lt;A href="http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-6-and-earlier.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2008/12/18/filtering-for-sql-injection-on-iis-6-and-earlier.aspx"&gt;this article&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Starting with version 7.0, IIS has a built-in feature that is able to filter HTTP requests.&amp;nbsp; If a request is found to have contents deemed unacceptable to the administrator, it will be blocked before it is processed by a web application.&amp;nbsp; This feature is useful as a mitigation tool in defense of SQL Injection vulnerabilities.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Note that any scheme that filters SQL Injection attempts is only a mitigation.&amp;nbsp; The complete solution to the problem requires fixing vulnerable web applications.&amp;nbsp; For more information about SQL Injection vulnerabilities and strategies for fixing them, here are some suggested links:&lt;/EM&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ms161953.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms161953.aspx"&gt;Definition of SQL Injection&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/aa224806.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa224806.aspx"&gt;SQL Server Injection Protection&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/cc676512.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc676512.aspx"&gt;Preventing SQL Injections in ASP&lt;/A&gt; &lt;BR&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ms998271.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms998271.aspx"&gt;How To: Protect from SQL Injection in ASP.NET&lt;/A&gt; &lt;BR&gt;&lt;A href="http://forums.asp.net/t/1254125.aspx" mce_href="http://forums.asp.net/t/1254125.aspx"&gt;Coding Techniques for protecting against SQL Injection in ASP.NET&lt;/A&gt; &lt;BR&gt;&lt;A href="http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx" mce_href="http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx"&gt;Filtering SQL Injection from Classic ASP&lt;/A&gt; &lt;BR&gt;&lt;A href="http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx" mce_href="http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx"&gt;Security Vulnerability Research &amp;amp; Defense Blog on SQL Injection Attack&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Prerequisite&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Before getting started, you should verify the specific version of IIS that you are using.&amp;nbsp; If you are using SP1 or earlier with IIS 7.0, you will need to install &lt;A href="http://support.microsoft.com/kb/957508" mce_href="http://support.microsoft.com/kb/957508"&gt;this update&lt;/A&gt; to the request filtering component before applying the following configuration.&amp;nbsp; If you are using IIS 7.0 with SP2, or any later version of IIS, you do not need to install any updates.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Configuring the Request Filter&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;To create a global filtering rule for SQL Injection:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Open the applicationhost.config file in the following path: &lt;/LI&gt;&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;%systemroot%\system32\inetsrv\config\applicationhost.config&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;UL&gt;
&lt;LI&gt;Search the applicationhost.config file for "&amp;lt;requestFiltering&amp;gt;" (without the quotes.) &lt;/LI&gt;
&lt;LI&gt;Immediately under the &amp;lt;requestFiltering&amp;gt; tag, paste the following settings: &lt;/LI&gt;&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&amp;lt;filteringRules&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filteringRule name="SQLInjection" scanQueryString="true"&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;appliesTo&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add fileExtension=".asp" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add fileExtension=".aspx" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/appliesTo&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;denyStrings&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="--" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string=";" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="/*" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="@" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="char" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="alter" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="begin" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="cast" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="create" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="cursor" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="declare" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="delete" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="drop" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="end" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="exec" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="fetch" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="insert" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="kill" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="open" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="select" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="sys" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="table" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="update" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/denyStrings&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/filteringRule&amp;gt; &lt;BR&gt;&amp;lt;/filteringRules&amp;gt; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;UL&gt;
&lt;LI&gt;Save the changes to applicationhost.config. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;What effect does this have on my server?&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;With the above configuration in place, IIS will look at each incoming request for pages with .asp or .aspx extensions to search for specific strings in the request's query string.&amp;nbsp; If found, IIS will block the request and return a 404 Not Found page to the client.&amp;nbsp; If you want to change the file extensions, you can add or remove fileExtension tags in the &amp;lt;appliesTo&amp;gt; section.&amp;nbsp; The specific strings in the search are controlled by the &amp;lt;denyStrings&amp;gt; section.&amp;nbsp; If you want to change the strings, you can do so by adding or remove entries here.&lt;/P&gt;
&lt;P&gt;It is worth noting that the above rule is fairly aggressive about blocking requests.&amp;nbsp; It is possible that this rule will block legitimate requests.&amp;nbsp; If this is an issue for your content, it is possible to use a web.config file to create a rule that applies only to content under that web.config.&amp;nbsp; Do do this, remove any overly restrictive strings from the above applicationhost.config rule.&amp;nbsp; Then, in the web.config file, include the following configuration with the more restrictive settings in the &amp;lt;system.webServer&amp;gt; section.&amp;nbsp; For example, if you have content on the server that requires "end" in the query string, remove the &lt;EM&gt;&amp;lt;add string="end" /&amp;gt;&lt;/EM&gt; entry from applicationhost.config and then add the following into the web.config file where you want to restrict "end":&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&amp;lt;security&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;requestFiltering&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filteringRules&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filteringRule name="SQLInjection2" scanQueryString="true"&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;appliesTo&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add fileExtension=".asp" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add fileExtension=".aspx" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/appliesTo&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;denyStrings&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add string="end" /&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/denyStrings&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/filteringRule&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/filteringRules&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/requestFiltering&amp;gt; &lt;BR&gt;&amp;lt;/security&amp;gt; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Note that the name of the filteringRule tag must be unique and cannot conflict with a name in applicationhost.config or any other web.config files in the path.&lt;/P&gt;
&lt;P&gt;Also note that if you want to skip request filtering for all but a specific directory or directories, it is possible to omit the filtering rules in applicationhost.config entirely and just use web.config files to constrain the paths to which filtering applies.&lt;/P&gt;
&lt;P&gt;It is also possible to constrain the scope of filtering rules through the use of location tags.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;How can I check my logs for SQL Injection attempts?&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The request filter logs all of the requests that it blocks in the regular IIS W3SVC logs.&amp;nbsp; Rejections triggered by a filteringRule will have a status of 404 with a substatus 19.&lt;/P&gt;
&lt;P&gt;You can check these logs periodically to see if you've been getting requests with SQL Injection attempts and also to see if your rule may be blocking legitimate requests.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;In conclusion&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This should be everything that you need to know to get a quick start in filtering SQL Injection attempts on your web server.&amp;nbsp; For more information about things the request filter can do, check out articles &lt;A href="http://learn.iis.net/page.aspx/143/how-to-use-request-filtering/" mce_href="http://learn.iis.net/page.aspx/143/how-to-use-request-filtering/"&gt;here&lt;/A&gt; and &lt;A href="http://learn.iis.net/page.aspx/504/using-enhanced-request-filtering-features-in-iis7/" mce_href="http://learn.iis.net/page.aspx/504/using-enhanced-request-filtering-features-in-iis7/"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Happy request filtering, &lt;BR&gt;-Wade&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2818936" width="1" height="1"&gt;</description></item><item><title>UrlScan 3.1</title><link>http://blogs.iis.net/wadeh/archive/2008/10/31/urlscan-3-1.aspx</link><pubDate>Fri, 31 Oct 2008 20:06:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2717855</guid><dc:creator>wadeh</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=2717855</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2008/10/31/urlscan-3-1.aspx#comments</comments><description>&lt;P&gt;Earlier this year, it came to our attention that our customers were being subjected to a &lt;A href="http://blogs.iis.net/wadeh/archive/2008/06/24/urlscan-v3-0-beta-release.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2008/06/24/urlscan-v3-0-beta-release.aspx"&gt;SQL Injection attack&lt;/A&gt;.&amp;nbsp; In response to that, we updated the venerable UrlScan filter and released version 3.0 with new features that provide tools to provide some mitigation and allow users to &lt;A href="http://blogs.msdn.com/sdl/archive/2008/05/15/giving-sql-injection-the-respect-it-deserves.aspx" mce_href="http://blogs.msdn.com/sdl/archive/2008/05/15/giving-sql-injection-the-respect-it-deserves.aspx"&gt;address issues&lt;/A&gt; in their affected applications.&lt;/P&gt;
&lt;P&gt;This effort has been largely successful, but it has driven attackers to come up with new techniques.&amp;nbsp; Very recently, our internal security team brought it to our attention that they'd seen a &lt;A href="http://blogs.technet.com/neilcar/archive/2008/10/31/sql-injection-hijinks.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/10/31/sql-injection-hijinks.aspx"&gt;new variation&lt;/A&gt; on the attacks.&amp;nbsp; This new variation is trying to exploit a behavior in ASP's parsing of the query string for the Request.QueryString function.&amp;nbsp; &lt;EM&gt;Note that ASP.NET's behavior in this area is different and ASP.NET applications are not vulnerable to this specific new technique.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;The specific behavior in ASP results when the query string contains a name/value pair where the value contains a '%' sign that has not been escape encoded.&amp;nbsp; Consider the following examples:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If the client sends "page.asp?abc=xyz", calling Request.QueryString("abc") will return "xyz".&lt;/LI&gt;
&lt;LI&gt;If the client sends "page.asp?abc=x%79z", ASP will decode the value and Request.QueryString("abc") will also return "xyz".&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;But if you wanted the value to contain a percent, Request.QueryString requires the '%' sign to be encoded at %25.&amp;nbsp; If you do not encode the '%' sign, Request.QueryString will drop it from the returned value.&amp;nbsp; For example:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If the client sends "page.asp?abc=x%25yz", Request.QueryString("abc") will return "x%yz".&lt;/LI&gt;
&lt;LI&gt;If the client sends "page.asp?abc=x%yz", Request.QueryString("abc") will drop the unescaped '%' and return "xyz".&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;It is the final example above that is problematic.&amp;nbsp; If you have a filtering rule that is attempting to prevent "xyz" from reaching an ASP application, an attacker could try to get around the filter by sending it in a name value pair with an unescaped '%' in the value.&lt;/P&gt;
&lt;P&gt;It is possible for UrlScan 3.0 to block the problematic request above, but to do so it is necessary to block any instance of a '%' sign in the query string.&amp;nbsp; This would be effective, but it would also be subject to many false positives because it would also block '%' sign instances that are part of a valid escape sequence.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Enter UrlScan 3.1&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;It became clear pretty quickly that UrlScan needed a new tool to address this new attack in an efficient way.&amp;nbsp; To do that, we've added the ability to deny unescaped '%' signs in a request.&amp;nbsp; This new feature can be applied to unescaped '%' signs in the query string, in specific named headers, or anywhere in any header name or value.&lt;/P&gt;
&lt;P&gt;To block any requests attempting to use an unescaped '%' to get around the query string filter, you can add a single rule to the urlscan.ini file.&amp;nbsp; The following rule says that, for any ASP page, search the query string for an unescaped percent and, if found, block the request.&amp;nbsp; To activate the rule, be sure to add to the RuleList property in the [Options] section of urlscan.ini:&lt;/P&gt;
&lt;P&gt;[UnescapedPercentRule] &lt;BR&gt;AppliesTo=.asp &lt;BR&gt;DenyUnescapedPercent=1 &lt;BR&gt;ScanQueryString=1&lt;/P&gt;
&lt;P&gt;And while we were adding this new feature, we were able to make a couple other fixes in UrlScan.&amp;nbsp; The following changes have been made:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It was possible for certain escape sequences to get past filtering rules.&amp;nbsp; This has been fixed.&lt;/LI&gt;
&lt;LI&gt;Certain query string rules did not work properly on IIS 5.1.&amp;nbsp; This has been fixed.&lt;/LI&gt;
&lt;LI&gt;The behavior of the [AlwaysAllowedUrls] section has been changed.&amp;nbsp; In UrlScan 3.0, any URLs listed in that section were not subject to filtering of anything that applied specifically to the URL.&amp;nbsp; Effective with UrlScan 3.1, any URLs in that section are not subject to &lt;EM&gt;any&lt;/EM&gt; UrlScan rules.&amp;nbsp; This means that adding a URL to this section will prevent query string or other rules from blocking the URL.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The UrlScan team highly recommends that you update to UrlScan 3.1 today at one of the below links.&amp;nbsp; If you are using UrlScan 3.0 to apply SQL injection filtering to Classic ASP pages, this is particularly important, along with adding the above rule to block unescaped '%' signs.&lt;/P&gt;
&lt;P&gt;Also, any discussion of filtering for SQL injection or other injection attacks, it is important to remember that filtering is only a stopgap mitigation.&amp;nbsp; It is essential to fix the vulnerabilities in the underlying code.&amp;nbsp; Information on SQL injection vulnerabilities in applications can be found &lt;A href="http://msdn.microsoft.com/en-us/library/ms161953.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms161953.aspx"&gt;here&lt;/A&gt; and general information on security web applications can be found &lt;A href="http://msdn.microsoft.com/en-us/library/ms994921.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms994921.aspx"&gt;here.&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;UrlScan 3.1 can be downloaded from the following locations:&lt;/P&gt;
&lt;P&gt;For 32 bit: &lt;A href="http://www.iis.net/go/1697" mce_href="http://www.iis.net/go/1697"&gt;http://www.iis.net/go/1697&lt;/A&gt; &lt;BR&gt;For 64 bit: &lt;A href="http://www.iis.net/go/1698" mce_href="http://www.iis.net/go/1698"&gt;http://www.iis.net/go/1698&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;-Wade&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2717855" width="1" height="1"&gt;</description></item><item><title>UrlScan v3.0 Beta Release</title><link>http://blogs.iis.net/wadeh/archive/2008/06/24/urlscan-v3-0-beta-release.aspx</link><pubDate>Tue, 24 Jun 2008 19:50:33 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2444223</guid><dc:creator>wadeh</dc:creator><slash:comments>37</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=2444223</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2008/06/24/urlscan-v3-0-beta-release.aspx#comments</comments><description>&lt;p&gt;The IIS team has some street smarts when it comes to security. &lt;/p&gt;  &lt;p&gt;We learned quite a few lessons the hard way back in 2001 with the outbreak of the CodeRed worm.&amp;#160; One of the lesser known facts about the Code Red worm is that the vulnerability it exploited was not actually in IIS itself.&amp;#160; It was an application that ran on top of IIS.&amp;#160; Since that application was distributed with IIS and was installed by default, this distinction did not matter to our customers.&amp;#160; IIS and CodeRed became associated with each other. &lt;/p&gt;  &lt;p&gt;When we designed IIS 6, we took on the challenge of creating an environment to protect the server from vulnerabilities in applications we host.&amp;#160; Our steps to address this issue ranged from not installing any applications (or even IIS itself) by default on a server, to providing a low privileged environment to minimize damage should a vulnerability be found.&amp;#160; We also took a hard look at our engineering practices and changed the way we did things to minimize the chances for serious bugs in the IIS core code. &lt;/p&gt;  &lt;p&gt;Our application of these lessons has withstood the test of time, with IIS 6 being recognized as one of the most secure server products ever released.&amp;#160; We've applied the same principles to IIS 7 - and even extended them. &lt;/p&gt;  &lt;p&gt;But back in 2001, IIS 5 was the current version of the web server and we needed to address the issues without waiting for the next IIS release.&amp;#160; To do this, we released a set of tools with The IIS Lockdown Tool.&amp;#160; This package included tools to go over configuration settings across IIS and set them to secure values appropriate to the applications running on the web server.&amp;#160; It also included a runtime tool called UrlScan. &lt;/p&gt;  &lt;p&gt;UrlScan installs as a filter on IIS and looks at incoming requests in real time.&amp;#160; It can then screen requests based on a set of general request properties.&amp;#160; For example, it can block overly long URLs or headers.&amp;#160; It can block requests with unexpected HTTP verbs or strings in the URL. &lt;/p&gt;  &lt;p&gt;Because CodeRed depended on a long URL and requests to a particular component, UrlScan was able to stop it in its tracks.&amp;#160; While this was no substitute for an actual patch to the affected component, it did buy customers time and protected their servers until they could get patches installed.&amp;#160; Over time, UrlScan was so effective at its job that we built most of its features into IIS 7 in the form of the request filter module. &lt;/p&gt;  &lt;p&gt;Today, in 2008, we find ourselves in a similar situation.&amp;#160; We are seeing a particularly nasty &lt;a href="http://blogs.iis.net/bills/archive/2008/04/25/sql-injection-attacks-on-iis-web-servers.aspx"&gt;automated SQL Injection attack&lt;/a&gt; that is targeting our customers.&amp;#160; This attack defaces web servers and sends their clients off to malicious servers that attempt to install malware.&amp;#160; As before, the vulnerability does not exist in IIS - or any software from Microsoft.&amp;#160; In this case, the attack is exploiting vulnerabilities in customer developed applications.&amp;#160; And as before, the real fixes will need to come from the myriad developers of those applications. &lt;/p&gt;  &lt;p&gt;Unfortunately, neither UrlScan nor the IIS 7 request filter have been able to mitigate these attacks.&amp;#160; The reason for this is that the payload is delivered in the query string.&amp;#160; For historical and some obscure RFC reasons, UrlScan never looked at the query string.&amp;#160; And since the request filter is based on UrlScan, it has the same limitation. &lt;/p&gt;  &lt;p&gt;As an initial measure to help our customers, we have released some sample &lt;a href="http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx"&gt;ASP&lt;/a&gt; and &lt;a href="http://forums.asp.net/t/1254125.aspx"&gt;ASP.NET&lt;/a&gt; code that can be used with existing applications to filter out these attacks.&amp;#160; But both of these measures still require every affected page to be located and edited. &lt;/p&gt;  &lt;p&gt;As our next measure, we are today releasing a beta for a new version of UrlScan - version 3.0 - that can reach these requests and block them.&amp;#160; This release includes a GoLive license, so you can deploy it on your production servers.&amp;#160; UrlScan version 3 is compatible with the configuration files for the existing UrlScan version 2.5, so you if you are already running UrlScan, everything will still work as it did - except you'll have new options.&amp;#160; Also, since its been just over 5 years since UrlScan 2.5 shipped, we've taken the opportunity to add some frequently requested features.&amp;#160; The new set of features in version 3 are: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Support for query string scanning, including an option to scan an unescaped version of the query string.&lt;/li&gt;    &lt;li&gt;Change notification for configuration (no more restarts for most settings.)&lt;/li&gt;    &lt;li&gt;UrlScan can be installed as a site filter.&amp;#160; Different sites can have their own copy, with their own configuration.&lt;/li&gt;    &lt;li&gt;Escape sequences can be used in the configuration file to express CRLF, a semicolon (normally a comment delimiter) or unprintable characters in rules.&lt;/li&gt;    &lt;li&gt;Custom rules can be created to scan the URL, query string, a particular header, all headers or combination of these.&amp;#160; The rules can be applied based on the type of file requested. &lt;/li&gt;    &lt;li&gt;Support for 64 bit IIS worker processes.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;We also have plans to update the IIS 7 request filter to add these features.&amp;#160; In the interim, UrlScan 3 is fully supported on IIS 7. &lt;/p&gt;  &lt;p&gt;Please feel free to download the UrlScan version 3 beta for &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=EE41818F-3363-4E24-9940-321603531989&amp;amp;displaylang=en"&gt;32 bit&lt;/a&gt; or &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=361E5598-C1BD-46B8-B3E7-3980E8BDF0DE&amp;amp;displaylang=en"&gt;64 bit&lt;/a&gt; and discuss it in the &lt;a href="http://forums.iis.net/1031.aspx"&gt;Security Forum&lt;/a&gt; here on iis.net. &lt;/p&gt;  &lt;p&gt;Finally, it cannot be overstated that these tools are just an interim measure to buy time to fix the affected applications.&amp;#160; While they are effective against the current wave of automated attacks, they cannot protect against more directed attacks against a specific server.&amp;#160; The category of SQL Injection vulnerabilites is so broad that there are no known filter strategies that can block a determined hacker against application vulnerabilities.&amp;#160; There are many resources available for learning about SQL Injection attacks and prevention strategies.&amp;#160; One of the nicest collections of links I've seen has been published in MVP Harry Waldron on his blog &lt;a href="http://msmvps.com/blogs/harrywaldron/archive/2008/05/31/microsoft-best-practices-for-preventing-sql-injection-attacks.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2444223" width="1" height="1"&gt;</description></item><item><title>Understanding FastCGI Settings for IIS 5.1 &amp; 6</title><link>http://blogs.iis.net/wadeh/archive/2007/03/02/first-post-fastcgi-settings-for-iis-5-1-6.aspx</link><pubDate>Fri, 02 Mar 2007 05:02:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:1601800</guid><dc:creator>wadeh</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/wadeh/rsscomments.aspx?PostID=1601800</wfw:commentRss><comments>http://blogs.iis.net/wadeh/archive/2007/03/02/first-post-fastcgi-settings-for-iis-5-1-6.aspx#comments</comments><description>&lt;P&gt;So here it is, my first ever blog post.&lt;/P&gt;
&lt;P&gt;I am not new to posting about IIS on the internet.&amp;nbsp; A quick newsgroup search reminds me that I've posted to around 900 threads related to IIS.&amp;nbsp; The first time was on June 10, 1997, where I helped someone to get "server push" to work from a CGI on IIS.&lt;/P&gt;
&lt;P&gt;It strikes me as a bit ironic that my first usenet post for IIS was on CGI, and my first blog post for IIS will be on FastCGI.&amp;nbsp; In the interim 10 years, I've worked far more with ISAPI than CGI.&amp;nbsp; In fact, it's my expertise with ISAPI that's drawn me to doing FastCGI support for IIS 5.1 and 6.&lt;/P&gt;
&lt;P&gt;So what does ISAPI have to do with FastCGI?&amp;nbsp; To answer the question, let's start by looking at plain old CGI.&lt;/P&gt;
&lt;P&gt;CGI, which stands for "Common Gateway Interface" is a way for application developers to interact with a web server.&amp;nbsp;&amp;nbsp;And it is a very old specification.&amp;nbsp; Every version of IIS that has ever shipped has supported CGI.&amp;nbsp; It's a simple specification:&amp;nbsp; Basically, when a web server receives a request, it creates a new process to handle a request.&amp;nbsp; For the new process, the stdin handle is remapped so that it receives request entity from the client, the stdout handle is remapped so that it writes response data to the client, and the command line and environment variables are set to provide other server and request information to the CGI process.&amp;nbsp; There is some magic that happens in the response that allows the CGI to specify custom response status and headers, but there's not much more to it than that.&lt;/P&gt;
&lt;P&gt;The problem with CGI, from IIS's perspective, is that IIS is somewhat at a disadvantage to its competition in handling requests.&amp;nbsp; The issue is that every single request will result in a new process spinning up, doing work, and shutting down.&amp;nbsp; If you are on an operating system that has very light weight process creation, the performance is bound by the "doing work" part of the equation.&amp;nbsp; Unfortunately, if you are on an operating system where process creation is an expensive operation, the "doing work" part of the equation can be overwhelmed by the "process creation" part.&amp;nbsp; This is the reason that CGI flourishes on our main competition running on a Unix-based platform, but is not recommended on IIS.&lt;/P&gt;
&lt;P&gt;This is most definitely not to say that IIS has a performance disadvantage.&amp;nbsp; To the contrary, IIS is quite capable of keeping up with - and often surpassing - the performance of other web servers.&amp;nbsp; The reason for this is ISAPI.&lt;/P&gt;
&lt;P&gt;ISAPI, which stands for Internet Server Application Programming Interface, is completely internal to the web server process.&amp;nbsp; When a new request comes in for an ISAPI, no new process is created.&amp;nbsp; Instead, the web server calls an entry point in a dll that is loaded into the web server process.&amp;nbsp; If the ISAPI is written with an understanding of how the operating system threading model works, it can be blindingly fast.&lt;/P&gt;
&lt;P&gt;So what is FastCGI, and why do we need it?&amp;nbsp; Basically, we need FastCGI due to the existence of popular CGI-based development platforms, not the least of which is PHP.&lt;/P&gt;
&lt;P&gt;PHP has run on IIS for years, with both CGI and ISAPI implementations.&amp;nbsp; Unfortunately, both implementations are a compromise when running on IIS.&amp;nbsp; The CGI implementation is a compromise due to the performance characteristics of process creation on Windows.&amp;nbsp; So why is the ISAPI implementation a compromise?&amp;nbsp; Remember what I said above about "threading model"?&amp;nbsp; When PHP runs as an ISAPI, it runs inside the web server process in a highly multithreaded process.&amp;nbsp; As it turns out, the PHP implementation itself is thread safe - but lots of folks use extensions to PHP that may or may not be thread safe.&amp;nbsp; If you end up using a non-thread-safe extension to PHP with the ISAPI, the result is an unstable server.&amp;nbsp; For this reason, some people are able to run the ISAPI version of PHP, and some are not.&lt;/P&gt;
&lt;P&gt;FastCGI offers a compromise solution that can deliver both performance and stability.&amp;nbsp; To do this, FastCGI preserves almost all of the original CGI specification, including a non-multithreaded environment - but it allows the host CGI process to remain alive after the request finishes, so that it's ready to be reused for another request.&amp;nbsp; Since the process can be used over and over, the cost of process creation drops out of the equation.&amp;nbsp; The difference between a regular CGI and a FastCGI is that a FastCGI has a layer in the process that maps the FastCGI protocol into the stdin, stdout and such that CGI uses.&amp;nbsp; There are available libraries (from outside of Microsoft) that can be simply linked into existing CGI source code with very minor modifications.&lt;/P&gt;
&lt;P&gt;So what does my ISAPI background have to do with FastCGI?&lt;/P&gt;
&lt;P&gt;Well, for the IIS 7 version of the PHP handler, it has nothing to do with it.&amp;nbsp; In fact, the main parts of the FastCGI handler, and all of the IIS 7 module code were written by Rick James (who has written lots of FastCGI stuff in his blog, and is very active on the FastCGI forums.)&amp;nbsp; This is because IIS 7 has an all new, and very powerful API, that works well for hosting many different platforms.&lt;/P&gt;
&lt;P&gt;Earlier versions of IIS, on the other hand, don't have this rich new API.&amp;nbsp; Because of that, it's necessary that the FastCGI handler for these versions of IIS to run on top of ISAPI.&amp;nbsp; My day-to-day responsibilities don't give me much time to write code any more, so when I saw a need to port FastCGI to ISAPI, I jumped at the chance to keep the project for myself.&lt;/P&gt;
&lt;P&gt;With the history lesson over, let's talk a bit about what the FastCGI handler has to do in IIS, which will lead to understanding what all of the configuration options do.&lt;/P&gt;
&lt;P&gt;The FastCGI handler is broken into a few parts:&amp;nbsp; Applications, the Application Manager, and various code to support the FastCGI protocol.&lt;/P&gt;
&lt;P&gt;Because you probably want to be able to handle multiple, concurrent requests, it is necessary to have a pool of processes available and ready to handle a request.&amp;nbsp; In the FastCGI handler, this pool of processes is called an application (and since the term "application" is already so overused in the web world, I often just go ahead and use the term "process pool".)&amp;nbsp; There are a number of properties of a process pool that you might want to manage.&amp;nbsp; For example, you probably want to specify the number of processes in the pool, or the number of requests a process is allowed to accept before it's shut down and recycled, etc.&lt;/P&gt;
&lt;P&gt;The FastCGI handler can support multiple process pools.&amp;nbsp; The reason for this is that you may want to run more than one kind of FastCGI on one server - for example, both PHP and Ruby.&amp;nbsp; You may also have multiple sites on your server, and you may not want requests for those sites to share the same processes, especially if you want the site processes to run as different users.&amp;nbsp; The piece that handles multiple process pools is called the application manager.&lt;/P&gt;
&lt;P&gt;Finally, you need to wire the FastCGI handler into IIS, so that requests can be routed to it.&amp;nbsp; As it turns out, IIS 7 does this in a different way than IIS 5.1 and 6.&amp;nbsp; In this blog entry, I am only going to discuss IIS 5.1 and 6.&amp;nbsp; This is done with an IIS configuration setting called "script maps", which basically associates a file extension with the ISAPI that should handle it.&amp;nbsp; In addition, the script mapping has an optional setting that will only allow requests to be processed where the physical file associated with the request exists.&amp;nbsp; This is the default setting for security reasons (which may be another good blog topic), but there are times when you may want to allow a URL which has no physical file behind it.&amp;nbsp; The ISAPI extension that contains the FastCGI handler is called fcgiext.dll.&amp;nbsp; So if you want the FastCGI handler to accept PHP requests, you would set up a script mapping that associates ".php" with fcgiext.dll; for Ruby, you would map ".rb" to fcgiext.dll, etc.&amp;nbsp; In IIS 6 (but not 5.1), it is also possible to set up a "wildcard script map" where all requests can be routed to an ISAPI dll.&amp;nbsp; If you create a wildcard script map for fcgiext.dll, all requests would go to FastCGI, regardless of file extension.&lt;/P&gt;
&lt;P&gt;So now that we know how the FastCGI handler works, let's talk about the specific things that you can put in the fcgiext.ini file.&lt;/P&gt;
&lt;P&gt;There is one section in fcgiext.ini file that is required, no matter what FastCGI you are trying to run.&amp;nbsp; That is the types section.&amp;nbsp; The purpose of the types section is to associate a file extension with a specific process pool.&amp;nbsp; Note that this is different than the script mapping described above.&amp;nbsp; If you set up script mappings, for example, for both .php and .rb, the FastCGI handler needs to know how they are different from each other, and the types section does this work.&lt;/P&gt;
&lt;P&gt;To see what is possible, let me show the types section from the fcgiext.ini file on my test machine.&amp;nbsp; This is the actual file that I used while writing and testing the FastCGI ISAPI:&lt;/P&gt;
&lt;P&gt;[Types]&lt;BR&gt;echo=c:\echo\echo.exe&lt;BR&gt;php=c:\php\php-cgi.exe&lt;BR&gt;fooby=c:\echo\echo.exe&lt;BR&gt;php:123154536=PHP Site 2&lt;BR&gt;php:123154537=PHP Site 3&lt;BR&gt;*=Wildcard Mapping&lt;/P&gt;
&lt;P&gt;The format of the file is pretty simple at first glance.&amp;nbsp; It is basically "file-extension:process-pool".&amp;nbsp; You can tell from the first three entries in this ini file that I probably have script maps set up that associate ".echo", ".php" and ".fooby" with fcgiext.dll, and you can see each of those is associated with a FastCGI compliant exe file.&amp;nbsp; And in the first technical preview, this would have been it.&lt;/P&gt;
&lt;P&gt;The next three entries are demonstrate new capabilites that were added in the second technical preview.&amp;nbsp; There are two more ".php" associations, but they have some long number behind them, and they don't have exe files associated with them.&amp;nbsp; The numbers behind them are site instance IDs.&amp;nbsp; These numbers tell the FastCGI handler that the association should only apply to a specific site with that ID.&amp;nbsp; And, starting with the second technical preview, the process name is no longer associated with the file extension in the types section.&amp;nbsp; Now, the association is made between a file extension (which is optionally site specifc) and a section name that must appear later in the fcgiext.ini file.&amp;nbsp; The reason for the latter change is that we need to be able to support declaring arguments for the process, and since we might want different pools running the same process with different arguments (a likely scenario for Ruby), we can't depend on the process name to define all of the process pool settings.&amp;nbsp; For compatibility with the first technical preview, we will still use the section name as the exe path if it's not otherwise specified in&amp;nbsp;the section.&lt;/P&gt;
&lt;P&gt;Let's look at the section for the ".echo" association:&lt;/P&gt;
&lt;P&gt;[c:\echo\echo.exe]&lt;BR&gt;QueueLength=999&lt;BR&gt;MaxInstances=20&lt;BR&gt;InstanceMaxRequests=500&lt;/P&gt;
&lt;P&gt;This section was created during development of the first technical preview.&amp;nbsp; Since it doesn't have an ExePath setting, which is how the second tech preview declares the exe, the FastCGI handler will just use the section name for the path to the exe.&lt;/P&gt;
&lt;P&gt;Now, lets look at the section for PHP Site 2, which only applies to the site with 123154536 as its ID:&lt;/P&gt;
&lt;P&gt;[PHP Site 2]&lt;BR&gt;ExePath=c:\php\php-cgi.exe&lt;BR&gt;Arguments=site2&lt;BR&gt;QueueLength=1001&lt;BR&gt;MaxInstances=20&lt;BR&gt;IdleTimeout=200&lt;BR&gt;ActivityTimeout=20&lt;BR&gt;RequestTimeout=60&lt;BR&gt;InstanceMaxRequests=1000&lt;/P&gt;
&lt;P&gt;In this section, you can see that we are associating ".php" requests on that site with&amp;nbsp;c:\php\php-cgi.exe.&amp;nbsp; Also, you can see that we are passing "site2" as an argument to the process when we start it.&amp;nbsp; This is different from PHP Site 3, which looks like:&lt;/P&gt;
&lt;P&gt;[PHP Site 3]&lt;BR&gt;ExePath=c:\php\php-cgi.exe&lt;BR&gt;Arguments=site3&lt;BR&gt;QueueLength=1001&lt;BR&gt;MaxInstances=20&lt;BR&gt;IdleTimeout=400&lt;BR&gt;ActivityTimeout=40&lt;BR&gt;RequestTimeout=120&lt;BR&gt;InstanceMaxRequests=1000&lt;/P&gt;
&lt;P&gt;In this case, we are passing "site3" as the argument when we start c:\php\php-cgi.exe.&amp;nbsp; Note that the Arguments setting is optional, and you can pass multiple arguments using a space delimiter&amp;nbsp;just like you would on the console command line.&amp;nbsp; If you need spaces within the arguments, instead of as a delimiter, you should be able to use quotes - again, just line the command line.&lt;/P&gt;
&lt;P&gt;Before talking about the Wildcard Mapping, let's take this opportunity to look at the other settings that can be used in each process pool:&lt;/P&gt;
&lt;P&gt;ExePath - The path to the process to use in the pool&lt;/P&gt;
&lt;P&gt;Arguments - Arguments to pass to each process in the pool at start time.&amp;nbsp; This setting is optional&lt;/P&gt;
&lt;P&gt;QueueLength - What happens if you get more simultaneous requests than you have processes to handle them?&amp;nbsp; Why, we queue them, of course.&amp;nbsp; This setting controls the number of requests for the process pool that we will queue before they start failing.&amp;nbsp; The default value is 1000 requests.&lt;/P&gt;
&lt;P&gt;MaxInstances - This is the highest number of processes we will allow in the pool.&amp;nbsp; The default is 10.&amp;nbsp; Note that this number is a maximum.&amp;nbsp; We won't create the processes until we need them.&amp;nbsp; If you never have more than two concurrent requests, we will only start two processes.&lt;/P&gt;
&lt;P&gt;InstanceMaxRequests - This is the number of requests that we will send to a process in the pool before we shut it down and recycle it.&amp;nbsp; The default value is 1000.&lt;/P&gt;
&lt;P&gt;IdleTimeout - This is the number of seconds that a process can site idle, without working on a request, before we will shut it down.&amp;nbsp; The default is 300 seconds.&lt;/P&gt;
&lt;P&gt;ActivityTimeout - The is the number of seconds that the FastCGI handler will wait for I/O activity from a process before we terminate it.&amp;nbsp; The default is 30 seconds.&amp;nbsp; Note that, internally, we double that number on the first I/O from a newly started process.&amp;nbsp; This allows a process to take some extra time to start up without incurring the wrath of the timeout period.&lt;/P&gt;
&lt;P&gt;RequestTimeout - The is the maximum amount of time that we'll allow for a FastCGI process to handle a request before we terminate it.&amp;nbsp; The default is 90 seconds.&lt;/P&gt;
&lt;P&gt;Now let's take a look at that '*' association with Wildcard Mapping.&amp;nbsp; This is something that applies only to IIS 6.&amp;nbsp; IIS 6 allows a special kind of script map that applies to all requests.&amp;nbsp; If you set up fcgiext.dll as a "Wildcard Scriptmap", this assocation will catch any requests that don't have a more specific association.&amp;nbsp; For example, with the types section above, if you request a "/foo.bar", the ".bar" file extension doesn't have a specific association, so it will be caught by this '*' association and go to the process pool called "Wildcard Mapping".&amp;nbsp; Let's take a look at that section:&lt;/P&gt;
&lt;P&gt;[Wildcard Mapping]&lt;BR&gt;ExePath=c:\echo\echo.exe&lt;BR&gt;QueueLength=1000&lt;BR&gt;MaxInstances=20&lt;BR&gt;InstanceMaxRequests=100&lt;BR&gt;IgnoreExistingFiles=1&lt;BR&gt;;IgnoreDirectories=1&lt;/P&gt;
&lt;P&gt;Most of it looks just like the other process pool sections, but it has two new settings that are only used for&amp;nbsp;wildcard script&amp;nbsp;maps (and thus, only IIS 6): IgnoreExistingFiles and IgnoreDirectories.&amp;nbsp; Remember way back in my discussion above about script mappings where I said that you might want to handle requests that don't map to a script file?&amp;nbsp; If you do this, it would be very convenient if you could have the FastCGI handler handle these non-file requests, but still get IIS to handle other files in the directory normally - and that's exactly what these two settings provide:&lt;/P&gt;
&lt;P&gt;IgnoreExistingFiles - If this is set to 1, the FastCGI handler will check to see if the requested URL exists as a file.&amp;nbsp; If so, the FastCGI handler will defer processing of the URL so that it will be processed without FastCGI.&amp;nbsp; The default value is 0.&lt;/P&gt;
&lt;P&gt;IgnoreDirectories - If this is set to 1, the FastCGI handler will check to see if the requested URL exists as a directory.&amp;nbsp; If so, the FastCGI handler will defer processing of the URL so that it will be processed without FastCGI.&amp;nbsp; This effectively allows default documents and directory listings to be served.&amp;nbsp; The default value is 0.&lt;/P&gt;
&lt;P&gt;It is possible to set a site-specific wildcard mapping using the same site ID syntax that file extensions use (ie. "*:12345678=Section Name".&amp;nbsp; The search order for file extensions is significant.&amp;nbsp; When a request reaches the FastCGI handler, the associations in the types section are checked in the following order:&lt;/P&gt;
&lt;P&gt;- A specific file extension association&amp;nbsp;specific to the&amp;nbsp;site ID&lt;/P&gt;
&lt;P&gt;- A '*' association specific to the site ID&lt;/P&gt;
&lt;P&gt;- A specific file extension association with no side ID specified&lt;/P&gt;
&lt;P&gt;- A '*' association with no site ID specified&lt;/P&gt;
&lt;P&gt;There is one other process pool setting that is pretty esoteric:&lt;/P&gt;
&lt;P&gt;FlushNamedPipe - There are some cases where a FastCGI might not read all of the data from the named pipe that communicates with the web server.&amp;nbsp; If this happens, the web server will wait for a read that isn't coming, effectively deadlocking that member of the process pool.&amp;nbsp; This most often happens in the case where the FastCGI process exits when we don't expect, due to&amp;nbsp;its having an internal notion of the max number of&amp;nbsp;request is will handle that is lower than our&amp;nbsp;InstanceMaxRequests setting.&amp;nbsp; Setting FlushNamedPipe=1 causes FastCGI to flush data that might lead to this condition.&amp;nbsp; The default is 0.&lt;/P&gt;
&lt;P&gt;----------&lt;/P&gt;
&lt;P&gt;So that is my first blog entry - whew!&amp;nbsp; It turned out to be a whole lot longer than I expected, but I wanted to be thorough about how the FastCGI handler works on IIS 6 and how it is affected by each of the available configuration options.&lt;/P&gt;
&lt;P&gt;If you have specific feedback about the content of the material or the presentation style, I would love to hear it.&amp;nbsp; I promise that they won't all be this long...&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=1601800" width="1" height="1"&gt;</description><category domain="http://blogs.iis.net/wadeh/archive/tags/IIS+News+Item/default.aspx">IIS News Item</category></item></channel></rss>