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: https://www.owasp.org/index.php/Top_10_2010-A10-Unvalidated_Redirects_and_Forwards
# The data group format is string. v11 example:
#
#ltm data-group internal my_domain_whitelist_dg {
# records {
# example.com { }
# example.net { }
# example.org { }
# example.co.uk { }
# partner.com { }
# }
# type string
#}
when RULE_INIT {
# Name of the string data group which contains the whitelisted domains
# (ex: legal.com, legal.net, okay.org, 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
}
when HTTP_RESPONSE {
# 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 "http://www.example.com/redirect_blocked.html"
}
}
}
}
}Published Mar 18, 2015
Version 1.0hoolio
Cirrostratus
VP of Solutions at WorldTech IThoolio
Cirrostratus
VP of Solutions at WorldTech ITNo CommentsBe the first to comment
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)