File Uploads and ASM

File Uploads through a WAF

Let’s say we have a web application with a form field that permits the upload of arbitrary files.  It would appear to the user similar to the below:

Aside from photos, the application may permit users to upload Word documents, Excel spreadsheets, PDF’s, and so forth.

This can cause many false positives when the web application is protected by ASM, because the uploaded files may:

  • Contain attack signatures.  Image files may be parsed as ASCII, and suspicious-looking strings detected; Word or Excel documents may contain XSS tags or SQL injection strings.  After all, Mr. ‘Select’ – ‘Union City’ -- is one of our most valuable customers.
  • Contain illegal metacharacters, like XSS tags <>
  • Be so large that the maximum request size (10MB by default) is exceeded
  • Trip other violations

It is therefore necessary to inform ASM that a particular parameter on a form field is one that contains a file upload so that checking for attack signatures and metacharacters can be disabled.

Why not just disable the signature?

Simply, because we do not want to introduce unnecessary exposure into the security policy.  Just because a particular signature causes a false positive on the file upload transaction does not mean it should do elsewhere on the web application.  At the time of writing, ASM permits attack signatures to be selectively disabled on parameters, but not URLs.

 

Identify the Upload Parameter(s)

Use a HTTP inspection tool such as Fiddler, Burp or Developer Tools to determine the name of the upload parameter and URL.  In this case, we are uploading a JPG file named DSCF8205.JPG; the parameter used to transfer the file is called ‘filename1’.  The URL is /foo.cfm.

 

NOTE: This can also be obtained from the ASM request log; however these do sometimes get truncated making it impossible to determine the parameter name if it occurs more than 5KB into the request.

 

Define the Upload Parameter(s)

Assuming the upload is specific to a given URL, create that URL in the ASM policy. 

Next, create a parameter with the name we discovered earlier, and ensure it is set to type ‘File Upload’.

 

Alternate Configuration Options

  • If file upload is possible in many parts of the site using the same filename, create the parameter globally without defining the URL as we did first here
  • If many file upload parameters are present on a single page with a similar name (e.g. filename1, filename2, filename3…), create a wildcard parameter name filename*
  • ‘Disallow file upload of executables’ is a desirable feature.  It checks the magic number of the uploaded file and blocks the upload if it indicates an executable file.
  • As with all ASM configurations, understanding the HTTP fields passed to the application is key

 

The above procedure should work for most cases, and arbitrary file uploads (except executables) should be allowed.  However, there are some cases where additional configuration is required.

 

Didn’t Work?

Attack signatures have a defined scope, as seen below:

Table C.1 Attack signature keywords and usage

 Keyword

 Usage

 content

 Match in the full content. See Using the content rule option, for syntax information.

 uricontent

 Match in the URI, including the query string (unless using theobjonly modifier).  See Using the uricontent rule option, for syntax information.

 headercontent

 Match in the HTTP headers. See Using the headercontent rule option, for syntax information.

 valuecontent

 Matches an alpha-numeric user-input parameter (or an extra-normalized parameter, if using the norm modifier); used for parameter values and XML objects. See Using the valuecontent rule option, for syntax information, and Scope modifiers for the pcre rule option, for more information on scope modifiers.

 An XML payload is checked for attack signatures when thevaluecontent keyword is used in the signature.

 Note: The valuecontent parameter replaces the paramcontent parameter that was used in the Application Security Manager versions earlier than 10.0.

 reference

 Provides an external link to documentation and other information for the rule.  See Using the reference rule option, for syntax information.

 

This information can be found in ASM under “Attack Signatures List”.  As an example, search for ‘Path Traversal’ attack types and expand signature id’s 200007006 and 200007000:

 

A signature with a ‘Request’ scope does not pay any attention to parameter extraction – it just performs a bitwise comparison of the signature to the entire request as a big flat hex blob.  So to prevent this signature from being triggered, we can (a) disable it, (b) use an iRule to disable it on these specific requests.

Before we can use iRules on an ASM policy, we need to switch on the ‘Trigger ASM iRule Events’ setting on the main policy configuration page.  Further information can be found at: https://techdocs.f5.com/kb/en-us/products/big-ip_asm/manuals/product/asm-implementations-11-5-0/27.html.

 

The below is an iRule that will prevent a request meeting the following characteristics from raising an ASM violation:
 

  • Is a POST
  • URI ends with /foo.cfm
  • Content-Type is ‘multipart/form-data’
  • Attack Signature violation raised with signature ID 200007000
when ASM_REQUEST_VIOLATION {
  if {([HTTP::method] equals "POST") and ([string tolower [HTTP::path]] ends_with "/foo.cfm") and ([string tolower [HTTP::header "Content-Type"]] contains "multipart/form-data") } {
    if {([lindex [ASM::violation_data] 0] contains "VIOLATION_ATTACK_SIGNATURE_DETECTED") and ([ASM::violation details] contains "sig_data.sig_id 200007000") } {
      ASM::unblock
    }
  }
}

What if you’re getting a lot of false positives and just want to disable attack signatures with Request scope?

when ASM_REQUEST_VIOLATION {
  if {([HTTP::method] equals "POST") and ([string tolower [HTTP::path]] ends_with "/foo.cfm") and ([string tolower [HTTP::header "Content-Type"]] contains "multipart/form-data") } {
    if {([lindex [ASM::violation_data] 0] contains "VIOLATION_ATTACK_SIGNATURE_DETECTED") and ([ASM::violation details] contains "context request") } {
      ASM::unblock
    }
  }
}

But it’s not an attack signature…

False positives might also be generated by large file uploads exceeding the system-defined maximum size.  This value is 10MB by default and can be configured.  See https://support.f5.com/csp/article/K7935 for more information.

However, this is a system-wide variable, and it may not be desirable to change this globally, nor may it be desirable to disable the violation.  Again, we can use an iRule to disable this violation on the file upload:

when ASM_REQUEST_VIOLATION {
  if {([HTTP::method] equals "POST") and ([string tolower [HTTP::path]] ends_with "/foo.cfm") and ([string tolower [HTTP::header "Content-Type"]] contains "multipart/form-data") } {
    if {([lindex [ASM::violation_data] 0] contains "VIOLATION_REQUEST_TOO_LONG") } {
      ASM::unblock
    }
  }
}

ASM iRules reference

 

Published Dec 30, 2015
Version 1.0
  • Hey Dylan, Thanks for posting this article, especially with iRule sample. This was much needed. Thanks for the good work. Keep up the good work!
  • Thank you for the very useful article. If you are on v11.5 or higher though you don't wanna use Compatibility mode as the iRules event mode. I'd go for Normal mode and change the irule as follows when HTTP_REQUEST { set unblock 0 if {([HTTP::method] equals "POST") and ([string tolower [HTTP::path]] ends_with "/foo.cfm") and ([string tolower [HTTP::header "Content-Type"]] contains "multipart/form-data") } { set unblock 1 } } when ASM_REQUEST_DONE { if { $unblock == 1 } { if {([lindex [ASM::violation_data] 0] contains "VIOLATION_ATTACK_SIGNATURE_DETECTED") and ([ASM::violation details] contains "context request") } { ASM::unblock } } }
  • MSZ's avatar
    MSZ
    Icon for Nimbostratus rankNimbostratus

    IS it possible to check the contents of the file uploaded via F5 ASM?

     

  • I've been using your iRule a bit, but we realized there is one problem with it. Imagine, there is a request which violates like 15 different violations(so it is a real attack). And now with your iRule, if one of the violations would be attack signature in context request, it would be unblocked. I've found a way how to improve the iRule. It reads the violation details, and if it finds other violation than VIOL_ATTACK_SIGNATURE in other context than request, it will keep blocking the request.

     when ASM_REQUEST_VIOLATION {
      log local0. "ASM Violation: [HTTP::method], [string tolower [HTTP::path]], [ASM::violation names] ; [ASM::violation details] "
      if {([HTTP::method] equals "POST") and ([class match [string tolower [HTTP::path]] equals upload-paths]) and ([string tolower [HTTP::header "Content-Type"]] contains "multipart/form-data") } {
         set details [ASM::violation details]
         set i 0
         set only_attack_context_request 1
         foreach {viol} $details {
           if { [lindex ${viol} 0] equals "viol_name" } {
             log local0. "ASM 01 $viol; [lindex ${details} [expr {$i+1}]]"
             if { ($viol ne "viol_name VIOL_ATTACK_SIGNATURE" ) or ([lindex ${details} [expr {$i+1}]] ne "context request") } {
               set only_attack_context_request 0
             }
           }
           set i [expr {$i+1}]
         }    
         if {$only_attack_context_request == 1 } {
          ASM::unblock
          log local0. "ASM unblocked [HTTP::method], [string tolower [HTTP::path]], [ASM::violation details] "
         }
      }
    }
    
  • Great article, i am with problems with uploads, so i will try this configuration. Thanks!