Core Rule Set: the package registries' searches of gitea and Forgejo pass (closes #354)
check / check (push) Waiting to run
check / check (push) Waiting to run
Recorded from gitea 1.27.3 and Forgejo 17.0.1 with each registry's own client, and curl for the requests no client sends, with python3, powershell, ls -la, .htaccess, file names and plain words. q on the Cargo, Chef, Composer and Conan searches and NuGet's search service joins 900603. 900605 lets /bin/sh through on Composer and Conan. New: 900609 for npm's text; 900611, in phase 2, lets one q shaped as a Conan reference with no +, */ or --, such as zlib/*, skip 942100 if 942100 passes it with each /* comment read as a space; 900612 for NuGet's Search(), Packages() and their counts: searchTerm, $filter, and the names $filter, $orderby and $top for 942290. Model: opus-5-5 Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
This commit was merged in pull request #378.
This commit is contained in:
1 parent
b84a33fb57
commit
50c50bfcae
5 files changed
+476
-21
No files matched your search
@@ -172,11 +172,13 @@ SecRule REQUEST_FILENAME "@rx ^/(?:explore/repos|user/search_candidates|\
|
||||
|
||||
# A branch, tag or package name can hold a slash, as feat/docker-support and
|
||||
# npm's @scope/name do. So q on a repository's branches, tags and packages
|
||||
# pages, on an owner's packages page, on the admin page of packages and on the
|
||||
# API's search of packages also skips this rule:
|
||||
# pages, on an owner's packages page, on the admin page of packages, on the
|
||||
# API's search of packages and on the Composer and Conan registries' searches
|
||||
# also skips this rule:
|
||||
# 932160: /bin/sh
|
||||
SecRule REQUEST_FILENAME "@rx ^/(?:[^/]+/[^/]+/(?:branches|tags|packages)|\
|
||||
admin/packages|api/v1/packages/[^/]+)$" \
|
||||
admin/packages|api/v1/packages/[^/]+|\
|
||||
api/packages/[^/]+/(?:composer/search\.json|conan/v[12]/conans/search))$" \
|
||||
"id:900605,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932160;ARGS:q"
|
||||
|
||||
# gitea's other searches send a name or a few words in q too, which skips only
|
||||
@@ -191,6 +193,8 @@ SecRule REQUEST_FILENAME "@rx ^/(?:[^/]+/[^/]+/(?:branches|tags|packages)|\
|
||||
# - the lists of users and organisations;
|
||||
# - the API's searches of users, of topics, of an organisation's teams and of
|
||||
# emails;
|
||||
# - the searches of the Cargo, Chef, Composer and Conan registries, and the
|
||||
# NuGet registry's search service;
|
||||
# - the list of repositories a user watches;
|
||||
# - an organisation's milestones of one team, and its search for teams;
|
||||
# - the milestones of a repository or an organisation, and the projects of a
|
||||
@@ -210,6 +214,8 @@ SecRule REQUEST_FILENAME "@rx ^/(?:repo/search|notifications/watching|\
|
||||
explore/(?:users|organizations)|\
|
||||
api/v1/(?:users/search|topics/search|orgs/[^/]+/teams/search|\
|
||||
admin/emails/search)|\
|
||||
api/packages/[^/]+/(?:cargo/api/v1/crates|chef/api/v1/(?:search|cookbooks)|\
|
||||
composer/search\.json|conan/v[12]/conans/search|nuget/query)|\
|
||||
org/[^/]+/(?:milestones/[^/]+|teams/-/search)|\
|
||||
[^/]+/-/packages/[^/]+/.+/versions|\
|
||||
[^/]+/[^/]+/(?:(?:issues|pulls)/posters|issues/suggestions|milestones|\
|
||||
@@ -246,6 +252,76 @@ SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/milestones$" \
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:name,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:name"
|
||||
|
||||
# The npm registry's search sends its words in text, which skips these rules
|
||||
# there:
|
||||
# 930120: .htaccess
|
||||
# 932120: powershell
|
||||
# 932160: /bin/sh, as an npm name such as @alice/tools-cli holds a slash
|
||||
# 932250: ls -la
|
||||
# 932260: python3
|
||||
SecRule REQUEST_FILENAME "@rx ^/api/packages/[^/]+/npm/-/v1/search$" \
|
||||
"id:900609,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:text,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:text,\
|
||||
ctl:ruleRemoveTargetById=932160;ARGS:text,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:text,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:text"
|
||||
|
||||
# A Conan search takes a pattern such as zlib/*, which the rule for SQL
|
||||
# injection (942100) refused in q. q skips that rule only when the request has
|
||||
# one q, in the query string or the body, with the shape of a Conan reference.
|
||||
# A reference is a name, then optionally / and a version, then optionally @
|
||||
# and a user, then optionally / and a channel. Each part is made of letters,
|
||||
# digits, _, ., - and *. A part holds no +, since 942100 reads + as a space.
|
||||
# q must also hold no */, which ends an SQL comment, and no --, which starts
|
||||
# one. Last, 942100 must find no SQL injection in q once each comment that /*
|
||||
# starts, an unclosed one included, is replaced by a space. So zlib/* passes,
|
||||
# and SQL injection such as these stays refused:
|
||||
# 1' OR '1'='1
|
||||
# 1/**/or/**/1
|
||||
# 1/*@*/or-1
|
||||
# 1+or+1--
|
||||
# 1-or-1--
|
||||
# x/1.or.1
|
||||
# 1.having.1
|
||||
# This rule is in phase 2, because a phase 1 rule runs before the body is read
|
||||
# and cannot see a q there. It checks tx.app_gitea, since the skip above does
|
||||
# not reach phase 2.
|
||||
SecRule REQUEST_FILENAME "@rx ^/api/packages/[^/]+/conan/v[12]/conans/search$" \
|
||||
"id:900611,phase:2,pass,nolog,chain"
|
||||
SecRule &TX:app_gitea "@eq 1" "chain"
|
||||
SecRule &ARGS:q "@eq 1" "chain"
|
||||
SecRule ARGS:q "!@contains */" "chain"
|
||||
SecRule ARGS:q "!@contains --" "chain"
|
||||
SecRule ARGS:q "!@detectSQLi" "t:none,t:replaceComments,chain"
|
||||
SecRule ARGS:q "@rx ^[\w.*-]+(?:/[\w.*-]+)?(?:@[\w.*-]+(?:/[\w.*-]+)?)?$" \
|
||||
"ctl:ruleRemoveTargetById=942100;ARGS:q"
|
||||
|
||||
# The NuGet v2 API's searches, Search() and Packages(), send their words in
|
||||
# searchTerm, or in $filter as an expression such as
|
||||
# tolower(Id) eq 'python3'. Search()/$count and Packages()/$count count a
|
||||
# search's results and read the same fields. searchTerm skips these rules:
|
||||
# 930120: .htaccess
|
||||
# 932120: powershell
|
||||
# 932250: ls -la
|
||||
# 932260: python3
|
||||
# $filter skips these:
|
||||
# 930120: .htaccess
|
||||
# 932120: powershell
|
||||
# The names $filter, $orderby and $top skip the rule for MongoDB operators
|
||||
# (942290), which refused every such search.
|
||||
SecRule REQUEST_FILENAME "@rx ^/api/packages/[^/]+/nuget/(?:Search|Packages)\(\)(?:/\$count)?$" \
|
||||
"id:900612,phase:1,pass,nolog,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:searchTerm,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:searchTerm,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:searchTerm,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:searchTerm,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:$filter,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:$filter,\
|
||||
ctl:ruleRemoveTargetById=942290;ARGS_NAMES:$filter,\
|
||||
ctl:ruleRemoveTargetById=942290;ARGS_NAMES:$orderby,\
|
||||
ctl:ruleRemoveTargetById=942290;ARGS_NAMES:$top"
|
||||
|
||||
# The repositories on a user's or an organisation's page are searched with q
|
||||
# too. Their path has one segment, so q skips these rules on every path of one
|
||||
# segment, other apps' pages such as /index.php included:
|
||||
|
||||
Reference in new issue
Block a user