Tightening the Security of HTTP Traffic Part 2

This is the second part of this article which provides guidelines for tightening the security of http traffic by leveraging the power of F5 Big-IP and  iRules to include the latest HTTP security headers to all HTTP responses.

You can access the first and last part of the article through following links.

Tightening the Security of HTTP Traffic part 1

Tightening the Security of HTTP Traffic Part 3

4. The X-Frame-Options Header

The X-Frame-Options header protects web applications against Clickjacking. It Instructs browsers on how to display frame or iFrame (an HTML document within another HTML document).

Possible X-Frame-Option values are:

  • DENY: Do not render data within iframes (Facebook)
  • SAMEORIGIN: Only render data in iframes from same origin (Google)
  • ALLOW-FROM: <DOMAIN>: Only render data in iframes from the specified domain

4.1 - About ClickJacking:

  • Attacker tricks a non suspecting user to click a button, a link or an area of the document that they did not intent to click. 
  • Generally achieved with combination of transparent or opaque iframes, CSS and text boxes.
  • Relatively common attack

4.2 iRule to add The X-Frame-Options Header

when HTTP_RESPONSE { 

    if { !([ HTTP::header exists "X-Frame-Options“ ])} { HTTP::header insert "X-Frame-Options" "SAMEORIGIN" }

}
  • This iRule adds the X-Frame-Options : SAMEORIGIN to the header of all http response
  • The browser will only display iframes from the same origin on a given web page.

4.3 Example outcome:

 curl -L -A "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" -sD - https://www.google.com -o /dev/null

HTTP/2 200
date: Wed, 23 Aug 2017 11:08:10 GMT
[...]
server: gws
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
set-cookie: NID=110=YPSLhC7E2B6nUZAfW-3iM-KI4alGqmWhNJYax5GYfeaMsxYL6V_LeppmuPbNsImCehXBB0

[...]

5. HTTP Strict Transport Security - HSTS

The HSTS header Instructs web browsers to only use HTTPS protocol when communicating with the application. This Protects web applications against protocol downgrade and cookie hijacking attacks.  A common example of the benefit of HSTS is when legacy and sometime recent applications contain hard codded http links, and those links transmits cookies or other sensitive information within http connections while the application is intended to use https. With HSTS enable, those links will be broken and the application protected (The application will fail securely).

Using HSTS in conjunction with the secure flag for cookies will provide stronger security and avoid broken links that may result in following an http link without supplying cookies.

HSTS is communicated to clients using "Strict-Transport-Security“  header. It is defined by IETF in RFC 6797.

5.1 Example:

curl -L -A "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" -s -D - https://www.f5.com -o /dev/null

HTTP/1.1 200 OK
Set-Cookie: dnn_IsMobile=False; path=/; HttpOnly
Connection: close
Content-Length: 83328
Set-Cookie: BIGipServer=!M+eTuU0mHEu4R8mBiet1HZsOy/41nDC5VnWBAlE5bvU0446qCYN4w/jKbf2+U8d8EVe+BxHFZ5+UJYg=; path=/; Httponly; Secure
Strict-Transport-Security: max-age=16070400
[..]

5.2 iRule to enable HSTS for all HTTP responses

when HTTP_RESPONSE {

          if { !([ HTTP::header exists "Strict-Transport-Security“ ])} { HTTP::header insert "Strict-Transport-Security" "max-age=16070400" }

}

The above iRule adds HSTS to all HTTP responses with a timeout of 16070400 seconds, which instructs browsers to only use HTTPS when accessing this site for the next 6 month (16070400 seconds)

6. X-Content-Type-Options

The X-Content-Type-Options is a security header that helps reduce risks to MIME type attacks. It Instructs the browser to only load content when the type matches the type specified in the Content-Type header. For instance, if  "X-Content-Type-Options: nosniff“ header is send by the web application, compatible  browsers, will not load a CSS file, unless the Content-Type matches “text/css”. this header has Only one valid value: nosniff

Equally browsers will not load scripts unless the MIME type matches “text/javascript”, “application/javascript”,   “text/vbscript”…etc.

6.1 Example:

curl -L -A "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" -s -D - https://www.facebook.com  -o /dev/null

HTTP/1.1 200 OK
X-XSS-Protection: 0
X-Content-Type-Options: nosniff
public-key-pins-report-only: max-age=500; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E="; pin-[...]
Pragma: no-cache
Cache-Control: private, no-cache, no-store, must-revalidate
Content-Type: text/html
[…]

  6.2 iRule to insert X-Content-Type-Options to all http responses

The following iRule will insert X-Content-Type-Options : nosniff to all http responses

when HTTP_RESPONSE {
            if { !([ HTTP::header exists "X-Content-Type-Options“ ])} { HTTP::header insert "X-Content-Type-Options" "'nosniff'" } 

}

 

7. Content-Security-Policy – CSP

  • The content-security-policy header explicitly specify the origin of any content the web browser is allowed to load.
  •  CSP is a defense-in-depth technique to prevent XSS and clickjacking attacks.
  • The content covered by CSP include JavaScript, CSS, HTML frames, web workers, fonts, images, ActiveX… etc.
  • CSP uses directives to indicate the source of different type of content such as script-src, style-src, img-src, font-src, …etc
  • A list of CSP directives and their usage can be found here: https://content-security-policy.com/

Details on which  Browsers and versions support CSP can be found here: http://caniuse.com/#feat=contentsecuritypolicy
Some Browsers may not support the latest iteration (Or version) of CSP requirements and features. See http://caniuse.com/#feat=contentsecuritypolicy2

7.1 CSP: iRule

The following iRule can be used to insert CSP header to HTTP responses.

when HTTP_RESPONSE {

      if { !([ HTTP::header exists "content-security-policy “ ])} { HTTP::header insert "content-security-policy" “<options and value>" } }

<options and values> should be carefully reviewed, and tested as  providing wrong values would lead to legitimate requests being rejected

7.2 Example:

curl -L -A "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" -s -D - https://www.twitter.com -o /dev/null

HTTP/1.1 200 OK
cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
content-length: 325649
content-security-policy: script-src https://connect.facebook.net https://cm.g.doubleclick.net https://ssl.google-analytics.com https://graph.facebook.com https://twitter.com 'unsafe-eval' https://www.facebook.com https://ton.twitter.com https://*.fbcdn.net https://syndication.twitter.com https://media.riffsy.com https://www.google.com https://stats.g.doubleclick.net https://api.mapbox.com https://www.google-analytics.com blob: 'self'; report-uri https://twitter.com/i/csp_report?a=NVQWGYLXFVZXO2LGOQ%3D%3D%3D%3D%3D%3D&ro=false;
content-type: text/html;charset=utf-8
[...]

8. HTTP Public Key Pinning (HPKP)

HPKP is a security mechanism that helps prevent web origin impersonation where attackers could forge CA certificates. It Provides a list of public key hashes for the site certificates. Browser that support HPKP will cache the hashes when the user first visits the site, and verify the match on subsequent visits of the site by the same browser.
HPKP uses the Trust On first Use (TOFU) Mechanism. The HTTP header for HPKP is “Public-Key-Pins” or “Public-Key-Pins-Report-Only”.

Public-Key-Pins-Report-Only:

  • Used to test HPKP
  • Errors are reported, the site is not blocked
  • A report URI must also be provided.

Public-Key-Pins:

  • This indicates full HPKP support
  • Browser blocks the site on failed validation.

8.1 HPKP: iRule

The following iRule can be used to insert HPKP header to HTTP responses

when HTTP_RESPONSE {

            if { !([ HTTP::header exists "Public-Key-Pins-Report-Only “ ])} { HTTP::header insert "Public-Key-Pins-Report-Only" “<options and value>" }

}

<options and values> should be carefully reviewed, and tested as  providing wrong values would lead to legitimate requests being rejected

8.2 Example:

curl -L -A "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" -s -D - https://www.facebook.com -o /dev/null

HTTP/2 200
x-xss-protection: 0
public-key-pins-report-only: max-age=500; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E="; pin-sha256="q4PO2G2cbkZhZ82+JgmRUyGMoAeozA+BSXVXQWB8XWQ="; report-uri="http://reports.fb.com/hpkp/"
pragma: no-cache
content-security-policy: default-src * data: blob:;script-src *.facebook.com *.fbcdn.net *.facebook.net
[...]
cache-control: private, no-cache, no-store, must-revalidate
x-frame-options: DENY
...]

9. Single iRule to tighten the web app

The following iRule will enhance the security of your web application by inserting most of the headers discussed earlier in all HTTP responses sent to web clients.

when HTTP_RESPONSE {

       foreach mycookie [HTTP::cookie names] {

                                HTTP::cookie secure $mycookie enable

                                HTTP::cookie httponly $mycookie enable
                }

    if { !([ HTTP::header exists "X-Frame-Options“ ])} { HTTP::header insert "X-Frame-Options" "SAMEORIGIN" }
    if { !([ HTTP::header exists "X-XSS-Protection“ ])} { HTTP::header insert "X-XSS-Protection" "1; mode=block" }
    if { !([ HTTP::header exists "X-Content-Type-Options“ ])} { HTTP::header insert "X-Content-Type-Options" "'nosniff'" } 
   if { !([ HTTP::header exists "Strict-Transport-Security“ ])} { HTTP::header insert "Strict-Transport-Security" "16070400" } 

}

 

  • HPKP and CSP should be added with individual iRules given their potential risk and complexity.
  • They require careful review before adding to http responses.
  • CSP and HPKP should be used as defense in depth options, not as first line of defense.

 

Published Aug 28, 2017
Version 1.0
  • I highly recommend that, if possible, when you are doing header insertion to all responses, utilize LTM policies with an 'All' match strategy. I'm currently revising my iRules to migrate over some simple functionality (Add headers, remove cookies, etc) into policies for increased performance.

     

  • Is the

    "X-Content-Type-Options" "'nosniff'"
    header supposed to have single quotes inside of the double quotes? Or is
    "X-Content-Type-Options" "nosniff"
    correct?

  • I believe it is just "nosniff" without the single quotes - having the nested quotes would actually add the single quotes to the header I believe. Pascal would have to edit the article to correct that.

     

  • Policies generally faster the iRule so the policies are recommended wherever you can achieve same task with policy rather than a iRule.