First step with this issue or related issues is to check your error logs via FTP or SHH. For me checking the error log showed this:
[Sun Sep 16 19:35 2018] [:error] [pid 999:tid 140411850934016] [client IP REDACTED] [client IP REDACTED] ModSecurity: Access denied with code 403 (phase 2). Pattern match "..." at REQUEST_URI. [file "/etc/apache2/modsecurity.d/rules/tortix/modsec/50_plesk_basic_asl_rules.conf"] [line "253"] [id "340149"] [rev "152"] [msg "Protected by Atomicorp.com Basic Non-Realtime WAF Rules: Potential Cross Site Scripting Attack"] [data "ecmascript"] [severity "CRITICAL"] [hostname "inboundfound.com"] [uri "/wp-content/plugins/gutenberg/vendor/wp-polyfill-ecmascript.min.2ae96136.js"] [unique_id "W56wkH8AAAEAAAPn6dMAAABS"], referer: https://inboundfound.com/wp-admin/post-new.php
Let’s break down the structure of the error:
- Date – self explanatory
- Error – we’re in the errorlog but for a list of loglevel directives, see apache.org docs here
- pid / tid – this stands for process id and thread id of the daemon
- client IP – self explanatory
- ModSecurity: Access denied with code 403 (phase 2). – This is how the server responded to the underlying issue (but NOT the actual issue)
- file – this is super helpful. It tells us exactly what file and line in the file as well as the actual culprit via security rule id and msg
- id – security rule id, a comprehensive list is hard to find outside of your .conf file BUT the message gives you what you need anyway
- msg – the actual security rule “explained” in this case potential cross-site scripting attack (XSS)
The culprit – your server configuration
(for me editable in the ModSecurity firewall settings of Plesk)
- Atomic Basic ModSecurity – A starter version of the Atomic ModSecurity rules. Provides basic web application firewall functionality. Updated on a monthly basis.
- OWASP ModSecurity – The OWASP rule set is very restrictive and thus might block some functions, such as file sharing, webmail, and some web applications, including WordPress.
- Advanced ModSecurity Rules by Atomicorp (requires subs
- Comodo ModSecurity (requires subscription)
- Custom rule set – Upload a custom web application firewall rule set. Supported formats: zip, tar.gz, tgz, tar.bz2, conf.
[msg "Protected by Atomicorp.com Basic Non-Realtime WAF Rules: Potential Cross Site Scripting Attack"]
My message showed the actual config file I was using, which was a default one that still created issues with a Gutenberg plugin js dependency.
Do you need your firewall active?
You probably need some sort of protection. If your security rule ID is coded for something insignificant or overkill and just continuously causes false positives and locks you out of working on a given site, you can create an exclusion and turn off that actual security rule. You can do this in the .conf file OR in Plesk there’s a form you can drop a rule into: for me it would mean excluding the actual mod security ID: 340149
Isn’t that a bad idea? What’s the best practice here?
Ideally, you want to exclude this specific issue, not the entire security directive because that sort of throws the baby out with the bathwater if its not an overly conservative and unnecessary rule.
In this case our directive is aimed at preventing cross-site scripting attacks (XSS). XSS attacks are possibly the most common WordPress security vulnerability so we probably shouldn’t just turn this rule off:
So we can’t just turn off XSS protection.
Whitelisting IPs or URIs to the rescue
LiquidWeb has a great post on how to do this. Whitelisting your IP is ideal if you work from home or your office and there is a static IP associated with doing that and you aren’t using VPNs a lot while developing.
In that post they provide example file paths to find the .conf files you need to edit BUT we’re already given this in the actual errorlog :
[file “/etc/apache2/modsecurity.d/rules/tortix/modsec/50_plesk_basic_asl_rules.conf”] [line “253”] [id “340149”] [rev “152”] [msg “Protected by Atomicorp.com Basic Non-Realtime WAF Rules: Potential Cross Site Scripting Attack”] [data “ecmascript”]found via ftp /logs/error_log
To exclude your IP address you will need to do a bit of regex. If you’re uncomfortable with this you can use a regex tester tool.
If you get a match, with this precise format, you should be good to go!
Questions or feedback?
Let me know if you have any questions or feedback – I would love to know if there is a way to exclude errors case by case, e.g. logged in WordPress admins working on posts/pages with Gutenberg plugin activated.