OptionsBleed mitigation example

Problem this snippet solves:

Mitigate exploitation of the OptionsBleed attack by blocking memory leaked through the Allow response header.

How to use this snippet:

OptionsBleed is a disclosed attack against Apache HTTP servers. It is similar to HeartBleed as server memory is leaked, however it's less prevalent. While the configuration leading to this vulnerability is fairly rare, you may want to protect against data leaking out of your server.

The original disclosure is here: https://blog.fuzzing-project.org/60-Optionsbleed-HTTP-OPTIONS-method-can-leak-Apaches-server-memory.html

As far as I can tell, there's no ASM signature that prevents this, and it's not possible to use ASM to sanitise outgoing Allow headers. In addition, it doesn't appear to be possible to use a Custom Signature to detect this, as custom signatures can't match on headercontent for responses (only requests).

The iRule example below reads all the Allow headers in every response from your website, and only adds them back if they contain "safe" HTTP verbs such as GET, POST and OPTIONS. If there's unsafe text in the Allow header, then this iRule drops that header from the response.

You can customise the regular expression to include more or less verbs depending on what your site uses.

Note that there's no logging or alerting. You might want to add some logging so that you know whether your web server is leaking memory, or if there is someone attempting to exploit you.

Code :

# OptionsBleed mitigation
# -----------------------

# This rule sanitises the returned Allow header to mitigate memory leaks
# Only the whitelisted verbs get|post|head|options|put|delete|patch|propfind are allowed.
#
# https://blog.fuzzing-project.org/60-Optionsbleed-HTTP-OPTIONS-method-can-leak-Apaches-server-memory.html
#
# If any other verbs are returned by the server, the whole Allow header is omitted from the response
#

when HTTP_RESPONSE {
    # Grab all the Allow headers being set in this response
    set allowheaders [HTTP::header values "Allow"]

    # Remove them from the response, so we can re-add them if they are safe
    HTTP::header remove "Allow"

    foreach header $allowheaders {

# Check if there's anything invalid in the Allow header

# A good header will look like: GET,POST,OPTIONS,HEAD
# Split each verb apart at the , character

set denied 0
set verbs [split $header ","]

for {set i 0} {$i < [llength $verbs]} {incr i} {
    
    set verb [lindex $verbs $i]

    # Check if the verb is allowed.
    # Maybe extend to this list?
    # HEAD, GET, PUT, POST, DELETE, TRACE, OPTIONS, MOVE, INDEX, MKDIR, RMDIR, COPY, CONNECT, PROPFIND, PROPPATCH, MKCOL, LOCK, UNLOCK, ACL, REPORT, VERSION-CONTROL, CHECKOUT, CHECKIN, UNCHECKOUT, MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, SEARCH, SUBSCRIBE, UNSUBSCRIBE, NOTIFY, POLL, BDELETE, BCOPY, BMOVE, BPROPPATCH, BPROPFIND
    if {[regexp -nocase {^get|post|head|options|put|delete|patch|propfind$} $verb]} {
#log local0. "Allowed Verb: $verb"
    } else {
#log local0. "Denied Verb: $verb"
set denied 1
    }
}

# If there is no denied verbs, then pass the Allow header through
if {$denied == 0} {
    HTTP::header insert "Allow" $header
}
    }
}
Published Sep 22, 2017
Version 1.0
No CommentsBe the first to comment