The internet today is an insecure place. It’s important to have a good 1st line of defence against web application attacks.
Using mod_security can be tricky with many false positives. Make sure to keep an eye on your log files when activating this module!
Installing the module
# apt install libapache2-mod-security2
If you are planning to use it for a wordpress site, there are a few rules to activate. i use the following ruleset inside the Apache Directive Block of ISPConfig vhost.
<IfModule mod_security2.c> SecRuleEngine On SecRequestBodyAccess On SecResponseBodyAccess On SecResponseBodyMimeType text/plain text/html text/xml application/octet-stream SecResponseBodyLimit 546870912 <locationmatch "/wp-json/wp/v2/posts/"> SecRuleRemoveById 930100 SecRuleRemoveById 930110 SecRuleRemoveById 949110 SecRuleRemoveById 980130 </locationmatch> SecRule &TX:crs_exclusions_wordpress|TX:crs_exclusions_wordpress "@eq 0" \ "id:9002000,\ phase:1,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ skipAfter:END-WORDPRESS" SecRule &TX:crs_exclusions_wordpress|TX:crs_exclusions_wordpress "@eq 0" \ "id:9002001,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ skipAfter:END-WORDPRESS" # # -=[ WordPress Front-End ]=- # # # [ Login form ] # # User login password SecRule REQUEST_FILENAME "@endsWith /wp-login.php" \ "id:9002100,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pwd,\ ver:'OWASP_CRS/3.2.0'" # Reset password SecRule REQUEST_FILENAME "@endsWith /wp-login.php" \ "id:9002120,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq resetpass" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # # [ Comments ] # # Post comment SecRule REQUEST_FILENAME "@endsWith /wp-comments-post.php" \ "id:9002130,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ver:'OWASP_CRS/3.2.0'" # # [ Gutenberg Editor ] # Used when a user (auto)saves a post/page with Gutenberg. # # Gutenberg SecRule REQUEST_FILENAME "@rx /wp-json/wp/v[0-9]+/(?:posts|pages)" \ "id:9002140,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:content,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:json.content,\ ver:'OWASP_CRS/3.2.0'" # Gutenberg via rest_route for sites without pretty permalinks SecRule REQUEST_FILENAME "@endsWith /index.php" \ "id:9002141,\ phase:1,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule &ARGS:rest_route "@eq 1" \ "t:none,\ nolog,\ chain" SecRule ARGS:rest_route "@rx ^/wp/v[0-9]+/(?:posts|pages)" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:content,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:json.content" # # [ Live preview ] # Used when an administrator customizes the site and previews the result # as a normal user. # # Theme select # Example: wp_customize=on&theme=twentyfifteen&customized= # {"old_sidebars_widgets_data":{"wp_inactive_widgets":[], # "sidebar-1":["search-2","recent-posts-2","recent-comments-2", # "archives-2","categories-2","meta-2"]}}&nonce=XXX& # customize_messenger_channel=preview-0 SecRule ARGS:wp_customize "@streq on" \ "id:9002150,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule &ARGS:action "@eq 0" \ "t:none,\ ctl:ruleRemoveTargetById=942200;ARGS:customized,\ ctl:ruleRemoveTargetById=942260;ARGS:customized,\ ctl:ruleRemoveTargetById=942300;ARGS:customized,\ ctl:ruleRemoveTargetById=942330;ARGS:customized,\ ctl:ruleRemoveTargetById=942340;ARGS:customized,\ ctl:ruleRemoveTargetById=942370;ARGS:customized,\ ctl:ruleRemoveTargetById=942430;ARGS:customized,\ ctl:ruleRemoveTargetById=942431;ARGS:customized,\ ctl:ruleRemoveTargetById=942460;ARGS:customized" # Appearance -> Widgets -> Live Preview SecRule ARGS:wp_customize "@streq on" \ "id:9002160,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@rx ^(?:|customize_save|update-widget)$" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=942200;ARGS:customized,\ ctl:ruleRemoveTargetById=942260;ARGS:customized,\ ctl:ruleRemoveTargetById=942300;ARGS:customized,\ ctl:ruleRemoveTargetById=942330;ARGS:customized,\ ctl:ruleRemoveTargetById=942340;ARGS:customized,\ ctl:ruleRemoveTargetById=942370;ARGS:customized,\ ctl:ruleRemoveTargetById=942430;ARGS:customized,\ ctl:ruleRemoveTargetById=942431;ARGS:customized,\ ctl:ruleRemoveTargetById=942460;ARGS:customized,\ ctl:ruleRemoveTargetById=920230;ARGS:partials,\ ctl:ruleRemoveTargetById=941320;ARGS:partials,\ ctl:ruleRemoveTargetById=942180;ARGS:partials,\ ctl:ruleRemoveTargetById=942200;ARGS:partials,\ ctl:ruleRemoveTargetById=942260;ARGS:partials,\ ctl:ruleRemoveTargetById=942330;ARGS:partials,\ ctl:ruleRemoveTargetById=942340;ARGS:partials,\ ctl:ruleRemoveTargetById=942370;ARGS:partials,\ ctl:ruleRemoveTargetById=942430;ARGS:partials,\ ctl:ruleRemoveTargetById=942431;ARGS:partials,\ ctl:ruleRemoveTargetById=942460;ARGS:partials" # Self calls to wp-cron.php?doing_wp_cron=[timestamp] # These requests may be missing Accept, Content-Length headers. # This rule must run in phase:1. SecRule REQUEST_FILENAME "@endsWith /wp-cron.php" \ "id:9002200,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveById=920180,\ ctl:ruleRemoveById=920300,\ ver:'OWASP_CRS/3.2.0'" # # [ Cookies ] # WP Session Manager # Cookie: _wp_session=[hex]||[timestamp]||[timestamp] # detected SQLi using libinjection with fingerprint 'n&1' SecRule REQUEST_COOKIES:_wp_session "@rx ^[0-9a-f]+\|\|\d+\|\|\d+$" \ "id:9002300,\ phase:1,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule &REQUEST_COOKIES:_wp_session "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=942100;REQUEST_COOKIES:_wp_session" # # -=[ WordPress Administration Back-End (wp-admin) ]=- # # Skip this section for performance unless /wp-admin/ is in filename SecRule REQUEST_FILENAME "!@contains /wp-admin/" \ "id:9002400,\ phase:1,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ skipAfter:END-WORDPRESS-ADMIN" SecRule REQUEST_FILENAME "!@contains /wp-admin/" \ "id:9002401,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ skipAfter:END-WORDPRESS-ADMIN" # # [ Installation ] # # WordPress installation: exclude database password SecRule REQUEST_FILENAME "@endsWith /wp-admin/setup-config.php" \ "id:9002410,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:step "@streq 2" \ "t:none,\ chain" SecRule &ARGS:step "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pwd" # WordPress installation: exclude admin password SecRule REQUEST_FILENAME "@endsWith /wp-admin/install.php" \ "id:9002420,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:step "@streq 2" \ "t:none,\ chain" SecRule &ARGS:step "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:admin_password,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:admin_password2,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text" # # [ User management ] # # Edit logged-in user SecRule REQUEST_FILENAME "@endsWith /wp-admin/profile.php" \ "id:9002520,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ctl:ruleRemoveTargetById=931130;ARGS:facebook,\ ctl:ruleRemoveTargetById=931130;ARGS:instagram,\ ctl:ruleRemoveTargetById=931130;ARGS:linkedin,\ ctl:ruleRemoveTargetById=931130;ARGS:myspace,\ ctl:ruleRemoveTargetById=931130;ARGS:pinterest,\ ctl:ruleRemoveTargetById=931130;ARGS:soundcloud,\ ctl:ruleRemoveTargetById=931130;ARGS:tumblr,\ ctl:ruleRemoveTargetById=931130;ARGS:youtube,\ ctl:ruleRemoveTargetById=931130;ARGS:wikipedia,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # Edit user SecRule REQUEST_FILENAME "@endsWith /wp-admin/user-edit.php" \ "id:9002530,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ctl:ruleRemoveTargetById=931130;ARGS:facebook,\ ctl:ruleRemoveTargetById=931130;ARGS:instagram,\ ctl:ruleRemoveTargetById=931130;ARGS:linkedin,\ ctl:ruleRemoveTargetById=931130;ARGS:myspace,\ ctl:ruleRemoveTargetById=931130;ARGS:pinterest,\ ctl:ruleRemoveTargetById=931130;ARGS:soundcloud,\ ctl:ruleRemoveTargetById=931130;ARGS:tumblr,\ ctl:ruleRemoveTargetById=931130;ARGS:youtube,\ ctl:ruleRemoveTargetById=931130;ARGS:wikipedia,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # Create user SecRule REQUEST_FILENAME "@endsWith /wp-admin/user-new.php" \ "id:9002540,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq createuser" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # # [ General exclusions ] # # _wp_http_referer and wp_http_referer are passed on a lot of wp-admin pages SecAction \ "id:9002600,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=920230;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=931130;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=932150;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=941100;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942130;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942200;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942260;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942431;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942440;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=920230;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=931130;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=932150;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=941100;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=942130;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=942200;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=942260;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=942431;ARGS:wp_http_referer,\ ver:'OWASP_CRS/3.2.0'" # # [ Content editing ] # # Edit posts and pages # /wp-admin/post.php, /wp-admin/post.php?t=[timestamp] # - Themes do not properly escape post_title in HTML, so beware of XSS # and be conservative in excluding this parameter. # - Parameter _wp_http_referer can appear multiple times. SecRule REQUEST_FILENAME "@endsWith /wp-admin/post.php" \ "id:9002700,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@rx ^(?:edit|editpost)$" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:post_title,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:content,\ ctl:ruleRemoveById=920272,\ ctl:ruleRemoveById=921180" # Autosave posts and pages # ARGS_NAMES:data[wp-check-locked-posts][] can appear multiple times SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002710,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq heartbeat" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:data[wp_autosave][post_title],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:data[wp_autosave][content],\ ctl:ruleRemoveTargetById=942431;ARGS_NAMES:data[wp-refresh-post-lock][post_id],\ ctl:ruleRemoveTargetById=942431;ARGS_NAMES:data[wp-refresh-post-lock][lock],\ ctl:ruleRemoveTargetById=942431;ARGS_NAMES:data[wp-check-locked-posts][],\ ctl:ruleRemoveById=921180,\ ctl:ruleRemoveById=920272" # Edit menus SecRule REQUEST_FILENAME "@endsWith /wp-admin/nav-menus.php" \ "id:9002720,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=942460;ARGS:menu-name,\ ctl:ruleRemoveTargetById=941330;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=941340;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942200;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942260;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942330;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942340;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942430;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942431;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942460;ARGS:nav-menu-data" # Edit text widgets (can contain custom HTML) SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002730,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@rx ^(?:save-widget|update-widget)$" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[0][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[1][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[2][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[3][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[4][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[5][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[6][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[7][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[8][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[9][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[10][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[11][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[12][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[13][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[14][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[15][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[16][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[17][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[18][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[19][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[20][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[21][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[22][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[23][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[24][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[25][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[26][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[27][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[28][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[29][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[30][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[31][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[32][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[33][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[34][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[35][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[36][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[37][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[38][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[39][text]" # Reorder widgets SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002740,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq widgets-order" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-1],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-1],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-2],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-2],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-3],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-3],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-4],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-4],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-5],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-5],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-6],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-6],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-7],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-7]" # Create permalink sample for new post SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002750,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq sample-permalink" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:new_title" # Add external link to menu SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002760,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq add-menu-item" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:menu-item[-1][menu-item-url]" # Editor: Add Media, Insert Media, Insert into page SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002770,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:action "@streq send-attachment-to-editor" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:html" # # [ Options and Settings ] # # Change site URL SecRule REQUEST_FILENAME "@endsWith /wp-admin/options.php" \ "id:9002800,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:option_page "@streq general" \ "t:none,\ chain" SecRule &ARGS:option_page "@eq 1" \ "t:none,\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:home,\ ctl:ruleRemoveTargetById=931130;ARGS:siteurl" # Permalink settings # permalink_structure=/index.php/%year%/%monthnum%/%day%/%postname%/ SecRule REQUEST_FILENAME "@endsWith /wp-admin/options-permalink.php" \ "id:9002810,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=920230;ARGS:selection,\ ctl:ruleRemoveTargetById=920272;ARGS:selection,\ ctl:ruleRemoveTargetById=942431;ARGS:selection,\ ctl:ruleRemoveTargetById=920230;ARGS:permalink_structure,\ ctl:ruleRemoveTargetById=920272;ARGS:permalink_structure,\ ctl:ruleRemoveTargetById=942431;ARGS:permalink_structure,\ ctl:ruleRemoveTargetById=920272;REQUEST_BODY,\ ver:'OWASP_CRS/3.2.0'" # Comments blacklist and moderation list SecRule REQUEST_FILENAME "@endsWith /wp-admin/options.php" \ "id:9002820,\ phase:2,\ pass,\ t:none,\ nolog,\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule ARGS:option_page "@streq discussion" \ "t:none,\ chain" SecRule &ARGS:option_page "@eq 1" \ "t:none,\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:blacklist_keys,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:moderation_keys" # Posts/pages overview search SecRule REQUEST_FILENAME "@endsWith /wp-admin/edit.php" \ "id:9002830,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:s,\ ver:'OWASP_CRS/3.2.0'" # # [ Helpers ] # # /wp-admin/load-scripts.php?c=0&load%5B%5D=hoverIntent,common, # admin-bar,wp-ajax-response,jquery-color,wp-lists,quicktags, # jquery-query,admin-comments,svg-painter,heartbeat,&load%5B%5D= # wp-auth-check,wp-a11y,wplink,jquery-ui-core,jquery-ui-widget, # jquery-ui-position,jquery-ui-menu,jquery-ui-autocomplete&ver=4.6.1 # # /wp-admin/load-styles.php?c=0&dir=ltr&load%5B%5D=dashicons, # admin-bar,buttons,media-views,common,forms,admin-menu,dashboard, # list-tables,edit,revisions,media,themes,about,nav-menu&load%5B%5D= # s,widgets,site-icon,l10n,wp-auth-check&ver=4.6.1 # # /wp-admin/load-scripts.php?c=0&load%5B%5D=hoverIntent,common, # admin-bar,jquery-ui-widget,jquery-ui-position,wp-pointer, # wp-ajax-response,jquery-color,wp-lists,quicktags, # jqu&load%5B%5D=ery-query,admin-comments,jquery-ui-core, # jquery-ui-mouse,jquery-ui-sortable,postbox,dashboard,underscore, # customize-base,customize&load%5B%5D=-loader,thickbox,plugin-install, # wp-util,wp-a11y,updates,shortcode,media-upload,svg-painter, # jquery-ui-accordion&ver=3f9999390861a0133beda3ee8acf152e SecRule REQUEST_FILENAME "@rx /wp-admin/load-(?:scripts|styles)\.php$" \ "id:9002900,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveById=921180,\ ctl:ruleRemoveTargetById=920273;ARGS_NAMES:load[],\ ctl:ruleRemoveTargetById=942432;ARGS_NAMES:load[],\ ctl:ruleRemoveTargetById=942360;ARGS:load[],\ ctl:ruleRemoveTargetById=942430;ARGS:load[],\ ctl:ruleRemoveTargetById=942431;ARGS:load[],\ ctl:ruleRemoveTargetById=942432;ARGS:load[],\ ver:'OWASP_CRS/3.2.0'" SecMarker "END-WORDPRESS-ADMIN" SecMarker "END-WORDPRESS" </IfModule>
Test your site with a malicious URL, like this:
https://xn--1ca.se/hack.php?param=../../etc
https://xn--1ca.se/?q=%22%3E%3Cscript%3Ealert(1)%3C/script%3E%27
Here is a useful one-liner to find false positives from your own server
# cat error.log|grep ModSec|grep <your_ip>|grep -oP '(?<=\[id\s\")\w+'|sort|uniq