Category Archives: IIS

Achieving an A+ grading at Qualys SSL Labs (Forward Secrecy in IIS)

At FundApps we love the SSL Labs tool from Qualys for checking best practice on our SSL implementations. They recently announced a bunch of changes introducing stricter security requirements for 2014, and a new A+ grade – so I was curious what it would take to achieve the new A+ grading. There are a few things required to now achieve A grading and then beyond:

  • TLS 1.2 required
  • Keys must be 2048 bits and above
  • Secure renegotiation
  • No RC4 on TLS 1.1 and 1.2 (RC4 has stuck around longer than it would be liked in order to mitigate the BEAST attack)
  • Forward secrecy for all browers that support it
  • HTTP Strict Transport Security with a long max age (Qualsys haven’t defined exactly what this is, but we use a 1 year value).

We’re using IIS so the focus of this entry is how to achieve an A+ grading in IIS 7/8.

Forward Secrecy & Best Practice Ciphers

Attention to Forward Secrecy has been increasing in recent time – the key benefit being if, say, the NSA obtain your keys in the future, this will not compromise previous communications that were encrypted using session keys derived from your long term key.

To set up support for Forward Secrecy, the easiest approach (in a Windows/IIS world) is to download the latest version of the IIS Crypto tool. This makes it really easy to get your SSL Ciphers in the right order and the correct ones enabled rather than messing directly with the registry.

Once downloaded, if you click the ‘Best Practice’ option, this will enable ECHDE as the preferred cipher (required for forward secrecy). The tool does also keep SSL 3.0, RC4 and 3DES enabled in order to support IE 6 on Windows XP. If you don’t require this, you can safely disable SSL 3.0, TLS_RSA_WITH_RC4_128_SHA and TLS_RSA_WITH_3DES_EDE_CBC_SHA in the cipher list. We also disable MD5.

HTTP Strict Transport Security

The other part of the equation is enabling a HTTP Strict Transport header. The idea with this is to stop man-in-the-middle attacks whereby they transparently convert a secure HTTPS connection to a plain HTTP connection. Visitors can see the connection is insecure, but there is no way of knowing that the connection *should* have been secure. By adding a HTTP Strict Transport header (which is remembered by the browser and stored for a specified period), then provided first communication with the server is not tampered with (by stripping out the header), the browser will prevent non-secure communication from then on.

Doing this is simple – but you need to ensure that you only return a Strict-Transport-Security header on a HTTPS connection. Any requests on HTTP should *not* have this header, and should be 301 redirect-ing to the HTTPS version. especially if your website only responds to HTTPS requests in the first place (we use a seperate website to redirect from non-HTTPS requests).

In our case, we have a seperate website already responsible for the non-HTTP redirection, so it was simply a case of adding the following in our system.webServer section of the web.config

<system.webServer>
  <httpProtocol>
    <customHeaders>
       <add name="Strict-Transport-Security" value="max-age=31536000" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

If you have to deal with both HTTPS and non-HTTPS, then implementation section on WikiPedia gives an example of how.

The end result? An A+ grading from the SSL Labs tool.

Migrating old websites & Rewrite maps in IIS 7

If you’re migrating to a new website and need to map old IDs to new IDs, I’ve just discovered that the UrlRewrite plugin in IIS has a great feature I hadn’t come across before called rewriteMaps. This means instead of writing a whole bunch of indentical looking rewrite rules, you can write one – and then simply list the ID mappings.

The syntax of the RegEx takes a bit of getting used to, but in our case we needed to map

/(various|folder|names|here)/display.asp?id=[ID]

to a new website url that looked like this:

/show/[NewId]

You can define a rewriteMap very simply – most examples I saw included full URLs here, but we just used the ID maps directly:

<rewriteMaps>
  <rewriteMap name="Articles">
    <add key="389" value="84288" />
    <add key="525" value="114571" />
    <add key="526" value="114572" />
  </rewriteMap>
</rewriteMaps>

You can reference a rewriteMap using {MapName:{SomeCapturedValue}}, so if SomeCapturedValue equalled 525 then you’d get back 114571 in the list above.

Because we’re looking to match a querystring based id, and you can’t match queryString parameters in the primary match clause, we needed to add a condition, and then match on that captured condition value instead, using an expression like this:

http://www.newdomain.com/show/{Articles:{C:1}}/

The final rule XML follows:

<rule name="Redirect rule for Articles" stopProcessing="true">
  <match url="(articles|java|dotnet|xml|databases|training|news)/display\.asp" />
  <conditions>
    <add input="{QUERY_STRING}" pattern="id=([0-9]+)" />
  </conditions>
  <action type="Redirect" url="http://www.developerfusion.com/show/{Articles:{C:1}}/" appendQueryString="false" />
</rule>

Detecting 404 errors after a new site design

We recently re-designed Developer Fusion and as part of that we needed to ensure that any external links were not broken in the process. In order to monitor this, we used the awesome LogParser tool. All you need to do is open up a command prompt, navigate to the directory with your web site’s log files in, and run a query like this:

"c:\program files (x86)\log parser 2.2\logparser" "SELECT top 500 cs-uri-stem,COUNT(*) as Computed FROM u_ex*.log WHERE sc-status=404 GROUP BY cs-uri-stem order by COUNT(*) as Computed desc" -rtp:-1 > topMissingUrls.txt

And you’ve got a text file with the top 500 requested URLs that are returning 404. Simple!