
Prueba de concepto de laboratorio para un bypass de autorización en Gitea donde un PAT solo público con write:organization crea una organización privada mediante 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 en un PAT se supone que es la promesa de que el token no puede tocar recursos privados. POST /user/repos tiene rejectPublicOnly. POST /orgs tiene tokenRequiresScopes y reqToken. No tiene rejectPublicOnly. DEFAULT_ALLOW_CREATE_ORGANIZATION por defecto es true.
Un PAT public-only con write:organization crea una organización privada. El mismo token no puede crear un repositorio de usuario privado.
| ID | aún sin CVE |
| CWE | CWE-863 |
| CVSS | Medio: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Producto | Gitea |
| Afectado | hasta v1.27.3 (146cc3e) |
| Auth | PAT public-only con escritura de org |
| Licencia | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Usar un PAT public-only robado o emitido en exceso que además tenga write:organization. Crear una organización privada. Esa org es un escondite que el token no debería haber podido crear. El mismo token sigue sin poder crear un repositorio de usuario privado, y este bug no abre el git privado existente de otra persona.
Integridad, no un volcado de git privado. Útil cuando la víctima emitió "public-only" a propósito: CI, un bot, un token de contratista que creían que no podía hacer crecer una org privada.
La creación de repos de org solo verifica la visibilidad de la org. El obsoleto POST /org/{org}/repos omite public-only por completo. Yo probé la creación de org. Eso es suficiente.
Misma pasada de restos que el lab de hostmatcher 0.0.0.0/8: v1.27.3 después de la oleada de GHSA, luego los handlers que aún omiten una puerta que un hermano ya tiene. Los bugs de visibilidad y de alcance de token fueron un tema de esa oleada. Hice grep de rejectPublicOnly en api.go. La creación de repos de usuario lo tiene. La creación de org no.
Generé un PAT con los scopes public-only,write:organization,write:repository,write:user. La creación de org privada devolvió 201. El mismo token, creación de repo de usuario privado, 403 this endpoint is not available for public-only tokens. Ese 403 es el control. Si ambos hubieran dado 201, el middleware habría desaparecido por completo. Si ambos hubieran dado 403, no habría nada que reportar.
Caminos equivocados ya registrados: tratar el HTTP 201 de org como suficiente (confirmar visibility=private en GET); que la creación de repo de usuario privado tuviera éxito (entonces rejectPublicOnly desapareció - el lab requiere 403); leer el contenido de git privado existente; una reverse shell. Teatro.
cd lab
./run.sh
Objetivo solo http://127.0.0.1:18132. Compose establece 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
Poner rejectPublicOnly() en POST /orgs, y tratar la creación de repos de org como sensible a public-only también. La creación de org public-only debe dar 403 de la misma forma que ya lo hace la creación de repo de usuario privado.
api.go (rejectPublicOnly, POST /orgs, POST /user/repos)GNU Affero GPL v3.0. Ver LICENSE. Solo lab en loopback. Sin garantía.