
Proof-of-concept de laboratoire pour un contournement d'autorisation Gitea où un PAT public uniquement avec write:organization crée une organisation privée via POST /api/v1/orgs.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitea-public-only-pat-org
Gitea 1.27.3 - Gitea
public-only sur un PAT est censé être la promesse que le token ne peut pas toucher aux ressources privées. POST /user/repos a rejectPublicOnly. POST /orgs a tokenRequiresScopes et reqToken. Il n'a pas rejectPublicOnly. DEFAULT_ALLOW_CREATE_ORGANIZATION vaut true par défaut.
Un PAT public-only avec write:organization crée une organisation privée. Le même token ne peut pas créer un dépôt utilisateur privé.
| ID | pas encore de CVE |
| CWE | CWE-863 |
| CVSS | Moyen : 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Produit | Gitea |
| Affecté | jusqu'à v1.27.3 (146cc3e) |
| Auth | PAT public-only avec écriture org |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Utiliser un PAT public-only volé ou sur-émis qui possède aussi write:organization. Créer une organisation privée. Cette org est une cachette que le token n'était pas censé pouvoir créer. Le même token ne peut toujours pas créer un dépôt utilisateur privé, et ce bug n'ouvre pas le git privé existant de quelqu'un d'autre.
Atteinte à l'intégrité, pas une exfiltration de git privé. Utile quand la victime a émis « public-only » exprès : CI, un bot, un token de sous-traitant qu'elle pensait incapable de faire pousser une org privée.
La création de dépôt d'org ne vérifie que la visibilité de l'org. Le POST /org/{org}/repos déprécié ignore complètement le public-only. J'ai testé en lab la création d'org. Cela suffit.
Même passe résiduelle que le lab hostmatcher 0.0.0.0/8 : v1.27.3 après la vague de GHSA, puis les handlers qui sautent encore une barrière qu'un handler frère possède déjà. Les bugs de visibilité et de portée de token étaient un thème de cette vague. J'ai fait un grep de rejectPublicOnly dans api.go. La création de dépôt utilisateur l'a. La création d'org ne l'a pas.
J'ai émis un PAT avec les scopes public-only,write:organization,write:repository,write:user. La création d'org privée a renvoyé 201. Même token, création de dépôt utilisateur privé, 403 this endpoint is not available for public-only tokens. Ce 403 est le témoin. Si les deux avaient renvoyé 201, le middleware aurait totalement disparu. Si les deux avaient renvoyé 403, il n'y aurait rien à signaler.
Fausses pistes déjà consignées : considérer le HTTP 201 de l'org comme suffisant (confirmer visibility=private sur GET) ; la création de dépôt utilisateur privé qui réussit (alors rejectPublicOnly a disparu - le lab exige un 403) ; lire le contenu d'un git privé existant ; un reverse shell. Du théâtre.
cd lab
./run.sh
Cible uniquement http://127.0.0.1:18132. Compose définit DEFAULT_ALLOW_CREATE_ORGANIZATION=true.
token-scopes=public-only,write:organization,write:repository,write:user
org-create status=201
org-visibility='private'
user-repo-create status=403 this endpoint is not available for public-only tokens
SUCCESS GITEA-PUBLIC-ONLY-PAT
Placer rejectPublicOnly() sur POST /orgs, et traiter la création de dépôt d'org comme sensible au public-only également. La création d'org public-only doit renvoyer 403 de la même manière que la création de dépôt utilisateur privé le fait déjà.
api.go (rejectPublicOnly, POST /orgs, POST /user/repos)GNU Affero GPL v3.0. Voir LICENSE. Lab en loopback uniquement. Aucune garantie.