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:
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
- https://clouddocs.f5.com/api/irules/ASM__violation_data.html
- https://clouddocs.f5.com/api/irules/ASM__violation.html
- https://clouddocs.f5.com/api/icontrol-soap/ASM__ViolationName.html
- swo0sh_gt_13163AltostratusHey Dylan, Thanks for posting this article, especially with iRule sample. This was much needed. Thanks for the good work. Keep up the good work!
- riraccuiaCirrusThank 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 } } }
- sdull_320887Nimbostratus
what is the list of executable files?
- MSZNimbostratus
IS it possible to check the contents of the file uploaded via F5 ASM?
- Jiri_RosenmayerAltostratus
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] " } } }
- Mohsen_Ba_alawiEmployee
, You can set up a third-party integrated anti-virus service on the ASM and have these files be checked for virus/malware by having the ASM send it to an external ICAP server:
K70941653: Configuring BIG-IP ASM antivirus protection
- mplaksin0Cirrus
Great article, i am with problems with uploads, so i will try this configuration. Thanks!