Mitigate Apache strut2 vulnerability, cve-2017-5638

Problem this snippet solves:

F5 has updated the official KB article K43451236 on AskF5 to include an enhanced version of the iRule below that will protect your vulnerable web servers behind the BIG-IP that will mitigate Apache strut2 vulnerability, cve-2017-5638

How to use this snippet:

Add the irule to a virtual server.

Irule below contributed by LinJing.

Code :

# Contributed by LinJing
when HTTP_REQUEST {
if {([HTTP::header exists "Content-Type"])}{
    set ctheader [string tolower [HTTP::header "Content-Type"]]
    if {($ctheader contains "multipart/form-data") and (($ctheader contains "'") or ($ctheader contains "ognl") or ($ctheader contains "java.lang") or ($ctheader contains "bash") or ($ctheader contains "cmd") or ($ctheader contains "org.apache")) }{
          log local0. "Found Struts S2-045 attack! Rejecting a request with Content-type [HTTP::header "Content-Type"] to  [HTTP::uri]  from  [IP::client_addr]"
          #if you do not want to reset the connection, then comment out the lien below
          reject
        }
    }
}
Published Mar 07, 2017
Version 1.0

Was this article helpful?

12 Comments

  • Here is another iRule that can block most but NOT all attacks. This irule is based on attack signatures that be been seen.

    If you decide to use this iRule please test it thoroughly against your application to make sure it does not block legitimate requests.

    when HTTP_REQUEST {
    if {([HTTP::header exists "Content-Type"])}{
        set ctheader [string tolower [HTTP::header "Content-Type"]]
        if {($ctheader contains "multipart/form-data") and (($ctheader contains "'") or ($ctheader contains "ognl") or ($ctheader contains "java.lang") or ($ctheader contains "bash") or ($ctheader contains "cmd") or ($ctheader contains "org.apache")) }{
              log local0. "Found Struts S2-045 attack! Rejecting a request with Content-type [HTTP::header "Content-Type"] to  [HTTP::uri]  from  [IP::client_addr]"
              if you do not want to reset the connection, then comment out the lien below
              reject
            }
        }
    }
    

    Here is another irule that reference a famous FW vendor's sig, Pls test:

    when HTTP_REQUEST {
    if {([HTTP::header exists "Content-Type"])}{
        set ctheader [string tolower [HTTP::header "Content-Type"]]
        if {($ctheader contains "multipart/form-data") and not($ctheader starts_with "multipart/form-data")}{
             log local0. "Found Struts S2-045 attack! Rejecting a request with Content-type [HTTP::header "Content-Type"] to  [HTTP::uri]  from  [IP::client_addr]"
             if you do not want to reset the connection, then comment out the lien below
             reject
            }
        }
    }
    
  • The RCA is the function 'findText' will execute the injection code. That means, before execute the injection code, attacker need to trigger an exception.

     

    Thus, the necessary and sufficient conditions are as below:

     

    • The Request contains 'Content-Type'
    • The Content-Type contains 'multipart/form-data'
    • The Content-Type should be illegal to trigger Error Key 'struts.messages.error.content.type.not.allowed'

    (refer to: https://cwiki.apache.org/confluence/display/WW/File+UploadFileUpload-AlternateLibraries)

     

    This maybe explained why the FW vendor's sig is using starts_with like below (currently, most PoC codes are added additional characters in the beginning of Content-Type):

     

    if {($ctheader contains "multipart/form-data") and not($ctheader starts_with "multipart/form-data")}{
    

    I suspect that if modify the PoC string like 'haha%{}multipart/form-data' or 'multipart/form-datahaha%{}' may have same result. That means 'starts_with' may not be exact enough for block the injection. Therefore, I would prefer to choose Linjing's irule. It would be better.