check / check (push) Failing after 2m47s
Each app's fixes are one .conf file, whose first rule skips the rest unless Inspect sets tx.app_<name>, and one entry in apps. SWW_APPS names each hostname's apps. A hostname gets only its apps' fixes; while SWW_APPS is unset, every hostname gets every app's fixes. A hostname in SWW_APPS that is not a DNS name, such as *.example.com, stops the start. Unset, SWW_APPS is logged at start as null; set empty, as "". Model: opus-5-5
239 lines
15 KiB
Plaintext
239 lines
15 KiB
Plaintext
# Drupal's fixes: on Drupal's paths, some fields skip the rules that refused
|
|
# ordinary Drupal requests there. They are the fields where Drupal sends a
|
|
# search, a name, a file name or an address. 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 a 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. The
|
|
# exclusions above the comment "The fields below are in bodies" also cover a
|
|
# body field of the same name whatever the query holds, and only those below it
|
|
# need a query without that name.
|
|
#
|
|
# Each path may start with a language prefix, such as /fr in
|
|
# /fr/admin/content. The prefix is two or three letters, then optionally a
|
|
# hyphen and more letters, as in /pt-br.
|
|
#
|
|
# Four rules read a search or a name as a command or a system file:
|
|
# 930120: .htaccess
|
|
# 932120: powershell
|
|
# 932250: ls -la
|
|
# 932260: python3
|
|
# Each query exclusion below removes these four from its fields, with two
|
|
# exceptions. Rule 900806 removes only 930120 and 932120 from url. Two more
|
|
# rules misfire on destination, the address of a page of results, so
|
|
# destination alone skips them too:
|
|
# 932230: ls -la
|
|
# 932235: python3
|
|
|
|
# Unless SWW_APPS lists drupal for the request's hostname, every rule below is
|
|
# skipped. Inspect sets tx.app_drupal when it does.
|
|
# The skip reaches only phase 1, so every rule in this file must be phase 1.
|
|
SecRule &TX:app_drupal "@eq 0" \
|
|
"id:900790,phase:1,pass,nolog,skipAfter:END_DRUPAL"
|
|
|
|
# Every admin page's filters and autocompletes, and the page to return to:
|
|
# title: /admin/content?title=python3
|
|
# name: /admin/content/media?name=python3
|
|
# user: /admin/people?user=python3
|
|
# filename, filemime: /admin/content/files?filename=python3
|
|
# info: /admin/content/block?info=python3
|
|
# subject, author_name: /admin/content/comment?subject=python3
|
|
# search: /admin/config/search/path?search=python3
|
|
# q: /admin/views/ajax/autocomplete/tag?q=python3
|
|
# destination: /admin/content?destination=/admin/content%3Ftitle%3Dpython3
|
|
SecRule REQUEST_FILENAME "@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/admin(?:/|$)" \
|
|
"id:900800,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:/^(?:title|name|user|filename|filemime|info|subject|author_name|search|q|destination)$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:title|name|user|filename|filemime|info|subject|author_name|search|q|destination)$/,\
|
|
ctl:ruleRemoveTargetById=932230;ARGS:destination,\
|
|
ctl:ruleRemoveTargetById=932235;ARGS:destination,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:title|name|user|filename|filemime|info|subject|author_name|search|q|destination)$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:title|name|user|filename|filemime|info|subject|author_name|search|q|destination)$/"
|
|
|
|
# The page to return to, on the other pages Drupal links to with one, such as
|
|
# /node/1/edit?destination=/search/node%3Fkeys%3Dpython3,
|
|
# /node/2/revisions/3/revert?destination=/admin/content%3Ftitle%3Dpython3 and
|
|
# /big_pipe/no-js?destination=/admin/content%3Ftitle%3Dpython3.
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/(?:node/(?:add/[^/]+|[0-9]+/[a-z]+|[0-9]+/revisions/[0-9]+/(?:revert|delete))|comment/[0-9]+/[a-z]+|media/(?:add/[^/]+|[0-9]+/[a-z]+)|taxonomy/term/[0-9]+/[a-z]+|user/[^/]+(?:/[a-z]+)?|block/add/[^/]+|big_pipe/no-js)$" \
|
|
"id:900801,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:destination,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:destination,\
|
|
ctl:ruleRemoveTargetById=932230;ARGS:destination,\
|
|
ctl:ruleRemoveTargetById=932235;ARGS:destination,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:destination,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:destination"
|
|
|
|
# The text searched for on the search pages: /search/node?keys=python3.
|
|
SecRule REQUEST_FILENAME "@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/search(?:/|$)" \
|
|
"id:900802,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:keys,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:keys,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:keys,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:keys"
|
|
|
|
# What is typed into a field that autocompletes a tag, a user, a link in the
|
|
# rich text editor or a block's category:
|
|
# /entity_reference_autocomplete/taxonomy_term/default/KEY?q=python3
|
|
# /ckeditor5/basic_html/entity-link-suggestions?q=python3
|
|
# /block-category/autocomplete?q=python3
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/(?:entity_reference_autocomplete/|ckeditor5/[^/]+/entity-link-suggestions$|block-category/autocomplete$)" \
|
|
"id:900803,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:q"
|
|
|
|
# The values a JSON:API client filters by, in fields named after what they
|
|
# filter: /jsonapi/node/article?filter[title]=python3 and
|
|
# filter[f][condition][value]=python3.
|
|
SecRule REQUEST_FILENAME "@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/jsonapi/" \
|
|
"id:900804,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:/^filter\[/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^filter\[/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^filter\[/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^filter\[/"
|
|
|
|
# A name, in the query or a body: the account whose password is reset, and
|
|
# the media library's filter by name:
|
|
# /user/password?name=python3
|
|
# /media-library?media_library_opener_id=...&name=python3
|
|
# /views/ajax?view_name=media_library&name=python3
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/(?:user/password|media-library|views/ajax)$" \
|
|
"id:900805,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:name"
|
|
|
|
# The address of a remote video shown in a page:
|
|
# 930120: /media/oembed?url=https%3A%2F%2Fvimeo.com%2Fchannels%2F.htaccess
|
|
# 932120: /media/oembed?url=https%3A%2F%2Fvimeo.com%2Fchannels%2Fpowershell
|
|
SecRule REQUEST_FILENAME "@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/media/oembed$" \
|
|
"id:900806,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:url,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:url"
|
|
|
|
# The fields below are in bodies. Saving content sends its title, summary, tags,
|
|
# address, revision note, comment subject, media name and image text, which
|
|
# skip the same four rules there. A title such as "python3, ls -la and .htaccess"
|
|
# refused saving a node.
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/(?:node/(?:add/[^/]+|[0-9]+/edit)|comment/(?:reply/[^/]+/[0-9]+/[^/]+(?:/[0-9]+)?|[0-9]+/edit)|media/(?:add/[^/]+|[0-9]+/edit))$" \
|
|
"id:900810,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:title|subject|name|body|revision_log|path|field_tags|field_)/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:(?:title|subject|name|revision_log|revision_log_message)\[0\]\[value\]|body\[0\]\[summary\]|path\[0\]\[alias\]|field_tags\[target_id\]|field_[a-z0-9_]+\[0\]\[(?:alt|title)\])$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:(?:title|subject|name|revision_log|revision_log_message)\[0\]\[value\]|body\[0\]\[summary\]|path\[0\]\[alias\]|field_tags\[target_id\]|field_[a-z0-9_]+\[0\]\[(?:alt|title)\])$/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:(?:title|subject|name|revision_log|revision_log_message)\[0\]\[value\]|body\[0\]\[summary\]|path\[0\]\[alias\]|field_tags\[target_id\]|field_[a-z0-9_]+\[0\]\[(?:alt|title)\])$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:(?:title|subject|name|revision_log|revision_log_message)\[0\]\[value\]|body\[0\]\[summary\]|path\[0\]\[alias\]|field_tags\[target_id\]|field_[a-z0-9_]+\[0\]\[(?:alt|title)\])$/"
|
|
|
|
# The rich text editor sends HTML in body and comment_body. Each of these rules
|
|
# refused saving a node or a comment whose HTML held an image and a code block
|
|
# with a shell script, an SQL query and JavaScript, so they skip those fields:
|
|
# 930120, 932120, 932125, 932140, 932160, 932230, 932235, 932250, 932260,
|
|
# 934100, 941160, 941390, 942170 and 942230.
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/(?:node/(?:add/[^/]+|[0-9]+/edit)|comment/(?:reply/[^/]+/[0-9]+/[^/]+(?:/[0-9]+)?|[0-9]+/edit))$" \
|
|
"id:900811,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:comment_)?body\[/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932125;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932140;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932230;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932235;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=941160;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=941390;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=942170;ARGS:/^(?:comment_)?body\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=942230;ARGS:/^(?:comment_)?body\[0\]\[value\]$/"
|
|
|
|
# A JSON:API client saving a node or a comment sends the same HTML in the
|
|
# JSON field body.value or comment_body.value, which skips the rules above. A
|
|
# title, summary, subject, name, revision note, block description or tag
|
|
# description beside it skips 930120, 932120, 932250 and 932260. A tag named
|
|
# python3 refused saving it.
|
|
SecRule REQUEST_FILENAME "@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/jsonapi/" \
|
|
"id:900812,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^json\.data\.attributes\./ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.data\.attributes\.(?:title|subject|name|revision_log|info|description\.value|body\.summary|(?:comment_)?body\.value)$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.data\.attributes\.(?:title|subject|name|revision_log|info|description\.value|body\.summary|(?:comment_)?body\.value)$/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.data\.attributes\.(?:title|subject|name|revision_log|info|description\.value|body\.summary|(?:comment_)?body\.value)$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.data\.attributes\.(?:title|subject|name|revision_log|info|description\.value|body\.summary|(?:comment_)?body\.value)$/,\
|
|
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=932140;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=941160;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=941390;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=942170;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/,\
|
|
ctl:ruleRemoveTargetById=942230;ARGS:/^json\.data\.attributes\.(?:comment_)?body\.value$/"
|
|
|
|
# Signing in, in name and pass or the JSON fields of the same names. A
|
|
# password holds any characters:
|
|
# 930120: a password ending in /etc/hosts, or a name of .htaccess
|
|
# 932120: a password or a name of powershell
|
|
# 932250: a password or a name of ls -la
|
|
# 932260: a password or a name starting with python3
|
|
SecRule REQUEST_FILENAME "@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/user/login$" \
|
|
"id:900813,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:json\.)?(?:name|pass)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:json\.)?(?:name|pass)$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:json\.)?(?:name|pass)$/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:json\.)?(?:name|pass)$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:json\.)?(?:name|pass)$/"
|
|
|
|
# A person's name and email address, when signing up, when editing an
|
|
# account and when commenting without an account. A name of python3 refused
|
|
# signing up, and python3@example.com refused saving an account. An address
|
|
# keeps 932250, which no recorded address set off.
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/(?:user/register|user/[0-9]+/edit|comment/reply/[^/]+/[0-9]+/[^/]+(?:/[0-9]+)?)$" \
|
|
"id:900814,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:name|mail)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:name|mail)$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:name|mail)$/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:name|mail)$/"
|
|
|
|
# Saving a tag, a custom block or a contact message sends its name,
|
|
# description, block description, body, subject or message, which skip the
|
|
# same four rules. A tag named python3 refused saving it.
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/(?:admin/structure/taxonomy/manage/[^/]+/add|taxonomy/term/[0-9]+/edit|block/add/[^/]+|admin/content/block/[0-9]+|contact(?:/[^/]+)?|user/[0-9]+/contact)$" \
|
|
"id:900815,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:name|description|info|body|subject|message)\[/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:name|description|info|body|subject|message)\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:name|description|info|body|subject|message)\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:name|description|info|body|subject|message)\[0\]\[value\]$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:name|description|info|body|subject|message)\[0\]\[value\]$/"
|
|
|
|
# A client saving a node in Drupal's JSON format sends its title in the JSON
|
|
# field title.0.value: PATCH /node/2?_format=json with a title of python3.
|
|
SecRule REQUEST_FILENAME "@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/node/[0-9]+$" \
|
|
"id:900816,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^json\.title\./ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:json.title.0.value,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:json.title.0.value,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:json.title.0.value,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.title.0.value"
|
|
|
|
# A client resetting a password in Drupal's JSON format sends the account in
|
|
# the JSON field name: POST /user/password?_format=json with a name of python3.
|
|
SecRule REQUEST_FILENAME "@rx ^(?:/[a-z]{2,3}(?:-[a-z]+)?)?/user/password$" \
|
|
"id:900817,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:json.name "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:json.name,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:json.name,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:json.name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.name"
|
|
|
|
SecMarker END_DRUPAL
|