Page 1 of 1

WordPress – Mod_security problems with posts and comments fixed

WordPress – Mod_security problems with posts and comments fixed
   5

In the world of WordPress, this situation does not seem uncommon;

A user posts a comment, and instead of actually posting the comment, gets redirected to the main page of your website. Not just annoying for webmasters, but a very unpleasant experience for visitors that like to actively contribute.

Quite often, with WordPress, this is caused by a false-positive being triggered by mod_security.

In this short article, I’ll show you what might be causing this issue, how to identify it, and how we can fix it.




WordPress, Mod_Security and False Positives

What I have noticed is that this happens when mod_security fires a so called false-positive.

The task of mod_security is to catch dangerous and malicious “code” that might harm your web-server.
One of the most common ones being “SQL injection“, a technique where the “attacker” adds certain characters to submitted comments or posts, which will make the SQL statement (database) that stores the post or comment, do something really bad to your database or data.

Obviously we do not want this to happen, so mod_security does a great job in trying to catch those “injections”.

However, it can be very difficult to define a rule that catches everything 100% correct, which causes these false-positives. A perfectly legit text get’s flagged and mod_security takes the safe route and brings the user back to your homepage instead of executing the SQL statement to store the “malicious” post.

Mod_security has all kinds of rules defined to catch all kinds of malicious attacks, so it’s not just one rule. But one of these rules that seem to fire quite often, producing a false-positive, is rule “300016” with the message “Generic SQL injection protection”.

You can check this on your server by checking the mod_security log file.
On my server it’s located at: /etc/httpd/logs/modsec_audit.log or /etc/httpd/logs/error.log

When accessing your server from a shell or using SSH, a simple “tail” statement right after posting an offending comment, will reveal this. Something like this:


tail /etc/httpd/logs/error_log

[Sun Mar 14 07:57:23.857486 2016] [:error] [pid 1328] [client 77.161.107.217]
ModSecurity: Access denied with code 500 (phase 2).
Pattern match "(insert[[:space:]]+into.+values|select.*from.+[a-z|A-Z|0-9]|select.+
from|bulk[[:space:]]+insert|union.+select|convert.+(.*from)" at ARGS:comment.
[file "/usr/local/apache/conf/modsec2.user.conf"] [line "379"] [id "300016"]
[rev "2"] [msg "Generic SQL injection protection"] [severity "CRITICAL"]
[hostname "www.example.com"] [uri "/wp-comments-post.php"]
[unique_id "VuVVo0UQ6TcBBAUwzDEAABBAb"]

If you see messages like this (I’ve added a few line-breaks), then this article is for you … well, unless you know for a fact that the link  uri "/wp-comments-post.php" is not legit, or if the rule id and message point to another issue of course.

Disabling a mod_security rule for WordPress

One option is to completely disable this rule, but by doing so we expose our web-server to an unnecessarily high risk. So I really consider that a very bad plan.

It’s a much better idea to disable certain rules only for very particular pages.

Besides that … WordPress has functions build in to sanitize posted comments, so we could disable this rule just for the places where users post comments and WordPress actually screens and cleans the posted data.

Knowing all that we can relatively safely create a list, in which we “whitelist” certain rules for certain links in our WordPress setup.
I do however strongly recommend to leave this to as little exceptions as possible of course – the less exceptions, the safer for our web-server.

Shared/Virtual Web-Servers 

It can be that your website is running on a shared server or a virtual web-server.
In a situation like that, you will most likely not be able to modify the whitelist as it might affect other websites on that same server as well.

In that case you will have to contact the support team of your web-host provider.

Root access Required! 

To edit your mod_security config file (whitelist in this case), in general ROOT ACCESS will be REQUIRED.

The whitelist can be found in one of two files, either called whitelist.conf or exclude.conf .

I did find mine (CentOS) here: /usr/local/apache/conf/modsec2/whitelist.conf

Before we can create a whitelist, we will need to find or determine which rule(s) cause the false positive(s). I found that, on my setup, the most common ones were: 300013, 300015, 300016 and 300017. With 300013 being the most common one!

Naturally this all depends on the type of website you have and what kind of text visitors will or might enter.

The whitelist.conf (or exclude.conf) file can be edited with a regular text editor like “vi” or “nano”:


cd /usr/local/apache/conf/modsec2/
nano whitelist.conf

The file might already contain one or the other exception, and it’s probably good not to touch those – just add exceptions, do not remove them unless you know why they are there or if you placed them yourself..

Obviously, it’s also good to prevent duplicate exceptions of course.

An example of rules I’ve added:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<locationmatch "/wp-comments-post.php">
  SecRuleRemoveById 300013
  SecRuleRemoveById 300015
  SecRuleRemoveById 300016
  SecRuleRemoveById 300017
</locationmatch>
<locationmatch "/wp-admin/post.php">
  SecRuleRemoveById 300013
  SecRuleRemoveById 300015
  SecRuleRemoveById 300016
  SecRuleRemoveById 300017
</locationmatch>
<locationmatch "/bb-post.php">
  SecRuleRemoveById 300013
  SecRuleRemoveById 300015
  SecRuleRemoveById 300016
  SecRuleRemoveById 300017
</locationmatch>

This should cover posting comments, adding posts (admin) and posts in a bbPress forum.

If you do not have bbPress running, then you’d be good with just this part:


1
2
3
4
5
6
7
8
9
10
11
12
<locationmatch "/wp-comments-post.php">
  SecRuleRemoveById 300013
  SecRuleRemoveById 300015
  SecRuleRemoveById 300016
  SecRuleRemoveById 300017
</locationmatch>
<locationmatch "/wp-admin/post.php">
  SecRuleRemoveById 300013
  SecRuleRemoveById 300015
  SecRuleRemoveById 300016
  SecRuleRemoveById 300017
</locationmatch>

I have seen configs where the following has been added as well, but only add this one if you run into false-positives there as well:


1
2
3
<LocationMatch "/wp-admin/edit-comments.php">
  SecRuleRemoveById 2000149
</LocationMatch>

The sequence in which you add these to your whitelist does not seem to matter (correct me if I’m wrong!).

Disabling a mod_security rule for bbPress

Now I have found that bbPress can have it’s own issues, since the URL you’d like to use might not be consistent (changes per forum and forum-topic).
In that case we need to use a regular expression to catch these.

An example of the error log:


1
2
3
4
5
6
7
8
[Mon Apr 12 17:34:09.310851 2016] [:error] [pid 13207] [client 134.171.197.17]
ModSecurity: Access denied with code 500 (phase 2).
Pattern match "(insert[[:space:]]+into.+values|select.*from.+[a-z|A-Z|0-9]|select.+
from|bulk[[:space:]]+insert|union.+select|convert.+\\\\(.*from)" at ARGS:bbp_topic_content.
[file "/usr/local/apache/conf/modsec2.user.conf"] [line "247"] [id "300016"]
[rev "2"] [msg "Generic SQL injection protection"] [severity "CRITICAL"]
[hostname "www.example.com"] [uri "/forum/development/sql/"]
[unique_id "VxVNbUUQ6TcAADOXFTsAAAAB"]

The problem is that the URL is (for this forum topic only): /forum/development/sql/
For another topic this could be: /forum/development/delphi/ or /forum/development/lazarus/

So we’d have to make a rule for each of those? No we don’t,… thank goodness.
We can solve this with a regular expression (well almost anyway), say we’d like to disable to rules for all URL’s that start with “/forum/development/”:


1
2
3
4
5
6
<locationmatch "^/forum/development/.*">
  SecRuleRemoveById 300013
  SecRuleRemoveById 300015
  SecRuleRemoveById 300016
  SecRuleRemoveById 300017
</locationmatch>

 

Restarting Apache

Once you’ve saved your changes (in nano: CTRL+X, Y, press ENTER), you will need to restart Apache so it takes the whitelist in consideration.

Restarting can be done in several ways. I usually do this through cPanel’s WHM (Web Host Manager).
Alternatively, depending on your setup, this can be done with one of these methods, where root access is typically needed,

These are 4 examples, … there are probably more ways to do this.


1
2
3
4
sudo /etc/init.d/apache2 restart
sudo service apache2 restart
sudo restart apache2
sudo apache2ctl restart

Alternative Whitelists for WordPress

Obviously I have been searching the web for all kinds of solutions.
For example, this article at WPSecure is a very good read as well …
Since they could be of use to you, I’ve posted a 2 examples below – I have not used or tested these, so your milage may vary.

Again; only pick those exceptions you really need. Less is better.
And … don’t forget to pay attention to the “LocationMatch” line, as they will tell you when the exception is being applied so you can determine if this is needed for your setup or not.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<LocationMatch "/wp-admin/post.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>

<LocationMatch "/wp-admin/admin-ajax.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>

<LocationMatch "/wp-admin/page.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>

<LocationMatch "/wp-admin/options.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>

<LocationMatch "/wp-admin/theme-editor.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>

<LocationMatch "/wp-includes/">
  SecRuleRemoveById 960010 960012 950006
</LocationMatch>

 

This following list is quite extensive, and probably too extensive for most of us (source) :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<LocationMatch "/wp-admin/post.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-admin/admin-ajax.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-admin/page.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-admin/options.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-admin/theme-editor.php">
  SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-content/plugins/">
  SecRuleRemoveById 300015 340151 1234234 340153 1234234 300016 300017 950907 950005 950006 960008 960011 960904 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-includes/">
  SecRuleRemoveById 960010 960012 950006 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-content/themes/">
  SecRuleRemoveById 340151 340153 1234234 950006 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-content/plugins/sociable/">
  SecRuleRemoveById 960010 960012 950006 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-content/plugins/wp-recaptcha/">
  SecRuleRemoveById 340151 340153 1234234 300015 300016 300017 950907 950005 950006 960008 960011 960904 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch "/wp-content/plugins/fancybox-for-wordpress/">
  SecRuleRemoveById 960010 960012 950006 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

<LocationMatch “/wp-includes/js/tinymce/plugins/spellchecker/rpc.php”>
  SecRuleRemoveById 960010
  SecRuleRemoveById 960012
  SecRuleRemoveById 959006
</LocationMatch>

<LocationMatch "/wp-content/themes/YOURTHEMEFOLDER/thumb.php">
  SecRuleRemoveById 340151 340153 1234234 300015 300016 300017 950907 950005 950006 960008 960011 960904 959006
  SecRuleRemoveById phpids-17
  SecRuleRemoveById phpids-20
  SecRuleRemoveById phpids-21
  SecRuleRemoveById phpids-30
  SecRuleRemoveById phpids-61
</LocationMatch>

Donation options


Donations are very much appreciated, but not required. Donations will be used for web-hosting expenses, project hardware or a motivational boost (a drink or snack). Thank you very much for those have donated already! It's truly AwEsOmE to see that folks like our articles and small applications.

Comments


There are 5 comments. You can read them below.
You can post your own comments by using the form below, or reply to existing comments by using the "Reply" button.

  • Mar 9, 2017 - 1:22 PM - Daniel Comment Link

    Hi,

    very nice article. I am still fighting with modsecurity. Do you have absolutly no false positive comments with your configuration? I always think: “yes,  solved” – but unfortunatly there are still comments blocked. Especially when they use special character.

    Thx

    Reply

    Daniel

    • Mar 9, 2017 - 3:16 PM - hans - Author: Comment Link

      Hi Daniel,

      thank you very much – as you migth have guessed … modsecurity is something we need, but it’s not 100% perfect and certain scenarios will still cause problems. Having said that: after applying these rules, I have not experienced issues on my website or the forum. This however is by no means a guarantee that this would be the case on your website. I guess it depends on what kind of false positives you’re getting.

      Did you try these settings yet?

      Reply

      hans

  • Mar 12, 2017 - 5:08 AM - Daniel Comment Link

    Hey,

    thanks for replying to my post. Yes I have added your rules.

    For example, if I write a simple comment, I still get this (coming from the generic_attacks of modsecurity):

    [id "950911"] [rev "2"] [msg "HTTP Response Splitting Attack"] 
    Reply

    Daniel

    • Mar 12, 2017 - 5:16 AM - Daniel Comment Link

      at the moment I ended up with this

      <LocationMatch "/wp-comments-post.php">
      SecRuleRemoveById 300013
      SecRuleRemoveById 300015
      SecRuleRemoveById 300016
      SecRuleRemoveById 300017
      SecRuleRemoveById 960024
      SecRuleRemoveById 950911
      SecRuleRemoveById 950901
      SecRuleRemoveById 973300
      </LocationMatch>

      Reply

      Daniel

    • Mar 12, 2017 - 5:19 PM - hans - Author: Comment Link

      Thanks for posting Daniel! 

      Are you using anything special on your website since you need to make exceptions for wp-comments-post?

      Reply

      hans



Your Comment …

Friendly request to not post large files here (like source codes, log files or config files). Please use the Forum for that purpose.

Please share:
*
*
Notify me about new comments (email).
       You can also use your RSS reader to track comments.


Tweaking4All uses the free Gravatar service for Avatar display.
Tweaking4All will never share your email address with others.