Freigeben über


Delete inbound cookies in IIS using URL Rewrite

I have recently come across a few issues where some web apps were having a bad time due to some "evil" cookies in the HTTP request headers.

Although web applications would normally expect to receive back the cookies they previously set, they don't really control what user agents include in the HTTP headers. Not to mention cases where proxies, load balancers or layer-7-devices may tamper with the original request and inject custom headers. To make it even worse, applications may be deployed in web farms and end up sharing the same hostname with many others. If any of those doesn't limit the cookie scope to its own path, user agents will just send the same cookies to all the sub applications in the domain.

These conditions, and many others more, are a clear indication that a robust web application must make no assumptions around the HTTP cookies it receives. Indeed, it should be able to cope with any kind of junk they might carry.

That said, it may well be that you find yourself very suspicious about a specific cookie received by one of your apps. Unfortunately, instrumenting a code change just to validate your hypothesis is quite inconvenient. Similarly, it may be very challenging to find where that one cookie is coming from. Moreover, given your suppositions turns out to be right, it can take time to implement an application fix and have it deployed, which leaves the problem exposed without any workaround.

Whether you would like a quick way to validate your hypothesis, a temporary workaround to wait for the application to be updated or simply a way to remove some specific content from the request headers, this trick might come in handy.

 

Before we get started, you would need to install ARR and the URL Rewrite module in IIS. For the latest binaries, please refer to these pages:
https://www.iis.net/downloads/microsoft/application-request-routing https://www.iis.net/downloads/microsoft/url-rewrite

 

Once ARR and URL Rewrite are setup, let's create an empty rewrite rule. What we need to do is:

  • filter every request, unless you want it to be limited to a specific path
  • look for a pattern of your choice in the "Cookies" header
  • if found, replace the whole header with something else. Namely, all the existing cookies except the one to remove
  • take no action on the request routing itself, meaning that no specific routing actions or URL changes will take place, unless you want to

The XML that produces this behavior looks like this:

 <rule name="remove cookie" enabled="true">
<match url=".*" />
<conditions>
<add input="{HTTP_COOKIE}" pattern="^(.*)(EvilCookie=.*?[;\s$]+)(.*)$" />
</conditions>
<serverVariables>
<set name="HTTP_COOKIE" value="{C:1}{C:3}" />
</serverVariables>
<action type="None" />
</rule>

The same result can be obtained using the GUI URL Rewrite exposes in the IIS manager.

More in detail:

  • Select the website in IIS manager and then the URL Rewrite feature
  • In the actions panel click on Add Rule(s) and then select a Blank rule among the inbound list. Confirm with OK
  • Give the new rule a name and make it run for all the inbound traffic to the website.
    • If you're using regular expressions select " .* " as pattern.
    • If you prefer the wildcard match use just " * "
      In this example we are going to use the regex pattern
  • Now expand the Conditions panel and add a new one
  • Populate the window with the following values
    • Condition input: {HTTP_COOKIE}
      This means the condition we are working on is the server variable named HTTP_COOKIE. I believe you guessed what that is, right?
    • Check if input string: Matches the Pattern
    • Pattern: ^(.*)(EvilCookie=.*?[;\s$]+)(.*)$
    • This is actually the interesting piece. This string needs to match 3 parts of the original Cookies header.
      • The cookie to remove itself, including separators: (EvilCookie=.*?[;\s$]+)

      • The trailing cookies after the one to remove, if any: (.*)$

      • The leading cookies before the one to remove, if any: ^(.*)

        Note that some of the fancy characters in the string are regex patterns to make sure we look like cool kids and handle in just one line the following conditions: 

      • the cookie to remove is the first in the list

      • it is in a middle position

      • it is the last one in the list
        If that looks too awkward or scary, you can split each case into a separate condition and ensure to have the logical grouping set to match any (logical OR).

  • Expand the Server Variables panel and Add a new one
  • Pick HTTP_COOKIE as variable name and {C:1}{C:3} as the value name. Do not forget to check "Replace the existing value"
    Here's the actual hack! URL Rewrite uses some placeholders that reference both the URL match ({R:x} syntax) or a condition match ({C:x} syntax).
    This means you can build all sorts of fancy strings based on a combination of the request URL and headers conditions!
    In this very case, the syntax {C:1}{C:3} tells URL Rewrite to replace the Cookies header with the first and last match from the conditions. Which in other words means, strip out the evil cookie from the header!
    Note that {C:0} and {R:0} exist only if there is a pattern match and they are used as references to the whole input string we are testing our pattern against.
  • To finish off, scroll down to the Action panel and set the Action type to None, meaning we are not going to change the request routing.
    Do not stop the processing of other rules as you may want to add more one day.
  • Click on Apply in the top right corner to save the rule which will be immediately active.

 

Now that we have our rule in place, let's give it a try.

To demonstrate the effectiveness of the hack, I'm going to browse to a simple ASP.NET page that lists all the cookies in the request header. You can find the source code for the page attached to this post. I'm also using Fiddler to customize my request header, in order to easily control the cookies I'm passing to IIS.

First off, let's make sure the page works. Let's disable our URL Rewrite rule in IIS and start fiddling!

GET https://be1i.albigi.lab/echocookies.aspx HTTP/1.1
Cookie: Good=IAmAValidCookie; Bad=IAmANotSoBadCookie; EvilCookie=bXVoYWhhaGFoYQ==; Ugly=LeaveMeAloneIAmJustUgly;
Host: be1i.albigi.lab

The EvilCookie is there, as expected. Our poor app is in danger!

 

Now, let's enable the rule in the URL Rewrite and touch wood. Time to take another ride!

GET https://be1i.albigi.lab/echocookies.aspx HTTP/1.1
Cookie: Good=IAmAValidCookie; Bad=IAmANotSoBadCookie; EvilCookie=bXVoYWhhaGFoYQ==; Ugly=LeaveMeAloneIAmJustUgly;
Host: be1i.albigi.lab

Urray!! No EvilCookie this time!!

 

One last consideration to make is about where, in the IIS configuration, we may want to setup this hack.

This is a general question that applies to any URL Rewrite rule we may want to add. Two things we'd better consider are:

      1. If we setup the rule at the site level, it will run when IIS has already mapped the request to a specific site. This means the inbound URL path to match is going to be the relative path of the application, given the domain name can no longer be changed at this stage.

        This configuration is equivalent to setting up the XML in the application web.config file and it applies the rule for an individual site only.

      2. If we setup the rule at the web server level, instead, we can still change the domain name in the URL. This is the case, for instance, if we need to route the request to a different server (ARR Routing to server farms) or if we want the rule to apply for all the websites. This configuration is equivalent to setting up the XML in the applicationHost.config file that stores the whole web server configuration.

 

I hope you'll find this one helpful!

 

Alessandro Bigi (albigi)

 

Download: echoCookies.aspx

Comments

  • Anonymous
    August 24, 2017
    "remove some specific content from the request headers, this trick might come in handy" - True"This configuration is equivalent to setting up the XML in the applicationHost.config file that stores the whole web server configuration" - My best strategyThanks!
  • Anonymous
    September 23, 2017
    What's up, everything is going sound here and ofcourse every one is sharing information, that's in fact excellent, keep up writing.
    • Anonymous
      October 02, 2017
      Hello Depilacja,Thank you for your encouragement. Will try and keep posting interesting stuff on ASP.net and IIS. Stay tuned.Paul