Uploading SVG files to WordPress when you’re behind the Sucuri CloudProxy Web Application Firewall isn’t that straightforward, but it is possible.

First of all: Are you sure you want to enable SVG uploads? Please read “SVG uploads in WordPress (the Unconvenient Truth)” first.


A couple of weeks ago I launched a new site on WordPress behind CloudProxy, the web application firewall from Sucuri. Today I was going to upload an SVG image in the media manager when this horrible little error message appeared:

So it was time to whip up the browser inspector which showed that this, in fact, was a request to wp-admin/async-upload.php which gave a HTTP error status 403.

Sucuri WebSite Firewall - CloudProxy - Access Denied

This code means “Access Denied” so I took a look at the response source and found this indicator that CloudProxy was blocking the request:

Sucuri WebSite Firewall - CloudProxy - Access Denied

So I scrolled down to see if I could get some more info, and sure I did:

Block reason: An attempted XSS (Cross site scripting) was detected and blocked.

Well, since this was no XSS attack but a legitimate file upload, I contacted Sucuri support. The answer I got was that they whitelisted my IP address and gave me instructions on how to do that myself. WTF Sucuri?

[bjornad]

This is not an acceptable solution due to, not only dynamic IP addresses, but also the fact that I don’t know every IP address that every editor will use to connect to the admin area.

From here on, I could only see two possible directions:

1. Whitelist the URL /wp-admin/async-upload.php which is very unfortunate, as this specific URL is clearly a target for attackers.

2. Writing a WordPress plugin that uses the CloudProxy API to update the whitelist on successful login.

Since it was the by far quickest fix, I whitelisted the URL:

Just a few seconds later, SVG-files could be uploaded as normal.

But since this is a delicate URL – which attacker wouldn’t like to find a vulnerability in a URL that let you upload files? – I did not want to leave it whitelisted and unprotected.

Whitelisting IP addresses is a trivial matter with the CloudProxy API, as this curl request from the documentation shows:

curl 'https://waf.sucuri.net/api?v2' \
  --data 'k=API_KEY' \
  --data 's=API_SECRET' \
  --data 'a=whitelist_ip' \
  --data 'ip=127.0.0.1'

A few minutes of digging into the free Sucuri plugin revealed a few handy static methods we could use to quickly throw together a plugin like this (without the plugin comment headers):

https://gist.github.com/bjornjohansen/c6598834712eb3b6cc5b18e23b186190

When activated, this plugin will whitelist all IP addresses for users with the capability unfiltered_html. By WordPress default this is only users with the role “Administrator” (only “Super Administrator” on multisite networks). It is very important to remember that whitelisting the IP address will circumvent most security features in CloudProxy for all visitors from that IP address. In my case I (kind of) trust the users who can upload files (by default, this is all roles from “Contributor” and up), so I used the filter to set the necessary capability to upload_files:

https://gist.github.com/bjornjohansen/8b02936ec6e69606b7cead19fd313574

Keep in mind that it is not possible to remove a whitelisted IP address using the API, so you will have to do that in the dashboard.

Conclusion

We can either whitelist the URL /wp-admin/async-upload.php which leaves the script that handles uploads unprotected by CloudProxy, or we can auto-whitelist users, which leaves the entire installation unprotected from those IP addresses.

Neither solution is ideal, but until Sucuri rolls out a feature to allow for SVG uploads, this seems to be what we have to live with if we want to use CloudProxy.

Endnote

If you have a static IP address, e.g. from your office or your own private VPN, you can whitelist that address in the CloudProxy dashboard without any hassle. If you do, you should also restrict access to wp-admin to whitelisted IPs. This would be the same as restricting access to the WordPress dashboard by IP address in Nginx.