# The tenth change: 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 # 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"