Modsecurity for Plesk 2

I already spend some attention on this subject. A customer complained that the webmail did not work no more. The user was able to logon but could not send an e-mail. Obviously this had something to do with Modsecurity. I’m running Plesk on a Ubuntu server. So enabling Modsecurity and enforcing this down on all customers is troublesome. But Plesk does not give you the option to enable or disable Modsecurity on “system” subdomains. Like for example webmail.domain.tld. So this causes an issue when Modsecurity is enabled system wide and webmail is needed. If you were to just read webmail and not answer everything will work just fine. There’re so many rules you’ll need to disable or exclude before it will run fine that it makes no sense to configure this. It’ll practically undermine the sole function of Modsecurity.

Plesk apparently  has a config file for each webmail subdomain. This file is located either here:

/etc/apache2/plesk.conf.d/webmails/roundcube/domain.tld_custom_webmail.conf

or here:

/etc/apache2/plesk.conf.d/webmails/horde/domain.tld__custom_webmail.conf

And now you’ll have to decide whether to exclude a great number of rules or to disabled Modsecurity completely.  If you want to disabled Modsecurity completely and want to enforce security by adding some security headers you can use the code below:

<IfModule mod_security2.c>
  SecRuleEngine Off
</IfModule>
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Content-Type-Options: nosniff
Header always set X-Frame-Options: SAMEORIGIN
Header always set X-XSS-Protection: "1; mode=block"
Header unset Content-Security-Policy
Header add Content-Security-Policy "default-src https: 'unsafe-inline' 'unsafe-eval';connect-src https: wss:"
Header always set Public-Key-Pins 'pin-sha256="2rpOTT3tKv5TF8/hZGAEvA5aJAwFrXSrEX404CzY9mM="; pin-sha256="gXyS+QHqbu4T0pNQLIgUX+WyMI3ndaViZacoqedaA/o="; max-age=2592000'
Header always edit Set-Cookie (.*) "$1; HTTPOnly; Secure"

If you want to disabled rules by ID (by url is impossible because that changes with every mail) you can use the code below:

<IfModule mod_security2.c>
SecRuleRemoveById 981319 960024 981231
</IfModule>
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Content-Type-Options: nosniff
Header always set X-Frame-Options: SAMEORIGIN
Header always set X-XSS-Protection: "1; mode=block"
Header unset Content-Security-Policy
Header add Content-Security-Policy "default-src https: 'unsafe-inline' 'unsafe-eval';connect-src https: wss:"
Header always set Public-Key-Pins 'pin-sha256="2rpOTT3tKv5TF8/hZGAEvA5aJAwFrXSrEX404CzY9mM="; pin-sha256="gXyS+QHqbu4T0pNQLIgUX+WyMI3ndaViZacoqedaA/o="; max-age=2592000'
Header always edit Set-Cookie (.*) "$1; HTTPOnly; Secure"

I guess to risk is somewhat moderate if you consider that anyone can send you a message with html content. But sometimes security is a notch below functionality.

Making exclusions is a very normal task when Modsecurity is enabled. So how do you do that? Well next to what’s shown above you’ll have the option to disable rules based on the request url. When using WordPress for example. Many thing do not work very well. This is especially when OWASP is enabled.  So to create some rules you’ll have to edit the config file below:

/etc/apache2/modsecurity.d/rules/modsecurity_crs-plesk/modsecurity_crs_15_custom.conf

If the file does not exist, create it. You can than append to file with the rules and URL that you can find when watching the log file. Enable Modsecurity first in report only. Than add the necessary rules and your site is much safer.

SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261001,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=973332"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261002,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=970903"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261003,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=973344"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261004,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=973333"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261005,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=973306"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261006,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=973304"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261007,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=973300"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261008,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=973338"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261009,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=981243"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261010,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=981245"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261011,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=981317"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261012,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=950901"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261013,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=981231"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261014,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=950120"
SecRule REQUEST_FILENAME "@streq /wp-admin/post.php" "id:88261015,phase:1,t:none,nolog,pass,ctl:ruleRemoveById=960024"