Redirect Location header validator

Problem this snippet solves:

This iRule demonstrates how to validate the 30x redirects a web application sends back to clients. It intercepts any redirects which are to a domain that is not in a whitelist string data group. The goal is to protect clients from a web application which does not provide complete validation of user-input when generating HTTP redirects. See the OWASP Top Ten page for details on this class of vulnerability:

OWASP Top Ten Unvalidated Redirects and Forwards

Code :

# Validate the 30x redirects the web application sends to clients against a whitelist stored in a data group
# The goal is to prevent the client from being tricked into receiving an unvalidated redirect to a malicious third party site
# by an attacker.  See the OWASP Top Ten for details on the vulnerability: 

# The data group format is string.  v11 example:
#ltm data-group internal my_domain_whitelist_dg {
#    records {
# { }
# { }
# { }
# { }
# { }
#    }
#    type string

when RULE_INIT {
   # Name of the string data group which contains the whitelisted domains
   # (ex:,,, etc)
   set static::domain_whitelist_dg "my_domain_whitelist_dg"

   # Log debug to /var/log/ltm? 1=yes, 0=no.
   set static::redirect_debug 1

   # Check if domain is a redirect
   if {[HTTP::is_redirect]}{

      if {$static::redirect_debug}{
         log local0. "[IP::client_addr]:[TCP::client_port]: status=[HTTP::status], Location=[HTTP::header Location], Server=[LB::server]"
      # Check if the redirect location is an absolute URL
      switch -glob [HTTP::header Location] {
         "/*" -
         "" {
            # No Location header value or a local reference so do not check against whitelist
            if {$static::redirect_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Location local or empty. Not validating"}
         default {
            # Check Location value against the data group
            set hostname [string tolower [URI::host [HTTP::header Location]]]
            if {$static::redirect_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Checking $hostname against $static::domain_whitelist_dg"}

            # Check the hostname against the whitelist
            if {[class match $hostname ends_with $static::domain_whitelist_dg]}{
               if {$static::redirect_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Legal redirect to [HTTP::header location]"}
            } else {
               if {$static::redirect_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Illegal redirect to [HTTP::header location]"}
               HTTP::respond 302 Location ""
Published Mar 18, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment