Core Rule Set: WordPress's ordinary requests pass by default (closes #235)
check / check (push) Successful in 4m43s
check / check (push) Successful in 4m43s
Add the ninth change: wordpress.conf switches off, per path and field, each rule that refused ordinary WordPress 7.1.4 requests. Add the recorded requests, a test at the defaults and reading bodies, and list WordPress in the README. Model: opus-5-5
This commit is contained in:
1 parent
aede434f6a
commit
650d4c0936
6 files changed
+1109
-18
No files matched your search
@@ -0,0 +1,223 @@
|
||||
# The ninth change: on WordPress's paths, some fields skip the rules that refused
|
||||
# ordinary WordPress requests there. Each exclusion runs with the request, before
|
||||
# the rules it switches off, so this file is loaded before the Core Rule Set's
|
||||
# rules. Each comment names a request the rule refused. An exclusion on a field
|
||||
# of a body applies only when the query has no parameter of that name, so it
|
||||
# matters only while SWW_WAF_BODY_LIMIT is set.
|
||||
|
||||
# WordPress takes a call to its REST API at any of four addresses:
|
||||
# /wp-json/wp/v2/posts/1
|
||||
# /index.php/wp-json/wp/v2/posts/1
|
||||
# /index.php?rest_route=/wp/v2/posts/1
|
||||
# /?rest_route=/wp/v2/posts/1
|
||||
# These two rules put the route, here /wp/v2/posts/1, in tx.rest_route for the
|
||||
# exclusions below. A call that names a route in both its path and its query
|
||||
# gets none of them, since WordPress follows the query.
|
||||
SecRule &ARGS_GET:rest_route "@eq 0" "id:900705,phase:1,pass,nolog,chain"
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:index\.php/)?wp-json(/.*)$" \
|
||||
"capture,setvar:tx.rest_route=%{tx.1}"
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:index\.php)?$" "id:900706,phase:1,pass,nolog,chain"
|
||||
SecRule ARGS_GET:rest_route "@rx ^(/.*)$" "capture,setvar:tx.rest_route=%{tx.1}"
|
||||
|
||||
# The block editor saves a post with POST and the header X-HTTP-Method-Override:
|
||||
# PUT, which the Core Rule Set refused (920450). So does saving a user's editor
|
||||
# preferences.
|
||||
SecRule TX:rest_route "@beginsWith /" \
|
||||
"id:900700,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=920450;REQUEST_HEADERS_NAMES:X-HTTP-Method-Override"
|
||||
|
||||
# The block editor and the site editor send HTML in the JSON field content, which
|
||||
# skips these rules when saving or autosaving a post, a page, a template or a
|
||||
# template part:
|
||||
# 930120: cat /etc/hosts
|
||||
# 932230: a code block with a shell pipeline and an SQL query
|
||||
# 932250: the same code block
|
||||
# 934100: console.log('ok')
|
||||
# 941100: <iframe src="..." onload="...">
|
||||
# 941110: <script>
|
||||
# 941120: onload=
|
||||
# 941160: <img src=
|
||||
# 941180: <!-- wp:paragraph -->, the comment that starts every block
|
||||
# 941390: console.log(
|
||||
# 942190: how to select a table from the catalog
|
||||
# 942270: how to select a table from the catalog
|
||||
SecRule TX:rest_route \
|
||||
"@rx ^/wp/v2/(?:(?:posts|pages)(?:/[0-9]+(?:/autosaves)?)?|template(?:s|-parts)(?:/[^/]+//[^/]+(?:/autosaves)?)?)$" \
|
||||
"id:900701,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:json.content "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=930120;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=932230;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=934100;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=941100;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=941110;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=941120;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=941160;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=941180;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=941390;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=942190;ARGS:json.content,\
|
||||
ctl:ruleRemoveTargetById=942270;ARGS:json.content"
|
||||
|
||||
# A reply to a comment from the list of comments, in content:
|
||||
# 932125: ls -la, in the reply's text
|
||||
# 932230: ls -la, in the reply's text
|
||||
# 932250: ls -la, in the reply's text
|
||||
SecRule REQUEST_FILENAME "@streq /wp-admin/admin-ajax.php" \
|
||||
"id:900702,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:content "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=932125;ARGS:content,\
|
||||
ctl:ruleRemoveTargetById=932230;ARGS:content,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:content"
|
||||
|
||||
# Saving a plugin's or a theme's file from its file editor sends the file in
|
||||
# newcontent, which skips these rules, each of which refused saving the plugin
|
||||
# Hello Dolly's hello.php. Some of them refused only the whole file:
|
||||
# 932140: if ( 'en_' !== substr(
|
||||
# 932235: the whole file
|
||||
# 933100: the whole file
|
||||
# 933160: if ( 'en_' !== substr(
|
||||
# 933210: $lyrics = explode(
|
||||
# 941100: <style type='text/css'>
|
||||
# 941160: <style type='text/css'>
|
||||
# 941190: the whole file
|
||||
# 942151: if ( 'en_' !== substr(
|
||||
# 942540: Dolly'll never go away again";
|
||||
SecRule REQUEST_FILENAME "@streq /wp-admin/admin-ajax.php" \
|
||||
"id:900703,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:newcontent "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=932140;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=932235;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=933100;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=933160;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=933210;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=941100;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=941160;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=941190;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=942151;ARGS:newcontent,\
|
||||
ctl:ruleRemoveTargetById=942540;ARGS:newcontent"
|
||||
|
||||
# Signing in, in pwd, where a password holds any characters:
|
||||
# 930120: a password ending in /etc/hosts
|
||||
SecRule REQUEST_FILENAME "@streq /wp-login.php" \
|
||||
"id:900704,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:pwd "@eq 0" "ctl:ruleRemoveTargetById=930120;ARGS:pwd"
|
||||
|
||||
# WordPress's searches for posts, media and plugins, and the later pages of a
|
||||
# search of the site, send the text searched for in s, which skips these rules
|
||||
# there:
|
||||
# 930120: .htaccess
|
||||
# 932120: powershell
|
||||
# 932250: ls -la
|
||||
# 932260: python3
|
||||
SecRule REQUEST_FILENAME \
|
||||
"@rx ^/(?:(?:index\.php/)?page/[0-9]+/?|index\.php|wp-admin/(?:edit|upload|plugin-install)\.php)?$" \
|
||||
"id:900707,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:s,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:s,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:s,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:s"
|
||||
|
||||
# The REST API's searches send it in search, on every route of WordPress's own
|
||||
# API, which skips the same rules there.
|
||||
SecRule TX:rest_route "@beginsWith /wp/v2/" \
|
||||
"id:900708,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:search,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:search,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:search,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:search"
|
||||
|
||||
# The plugin and theme file editors name the file open in file, which skips
|
||||
# these rules there:
|
||||
# 930120: akismet/views/config.php
|
||||
# 932120: install-script.sh
|
||||
# 932160: bin/install.sh
|
||||
# 932260: docker-compose.yml
|
||||
# 941180: document.write.js
|
||||
SecRule REQUEST_FILENAME "@rx ^/wp-admin/(?:plugin|theme)-editor\.php$" \
|
||||
"id:900709,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:file,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:file,\
|
||||
ctl:ruleRemoveTargetById=932160;ARGS:file,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:file,\
|
||||
ctl:ruleRemoveTargetById=941180;ARGS:file"
|
||||
|
||||
# The plugin file editor and the links to activate, deactivate and install a
|
||||
# plugin name it in plugin, which skips these rules there:
|
||||
# 932120: powershell-tools/powershell-tools.php
|
||||
# 932260: docker-helper/docker-helper.php
|
||||
SecRule REQUEST_FILENAME "@rx ^/wp-admin/(?:plugin-editor|plugins|update)\.php$" \
|
||||
"id:900710,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:plugin,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:plugin"
|
||||
|
||||
# The list pages of wp-admin send their own address in _wp_http_referer, so the
|
||||
# next search, filter or bulk action repeats the last search, which skips these
|
||||
# rules there:
|
||||
# 930120: .htaccess
|
||||
# 932120: powershell
|
||||
# 932235: python3
|
||||
# 932250: ls -la
|
||||
# 932260: python3
|
||||
# 932340: &ps, the end of the media list's own address
|
||||
SecRule REQUEST_FILENAME \
|
||||
"@rx ^/wp-admin/(?:edit|edit-comments|edit-tags|plugin-install|plugins|theme-install|themes|upload|users)\.php$" \
|
||||
"id:900711,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:_wp_http_referer,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:_wp_http_referer,\
|
||||
ctl:ruleRemoveTargetById=932235;ARGS:_wp_http_referer,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:_wp_http_referer,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:_wp_http_referer,\
|
||||
ctl:ruleRemoveTargetById=932340;ARGS:_wp_http_referer"
|
||||
|
||||
# The rules below refused the text searched for, or a name:
|
||||
# 932120: powershell
|
||||
# 932250: ls -la
|
||||
# 932260: python3
|
||||
# Each request skips them in the field that holds that text.
|
||||
|
||||
# wp-admin's searches of comments, users, plugins and tags, in s.
|
||||
SecRule REQUEST_FILENAME "@rx ^/wp-admin/(?:edit-comments|users|plugins|edit-tags)\.php$" \
|
||||
"id:900712,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:s,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:s,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:s"
|
||||
|
||||
# wp-admin's searches of themes and of the media library's grid, in search.
|
||||
SecRule REQUEST_FILENAME "@rx ^/wp-admin/(?:themes|theme-install|upload)\.php$" \
|
||||
"id:900713,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:search,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:search,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:search"
|
||||
|
||||
# The tag field of the classic editor, in q, and the search for a user to add,
|
||||
# in term.
|
||||
SecRule REQUEST_FILENAME "@streq /wp-admin/admin-ajax.php" \
|
||||
"id:900714,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:q,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:q,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:q,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:term,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:term,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:term"
|
||||
|
||||
# The REST API's search of the block directory, in term.
|
||||
SecRule TX:rest_route "@streq /wp/v2/block-directory/search" \
|
||||
"id:900715,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:term,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:term,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:term"
|
||||
|
||||
# A tag's address with the Plain permalink setting, and the link on a tag in the
|
||||
# list of posts, in tag.
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:index\.php|wp-admin/edit\.php)?$" \
|
||||
"id:900716,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:tag,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:tag,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:tag"
|
||||
|
||||
# The link on a category in the list of posts, in category_name.
|
||||
SecRule REQUEST_FILENAME "@streq /wp-admin/edit.php" \
|
||||
"id:900717,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:category_name,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:category_name,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:category_name"
|
||||
Reference in new issue
Block a user