Core Rule Set: MediaWiki's ordinary requests pass by default (closes #237)
check / check (push) Successful in 5m49s
check / check (push) Successful in 5m49s
Adds mediawiki.conf, the eleventh change: on MediaWiki's paths, the fields that carry a search, a title, a name, a file name or an address skip the four rules that read them as commands or system files, and the wikitext fields skip the rules that refused saving a page. The reasons on the admin pages skip only 930120 and 932120. /index.php counts as MediaWiki's only with a page title in its query or after its path, since WordPress serves it too. The requests recorded from MediaWiki 1.46.2, with and without short URLs and on the admin pages, pass at the defaults and while bodies are read. The app tests share the check of recorded requests and the list of hard values. Model: opus-5-5
This commit is contained in:
1 parent
c0313f7b27
commit
68a1e42d0c
8 files changed
+1227
-49
No files matched your search
@@ -0,0 +1,176 @@
|
||||
# The eleventh change: on MediaWiki's paths, some fields skip the rules that
|
||||
# refused ordinary MediaWiki requests there. They are the fields where MediaWiki
|
||||
# sends a search, a title, a name, a file name, an address, a summary or a
|
||||
# reason, and the fields that hold wikitext. 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. MediaWiki's
|
||||
# paths are matched at the site root and under /w/.
|
||||
#
|
||||
# WordPress serves /index.php too. So /index.php counts as MediaWiki's only
|
||||
# with a page title, in the query or after the path:
|
||||
# /index.php?title=Main_Page
|
||||
# /index.php/Main_Page, where a wiki without short URLs serves its pages
|
||||
# Pages under /wiki/ need neither.
|
||||
#
|
||||
# Four rules read a search, a title or a name as a command or a system file.
|
||||
# Each exclusion below for such a field removes these four, and only these:
|
||||
# 930120: .htaccess
|
||||
# 932120: powershell
|
||||
# 932250: ls -la
|
||||
# 932260: python3
|
||||
|
||||
# The pages and their titles, the searches, and the special pages' fields
|
||||
# for a page, a user, a file or an address:
|
||||
# title: /index.php?title=Python3_notes&action=history
|
||||
# search: /index.php?search=python3&title=Special:Search
|
||||
# target: /wiki/Special:WhatLinksHere?target=Python3+notes
|
||||
# page, user: /wiki/Special:Log?user=Admin&page=Python3+notes
|
||||
# username: /wiki/Special:ListUsers?username=python3
|
||||
# from, to: /wiki/Special:AllPages?from=python3
|
||||
# prefix: /wiki/Special:PrefixIndex?prefix=python3
|
||||
# returnto, returntoquery: /wiki/Special:UserLogin?returnto=Python3_notes
|
||||
# ilsearch: /wiki/Special:ListFiles?ilsearch=python3
|
||||
# filename: /wiki/Special:FileDuplicateSearch?filename=Pic+python3.png
|
||||
# wpDestFile: /wiki/Special:Upload?wpDestFile=Pic+python3.png
|
||||
# wpTarget: /wiki/Special:BlockList?wpTarget=Python3, and blocking or
|
||||
# unblocking the user Python3
|
||||
# Uploaded files' names skip 932180, as on the API below.
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php(?:$|/.)|^/wiki/" \
|
||||
"id:900900,phase:1,pass,nolog,chain"
|
||||
SecRule REQUEST_FILENAME|ARGS_GET_NAMES "@rx ^/(?:w/)?index\.php/.|^/wiki/|^title$" \
|
||||
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:title|search|target|page|user|username|from|to|prefix|returnto|returntoquery|ilsearch|filename|wpdestfile|wptarget)$/,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:title|search|target|page|user|username|from|to|prefix|returnto|returntoquery|ilsearch|filename|wpdestfile|wptarget)$/,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:title|search|target|page|user|username|from|to|prefix|returnto|returntoquery|ilsearch|filename|wpdestfile|wptarget)$/,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:title|search|target|page|user|username|from|to|prefix|returnto|returntoquery|ilsearch|filename|wpdestfile|wptarget)$/,\
|
||||
ctl:ruleRemoveTargetById=932180;FILES"
|
||||
|
||||
# The API's searches, titles, names and file names, in the query or the body,
|
||||
# with or without the g of a generator:
|
||||
# search: /api.php?action=opensearch&search=python3
|
||||
# srsearch, pssearch: /api.php?action=query&list=search&srsearch=python3
|
||||
# titles, title, page: /api.php?action=parse&page=Python3+notes
|
||||
# from, to: moving a page, from=Python3+notes&to=Ls+-la+notes
|
||||
# apfrom, apto, apprefix: /api.php?action=query&list=allpages&apfrom=python3
|
||||
# aifrom, aiprefix: /api.php?action=query&list=allimages&aiprefix=python3
|
||||
# aufrom, auprefix: /api.php?action=query&list=allusers&auprefix=python3
|
||||
# bltitle: /api.php?action=query&list=backlinks&bltitle=Python3+notes
|
||||
# euquery: /api.php?action=query&list=exturlusage&euquery=example.com/python3
|
||||
# ucuser: /api.php?action=query&list=usercontribs&ucuser=python3
|
||||
# bkusers: /api.php?action=query&list=blocks&bkusers=Python3
|
||||
# user: blocking, unblocking or changing the groups of a user, user=Python3
|
||||
# summary, sectiontitle: saving a page, summary=Notes+on+python3
|
||||
# filename, comment: uploading a file, filename=Api+python3.png
|
||||
# reason: moving or deleting a page, reason=python3
|
||||
# lgname, lgpassword, username, password: signing in, password=python3
|
||||
# Uploaded files' names skip 932180, which refused uploading
|
||||
# "Api .htaccess.png" as a server's own file. Coraza keeps these names without
|
||||
# the field each came in. MediaWiki refuses a file whose extension it does not
|
||||
# allow.
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?api\.php$" \
|
||||
"id:900901,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:/^g?(?:search|srsearch|pssearch|titles?|page|from|to|apfrom|apto|apprefix|aifrom|aiprefix|aufrom|auprefix|bltitle|euquery|ucuser|bkusers|user|summary|sectiontitle|filename|comment|reason|lgname|lgpassword|username|password)$/,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:/^g?(?:search|srsearch|pssearch|titles?|page|from|to|apfrom|apto|apprefix|aifrom|aiprefix|aufrom|auprefix|bltitle|euquery|ucuser|bkusers|user|summary|sectiontitle|filename|comment|reason|lgname|lgpassword|username|password)$/,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:/^g?(?:search|srsearch|pssearch|titles?|page|from|to|apfrom|apto|apprefix|aifrom|aiprefix|aufrom|auprefix|bltitle|euquery|ucuser|bkusers|user|summary|sectiontitle|filename|comment|reason|lgname|lgpassword|username|password)$/,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:/^g?(?:search|srsearch|pssearch|titles?|page|from|to|apfrom|apto|apprefix|aifrom|aiprefix|aufrom|auprefix|bltitle|euquery|ucuser|bkusers|user|summary|sectiontitle|filename|comment|reason|lgname|lgpassword|username|password)$/,\
|
||||
ctl:ruleRemoveTargetById=932180;FILES"
|
||||
|
||||
# The search box's suggestions and the search through the REST API:
|
||||
# /rest.php/v1/search/title?q=python3.
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?rest\.php/" \
|
||||
"id:900902,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 names of the scripts and styles a page loads, which 930120 read as a
|
||||
# system file: /load.php?modules=jquery,moment,oojs,...|mediawiki.storage.
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?load\.php$" \
|
||||
"id:900903,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:modules"
|
||||
|
||||
# The fields below are in bodies, and skip the four rules there:
|
||||
# wpSummary: saving a page, "Notes on python3, ls -la and .htaccess"
|
||||
# wpUploadDescription: uploading a file
|
||||
# wpName, wpPassword: signing in
|
||||
# wpOldTitle, wpNewTitleMain, wpReason: moving a page to "Python3 notes"
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php(?:$|/.)|^/wiki/" \
|
||||
"id:900910,phase:1,pass,nolog,chain"
|
||||
SecRule REQUEST_FILENAME|ARGS_GET_NAMES "@rx ^/(?:w/)?index\.php/.|^/wiki/|^title$" "chain"
|
||||
SecRule &ARGS_GET:/^wp(?:summary|uploaddescription|name|password|oldtitle|newtitlemain|reason)$/ "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=930120;ARGS:/^wp(?:summary|uploaddescription|name|password|oldtitle|newtitlemain|reason)$/,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:/^wp(?:summary|uploaddescription|name|password|oldtitle|newtitlemain|reason)$/,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:/^wp(?:summary|uploaddescription|name|password|oldtitle|newtitlemain|reason)$/,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:/^wp(?:summary|uploaddescription|name|password|oldtitle|newtitlemain|reason)$/"
|
||||
|
||||
# Wikitext: the edit form sends it in wpTextbox1, the API in text, appendtext
|
||||
# or prependtext, and the REST API in the JSON field source. Each of these
|
||||
# rules refused saving or previewing a page whose wikitext held a template, a
|
||||
# table and code blocks with a shell script, an SQL query and JavaScript, so
|
||||
# they skip those fields: 930120, 932120, 932125, 932160, 932230, 932235,
|
||||
# 932250, 932260, 941180, 941390, 942190 and 942270.
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php(?:$|/.)|^/wiki/" \
|
||||
"id:900911,phase:1,pass,nolog,chain"
|
||||
SecRule REQUEST_FILENAME|ARGS_GET_NAMES "@rx ^/(?:w/)?index\.php/.|^/wiki/|^title$" "chain"
|
||||
SecRule &ARGS_GET:wpTextbox1 "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=930120;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=932125;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=932160;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=932230;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=932235;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=941180;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=941390;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=942190;ARGS:wpTextbox1,\
|
||||
ctl:ruleRemoveTargetById=942270;ARGS:wpTextbox1"
|
||||
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?api\.php$" \
|
||||
"id:900912,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:/^(?:text|appendtext|prependtext)$/ "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=932125;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=932160;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=932230;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=932235;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=941180;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=941390;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=942190;ARGS:/^(?:text|appendtext|prependtext)$/,\
|
||||
ctl:ruleRemoveTargetById=942270;ARGS:/^(?:text|appendtext|prependtext)$/"
|
||||
|
||||
# A REST API client saving a page sends its wikitext in source, which skips
|
||||
# the rules above, and its summary in comment, which skips the four rules.
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?rest\.php/" \
|
||||
"id:900913,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:/^json\.(?:source|comment)$/ "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:source|comment)$/,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:source|comment)$/,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:source|comment)$/,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:source|comment)$/,\
|
||||
ctl:ruleRemoveTargetById=932125;ARGS:json.source,\
|
||||
ctl:ruleRemoveTargetById=932160;ARGS:json.source,\
|
||||
ctl:ruleRemoveTargetById=932230;ARGS:json.source,\
|
||||
ctl:ruleRemoveTargetById=932235;ARGS:json.source,\
|
||||
ctl:ruleRemoveTargetById=941180;ARGS:json.source,\
|
||||
ctl:ruleRemoveTargetById=941390;ARGS:json.source,\
|
||||
ctl:ruleRemoveTargetById=942190;ARGS:json.source,\
|
||||
ctl:ruleRemoveTargetById=942270;ARGS:json.source"
|
||||
|
||||
# The reasons on the admin pages are in bodies. They skip only 930120 and
|
||||
# 932120, which refused "Spamming links to .htaccess guides" and the same with
|
||||
# powershell:
|
||||
# wpReason-other: blocking a user
|
||||
# user-reason: changing a user's groups
|
||||
# mwProtect-reason: protecting a page
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php(?:$|/.)|^/wiki/" \
|
||||
"id:900914,phase:1,pass,nolog,chain"
|
||||
SecRule REQUEST_FILENAME|ARGS_GET_NAMES "@rx ^/(?:w/)?index\.php/.|^/wiki/|^title$" "chain"
|
||||
SecRule &ARGS_GET:/^(?:wpreason-other|user-reason|mwprotect-reason)$/ "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:wpreason-other|user-reason|mwprotect-reason)$/,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:wpreason-other|user-reason|mwprotect-reason)$/"
|
||||
Reference in new issue
Block a user