iRule Security 101 - #1 - HTTP Version

When looking at securing up your web application, there are a set of fairly standard attack patterns that application firewalls make use of to protect against those bad guys out there who are trying exploit your website.  A good reference for web application attacks is the Open Web Application Security Project (OWASP). In this series of blog posts, I'm going to highlight different attacks and how they can be defended against by using iRules.

In the first installment of this series I will show how to only allow valid HTTP requests to your application server.  The most common HTTP versions out there are 1.0 and 1.1 although version 0.9 is still used in places.  A common attempt to fool an application is by passing an invalid HTTP Version causing the server to not interpret the request correctly.  The "HTTP version" iRules command contains the request version and you can ensure that only valid requests are processed and allowed to your app servers with this iRule:

 

when RULE_INIT {
    set INFO 0
    set DEBUG 0
    #------------------------------------------------------------------------  
    # HTTP Version  
    #------------------------------------------------------------------------  
    set sec_http_version_enabled 0  
    set sec_http_version_block 1  
    set sec_http_version_alert 1  
    set sec_http_versions [list \  "0.9" \  "1.0" \  "1.1" \  ]
}
when HTTP_REQUEST {  
    #============================================================================  
    # HTTP Version  
    #============================================================================  
    if { $::INFO } { 
        log local0. "ASSERTION: http_version" 
    }  
    if { $::sec_http_version_enabled } {    
        if { $::DEBUG } { 
            log local0. "  HTTP Version: [HTTP::version]"
        }    
        if { ! [matchclass [HTTP::version] equals $::sec_http_versions ] } {      
            if { $::sec_http_version_alert } { 
                log local0. "  SEC-ALERT: Invalid HTTP Version found: '[HTTP::version]'" 
            }
            if { $::sec_http_version_block } { 
                reject 
            }
        } else {
            if { $::DEBUG } {
                log local0. "  PASSED" 
            }
        }
    }
}

 

In the RULE_INIT method I've created a few global variables enabling one to turn on or off the verification.  Without all the extra conditionals, the iRule can be stripped down to the following couple of lines:

 

when RULE_INIT {
    set sec_http_versions [list "0.9" "1.0" "1.1" ]
}
when HTTP_REQUEST {
    if { ! [matchclass [HTTP::version] equals $::sec_http_versions ] } {
        reject
    }
}

 

Stay tuned for the next installment of iRules Security 101 where I'll show how to validate HTTP methods.

-Joe

Updated Mar 18, 2022
Version 4.0
  • The Syndication (RSS) link is in the upper right corner. You could be able to cut and paste this link into feedburner.
  • Jon_N's avatar
    Jon_N
    Icon for Nimbostratus rankNimbostratus
    Should be noted for anyone that is looking to implement this that the way global vars has changed and any of the INIT statements should be something like: set static::sec_http_version_enabled 1 set static::sec_http_version_alert 1 set static::sec_http_version_alert_syslog 1 set static::sec_http_versions [list \ "0.9" \ "1.0" \ "1.1" \ ] For newer F5 OS versions (ran into this error recently)