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://support.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/kb/en-us/solutions/public/7000/900/sol7935.html 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:

https://devcentral.f5.com/wiki/iRules.ASM__violation_data.ashx

https://devcentral.f5.com/wiki/iRules.ASM__violation.ashx

https://devcentral.f5.com/wiki/iControl.Print.aspx?Page=iControl.ASM__ViolationName