From 4fbb50c41754356f4a3d5fcdb68c43ace39c4c64 Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 10 Nov 2026 22:21:57 +0000 Subject: [PATCH] Core Rule Set: MediaWiki's password fields pass on a wiki in any language (closes #299) A wiki in another language posts its sign-up, password change and new-password forms to its own names for the special pages, such as Spezial:Benutzerkonto_anlegen. So password and retype no longer match on the English page name. They skip the rules when authAction names the form that sends them: change, create or login-continue. MediaWiki sends the same value in every language. The page must still be MediaWiki's, with a namespace in its title, so another app's paths under /index.php/ keep every rule. The two rules move to phase 2 to read the body. Adds requests recorded from a German MediaWiki 1.46.2. Model: opus-5-5 --- SPEC.md | 19 ++++-- internal/coreruleset/mediawiki.conf | 41 ++++++----- internal/coreruleset/mediawiki_test.go | 68 +++++++++++++------ .../testdata/mediawiki-requests.txt | 11 +++ 4 files changed, 96 insertions(+), 43 deletions(-) diff --git a/SPEC.md b/SPEC.md index 76f716a..7695c7b 100644 --- a/SPEC.md +++ b/SPEC.md @@ -1139,10 +1139,12 @@ The changes hold in front of every app, and no setting undoes them: - `source` in the JSON body of `/rest.php/`. - The passwords when signing in, signing up and changing a password: - `wpPassword` on MediaWiki's pages; - - `password` and `retype` on `Special:ChangeCredentials`; - - `retype` on `Special:CreateAccount`; - - `retype` on `Special:UserLogin`, where a password reset sets the new - password; + - `password` and `retype` on `Special:ChangeCredentials`, whose form + sends `authAction=change`; + - `retype` on `Special:CreateAccount`, whose form sends + `authAction=create`; + - `retype` on `Special:UserLogin`, where a password reset or an expired + password sets the new password with `authAction=login-continue`; - `lgpassword`, `password` and `retype` on `/api.php`. They skip each rule that random passwords set off: @@ -1156,9 +1158,12 @@ The changes hold in front of every app, and no setting undoes them: `` sent as a password reach MediaWiki; `` and `javascript:alert(1)` are still refused. - The path must name the special page, or be `/index.php` with a `title` - that names it. Other apps use `password` and `retype` too, so on any - other page those two fields keep every rule. + Other apps use `password` and `retype` too. So those two fields skip + these rules only when `authAction` names the form that sends them. The + page's name does not count, because a wiki in another language posts + these forms to its own names, such as `Spezial:Benutzerkonto_anlegen`. + The page's title must have a namespace, such as `Special:`. The title is + after the path, or in the `title` of `/index.php`. These body exclusions matter only while `SWW_WAF_BODY_LIMIT` is set. None applies when the query has a parameter of the same name. diff --git a/internal/coreruleset/mediawiki.conf b/internal/coreruleset/mediawiki.conf index 10fc915..e0f49ba 100644 --- a/internal/coreruleset/mediawiki.conf +++ b/internal/coreruleset/mediawiki.conf @@ -194,18 +194,26 @@ SecRule REQUEST_FILENAME "@rx ^/(?:w/)?api\.php$" \ ctl:ruleRemoveTargetById=944150;ARGS:/^(?:lgpassword|password|retype)$/" # Other apps use the names password and retype too, and these exclusions apply -# in front of every app. So these two fields skip the same rules only on the -# pages that take them: -# password, retype: changing the password at Special:ChangeCredentials -# retype: signing up at Special:CreateAccount -# retype: setting the new password after a reset at Special:UserLogin -# The path names the page, or the path is /index.php and title names it. A title -# on any other path does not count, so another app's paths under /index.php/ -# keep every rule. -SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php$|^/(?:(?:w/)?index\.php|wiki)/Special:ChangeCredentials(?:/|$)" \ - "id:900919,phase:1,pass,nolog,chain" - SecRule REQUEST_FILENAME|ARGS_GET:title "@rx ^(?:/(?:(?:w/)?index\.php|wiki)/)?Special:ChangeCredentials(?:/|$)" "chain" - SecRule &ARGS_GET:/^(?:password|retype)$/ "@eq 0" \ +# in front of every app. So these two fields skip the same rules only in the +# forms that send them. Each of these forms sends the field authAction, whose +# value is the same in every language: +# password, retype: authAction=change, changing the password at +# Special:ChangeCredentials +# retype: authAction=create, signing up at Special:CreateAccount +# retype: authAction=login-continue, setting a new password at +# Special:UserLogin after a reset or once the old one expired +# A wiki in another language posts these forms to its own names for the pages, +# such as Spezial:Benutzerkonto_anlegen on a German wiki. So the page's name +# does not count, but its title must have a namespace, such as Special: or +# Spezial:. The title is after the path, or in title on /index.php. A title on +# any other path does not count, so another app's paths under /index.php/ keep +# every rule. These rules are in phase 2, because the forms send authAction in +# the body. +SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php$|^/(?:(?:w/)?index\.php|wiki)/[^/:]+:" \ + "id:900919,phase:2,pass,nolog,chain" + SecRule REQUEST_FILENAME|ARGS_GET:title "@rx ^(?:/(?:(?:w/)?index\.php|wiki)/)?[^/:]+:" "chain" + SecRule &ARGS_GET:/^(?:password|retype)$/ "@eq 0" "chain" + SecRule ARGS:authAction "@streq change" \ "ctl:ruleRemoveTargetById=920270;ARGS:/^(?:password|retype)$/,\ ctl:ruleRemoveTargetById=920540;ARGS:/^(?:password|retype)$/,\ ctl:ruleRemoveTargetById=921200;ARGS:/^(?:password|retype)$/,\ @@ -242,10 +250,11 @@ SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php$|^/(?:(?:w/)?index\.php|wiki)/ ctl:ruleRemoveTargetById=942550;ARGS:/^(?:password|retype)$/,\ ctl:ruleRemoveTargetById=944150;ARGS:/^(?:password|retype)$/" -SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php$|^/(?:(?:w/)?index\.php|wiki)/Special:(?:CreateAccount|UserLogin)(?:/|$)" \ - "id:900920,phase:1,pass,nolog,chain" - SecRule REQUEST_FILENAME|ARGS_GET:title "@rx ^(?:/(?:(?:w/)?index\.php|wiki)/)?Special:(?:CreateAccount|UserLogin)(?:/|$)" "chain" - SecRule &ARGS_GET:retype "@eq 0" \ +SecRule REQUEST_FILENAME "@rx ^/(?:w/)?index\.php$|^/(?:(?:w/)?index\.php|wiki)/[^/:]+:" \ + "id:900920,phase:2,pass,nolog,chain" + SecRule REQUEST_FILENAME|ARGS_GET:title "@rx ^(?:/(?:(?:w/)?index\.php|wiki)/)?[^/:]+:" "chain" + SecRule &ARGS_GET:retype "@eq 0" "chain" + SecRule ARGS:authAction "@rx ^(?:create|login-continue)$" \ "ctl:ruleRemoveTargetById=920270;ARGS:retype,\ ctl:ruleRemoveTargetById=920540;ARGS:retype,\ ctl:ruleRemoveTargetById=921200;ARGS:retype,\ diff --git a/internal/coreruleset/mediawiki_test.go b/internal/coreruleset/mediawiki_test.go index 8e0ae88..e9a7bfb 100644 --- a/internal/coreruleset/mediawiki_test.go +++ b/internal/coreruleset/mediawiki_test.go @@ -248,26 +248,52 @@ func TestMediaWikiSignUpAndPasswordChangeFieldsPass(t *testing.T) { // The form that changes a password posts to this subpage. const subpage = "/MediaWiki%5CAuth%5CPasswordAuthenticationRequest" + // The forms send authAction in the body, and MediaWiki reads it from the + // query too. These requests send it in the query, so that the body holds + // only the passwords. The recorded requests send it in the body. + const ( + create = "authAction=create" + loginContinue = "authAction=login-continue" + changeAction = "authAction=change" + ) + change := []string{passwordKey, retypeKey} retype := []string{retypeKey} wantPasswordFieldsPass(t, []passwordFields{ - {mediawikiSignUp, formData, retype}, - {"/index.php/Special:CreateAccount", formData, retype}, - {"/index.php?title=Special:CreateAccount&returnto=Main_Page", formData, retype}, - {"/wiki/Special:UserLogin", formData, retype}, - {mediawikiSignIn, formData, retype}, - {mediawikiAccountChange, formData, change}, - {mediawikiAccountChange + subpage, formData, change}, - {"/index.php/Special:ChangeCredentials", formData, change}, - {"/index.php?title=Special:ChangeCredentials" + subpage, formData, change}, - {"/w/index.php?title=Special:ChangeCredentials", formData, change}, + {mediawikiSignUp + "?" + create, formData, retype}, + {"/index.php/Special:CreateAccount?" + create, formData, retype}, + { + "/index.php?title=Special:CreateAccount&returnto=Main_Page&" + create, + formData, retype, + }, + {"/wiki/Special:UserLogin?" + loginContinue, formData, retype}, + {mediawikiSignIn + "&" + loginContinue, formData, retype}, + {mediawikiAccountChange + "?" + changeAction, formData, change}, + {mediawikiAccountChange + subpage + "?" + changeAction, formData, change}, + {"/index.php/Special:ChangeCredentials?" + changeAction, formData, change}, + { + "/index.php?title=Special:ChangeCredentials" + subpage + "&" + changeAction, + formData, change, + }, + {"/w/index.php?title=Special:ChangeCredentials&" + changeAction, formData, change}, + // A German wiki's names for the same pages. + {"/index.php/Spezial:Benutzerkonto_anlegen?" + create, formData, retype}, + { + "/index.php?title=Spezial:Anmelden&returnto=Hauptseite&" + loginContinue, + formData, retype, + }, + { + "/wiki/Spezial:Anmeldeinformationen_%C3%A4ndern" + subpage + "?" + changeAction, + formData, change, + }, {mediawikiAPI, formData, retype}, }) } // Other apps use the names password and retype too. So these fields keep every -// rule on any page that does not take them, whatever title the query names. +// rule unless the page is MediaWiki's, its title has a namespace, and +// authAction names a form that sends the field. func TestMediaWikiPasswordFieldsStayCheckedOffTheirPages(t *testing.T) { t.Parallel() @@ -277,15 +303,17 @@ func TestMediaWikiPasswordFieldsStayCheckedOffTheirPages(t *testing.T) { for _, sent := range []struct{ target, name string }{ {appPath, passwordKey}, - {appPath, retypeKey}, - {appPath + "?title=Special:ChangeCredentials", passwordKey}, - {appPath + "?title=Special:CreateAccount", retypeKey}, - {"/index.php?title=Main_Page", passwordKey}, - {"/index.php/Main_Page", retypeKey}, - {"/wiki/Main_Page", passwordKey}, - {"/wiki/Special:ChangeCredentialsExample", passwordKey}, - {mediawikiSignUp, passwordKey}, - {"/index.php?title=Special:CreateAccount", passwordKey}, + {appPath + "?authAction=create", retypeKey}, + {appPath + "?title=Special:ChangeCredentials&authAction=change", passwordKey}, + {appPath + "?title=Special:CreateAccount&authAction=create", retypeKey}, + {"/index.php?title=Main_Page&authAction=change", passwordKey}, + {"/index.php/Main_Page?authAction=create", retypeKey}, + {"/wiki/Main_Page?authAction=change", passwordKey}, + {mediawikiAccountChange, passwordKey}, + {mediawikiAccountChange + "?authAction=login", passwordKey}, + {mediawikiSignUp + "?authAction=create", passwordKey}, + {"/index.php?title=Special:CreateAccount&authAction=create", passwordKey}, + {"/index.php/Spezial:Anmelden?authAction=login", retypeKey}, } { r := request{http.MethodPost, sent.target, []string{formData}} diff --git a/internal/coreruleset/testdata/mediawiki-requests.txt b/internal/coreruleset/testdata/mediawiki-requests.txt index 8224e74..2419501 100644 --- a/internal/coreruleset/testdata/mediawiki-requests.txt +++ b/internal/coreruleset/testdata/mediawiki-requests.txt @@ -600,3 +600,14 @@ {"method": "POST", "target": "/index.php/Special:EditWatchlist/raw", "headers": ["Host: example.com", "Content-Length: 161", "Cache-Control: max-age=0", "Accept-Language: en-US,en;q=0.9", "Origin: http://example.com", "Content-Type: application/x-www-form-urlencoded", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/index.php?title=Special:EditWatchlist/raw", "Accept-Encoding: gzip, deflate", "Cookie: my_wiki_session=ed9592ia2u8ub3tdanl6632jbgboksr9; my_wikiUserID=2; my_wikiUserName=Admin; cpPosIndex=2%401794271545%23fad50a8505bea134cc843d03608984cc; UseDC=master"], "body": "title=Special%3AEditWatchlist%2Fraw&wpTitles=Lighthouse+notes%0D%0APython3+notes%0D%0APowershell+notes&wpEditToken=b2872c8548fbba5f193e80b549d5da2f6af26939%2B%5C"} {"method": "POST", "target": "/index.php/Special:EditWatchlist/raw", "headers": ["Host: example.com", "Content-Length: 179", "Cache-Control: max-age=0", "Accept-Language: en-US,en;q=0.9", "Origin: http://example.com", "Content-Type: application/x-www-form-urlencoded", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/index.php?title=Special:EditWatchlist/raw", "Accept-Encoding: gzip, deflate", "Cookie: my_wiki_session=ed9592ia2u8ub3tdanl6632jbgboksr9; my_wikiUserID=2; my_wikiUserName=Admin; UseDC=master; cpPosIndex=3%401794271545%23fad50a8505bea134cc843d03608984cc"], "body": "title=Special%3AEditWatchlist%2Fraw&wpTitles=Lighthouse+notes%0D%0APowershell+notes%0D%0APython3+notes%0D%0ALs+-la+notes&wpEditToken=b2872c8548fbba5f193e80b549d5da2f6af26939%2B%5C"} {"method": "POST", "target": "/index.php/Special:EditWatchlist/raw", "headers": ["Host: example.com", "Content-Length: 200", "Cache-Control: max-age=0", "Accept-Language: en-US,en;q=0.9", "Origin: http://example.com", "Content-Type: application/x-www-form-urlencoded", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/index.php?title=Special:EditWatchlist/raw", "Accept-Encoding: gzip, deflate", "Cookie: my_wiki_session=ed9592ia2u8ub3tdanl6632jbgboksr9; my_wikiUserID=2; my_wikiUserName=Admin; UseDC=master; cpPosIndex=4%401794271545%23fad50a8505bea134cc843d03608984cc"], "body": "title=Special%3AEditWatchlist%2Fraw&wpTitles=Lighthouse+notes%0D%0ALs+-la+notes%0D%0APowershell+notes%0D%0APython3+notes%0D%0A.htaccess+notes&wpEditToken=b2872c8548fbba5f193e80b549d5da2f6af26939%2B%5C"} +# From a German wiki without short URLs, whose forms post to the German names of +# the special pages: signing up, changing the password, and setting a new +# password at sign-in once the old one expired. Each password is random. +{"method": "GET", "target": "/index.php/Spezial:Benutzerkonto_anlegen", "headers": ["Host: example.com", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "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", "Accept-Encoding: gzip, deflate", "Accept-Language: de-DE,de;q=0.9"], "body": ""} +{"method": "POST", "target": "/index.php/Spezial:Benutzerkonto_anlegen", "headers": ["Host: example.com", "Content-Length: 328", "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/137.0.0.0 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/index.php/Spezial:Benutzerkonto_anlegen", "Accept-Encoding: gzip, deflate", "Accept-Language: de-DE,de;q=0.9", "Cookie: my_wiki_session=n6eeeqk2f317s76jc5710hofe2o5pk65"], "body": "title=Spezial%3ABenutzerkonto+anlegen&wpName=Beispielnutzer&wpPassword=+%2F%22j14y%5B%25%5C%28iM%5DzmG%25%3D%5E&retype=+%2F%22j14y%5B%25%5C%28iM%5DzmG%25%3D%5E&email=&realname=&wpEditToken=%2B%5C&authAction=create&force=&wpCreateaccountToken=e75eca0539b22c74e93948a1d4631c466af3953d%2B%5C&wpCreateaccount=Benutzerkonto+erstellen"} +{"method": "GET", "target": "/index.php/Spezial:Anmeldeinformationen_%C3%A4ndern/MediaWiki%5CAuth%5CPasswordAuthenticationRequest", "headers": ["Host: example.com", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "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", "Accept-Encoding: gzip, deflate", "Accept-Language: de-DE,de;q=0.9", "Cookie: my_wiki_session=gfiqj1icq48j4cu6ghubpfc7n5css8ee; my_wikiUserID=3; my_wikiUserName=Beispielnutzer; cpPosIndex=1%401794348350%2383f0234f558f9a2917ed83d7eb2c1095; UseDC=master"], "body": ""} +{"method": "POST", "target": "/index.php/Spezial:Anmeldeinformationen_%C3%A4ndern/MediaWiki%5CAuth%5CPasswordAuthenticationRequest", "headers": ["Host: example.com", "Content-Length: 333", "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/137.0.0.0 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/index.php/Spezial:Anmeldeinformationen_%C3%A4ndern/MediaWiki%5CAuth%5CPasswordAuthenticationRequest", "Accept-Encoding: gzip, deflate", "Accept-Language: de-DE,de;q=0.9", "Cookie: my_wiki_session=gfiqj1icq48j4cu6ghubpfc7n5css8ee; my_wikiUserID=3; my_wikiUserName=Beispielnutzer; cpPosIndex=1%401794348350%2383f0234f558f9a2917ed83d7eb2c1095; UseDC=master"], "body": "title=Spezial%3AAnmeldeinformationen+%C3%A4ndern%2FMediaWiki%5CAuth%5CPasswordAuthenticationRequest&password=Z%3E%22%7BZ%5CQDwqBQs%25v%7D%60nBu&retype=Z%3E%22%7BZ%5CQDwqBQs%25v%7D%60nBu&wpusername=&wpEditToken=a0fa962ce1b1e7c743ff500b3a740c236af3953e%2B%5C&wpAuthToken=2ea5e8a20a3cfa31cce14265135edf856af3953e%2B%5C&authAction=change"} +{"method": "GET", "target": "/index.php/Spezial:Anmelden", "headers": ["Host: example.com", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "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", "Accept-Encoding: gzip, deflate", "Accept-Language: de-DE,de;q=0.9"], "body": ""} +{"method": "POST", "target": "/index.php/Spezial:Anmelden", "headers": ["Host: example.com", "Content-Length: 219", "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/137.0.0.0 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/index.php/Spezial:Anmelden", "Accept-Encoding: gzip, deflate", "Accept-Language: de-DE,de;q=0.9", "Cookie: my_wiki_session=49u0bk921kv5dan4pc4i86e1nvbqerur"], "body": "title=Spezial%3AAnmelden&wpName=Beispielnutzer&wpPassword=Z%3E%22%7BZ%5CQDwqBQs%25v%7D%60nBu&wpEditToken=%2B%5C&authAction=login&force=&wpLoginToken=d5a70412545c3a0a18b18e04dbf80c636af3953e%2B%5C&wploginattempt=Anmelden"} +{"method": "POST", "target": "/index.php/Spezial:Anmelden", "headers": ["Host: example.com", "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/137.0.0.0 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/index.php/Spezial:Anmelden", "Accept-Encoding: gzip, deflate", "Accept-Language: de-DE,de;q=0.9", "Cookie: my_wiki_session=49u0bk921kv5dan4pc4i86e1nvbqerur"], "body": "title=Spezial%3AAnmelden&wpName=&wpPassword=gJ%3CEcT%29jhZ%27%60GC%3EcX%7EhM&retype=gJ%3CEcT%29jhZ%27%60GC%3EcX%7EhM&wpEditToken=%2B%5C&authAction=login-continue&force=&wpLoginToken=d5a70412545c3a0a18b18e04dbf80c636af3953e%2B%5C&wploginattempt=Mit+der+Anmeldung+fortfahren"} +{"method": "GET", "target": "/index.php/Hauptseite", "headers": ["Host: example.com", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "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/index.php/Spezial:Anmelden", "Accept-Encoding: gzip, deflate", "Accept-Language: de-DE,de;q=0.9", "Cookie: my_wiki_session=hd06l4sbv7mprq1ogl7ia3p62rm2o68n; my_wikiUserID=3; my_wikiUserName=Beispielnutzer; cpPosIndex=3%401794348350%2383f0234f558f9a2917ed83d7eb2c1095; UseDC=master"], "body": ""}