
Prova de conceito de laboratório para um bypass de autorização no Gitea, onde um PAT somente público com write:organization cria uma organização privada 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 em um PAT deveria ser a promessa de que o token não pode tocar recursos privados. POST /user/repos tem rejectPublicOnly. POST /orgs tem tokenRequiresScopes e reqToken. Não tem rejectPublicOnly. DEFAULT_ALLOW_CREATE_ORGANIZATION tem valor padrão true.
Um PAT public-only com write:organization cria uma organização privada. O mesmo token não consegue criar um repositório de usuário privado.
| ID | sem CVE ainda |
| CWE | CWE-863 |
| CVSS | Médio: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Produto | Gitea |
| Afetado | até v1.27.3 (146cc3e) |
| Autenticação | PAT public-only com permissão de escrita em org |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1 |
Usar um PAT public-only roubado ou emitido em excesso que também tenha write:organization. Criar uma organização privada. Essa org é um esconderijo que o token não deveria ser capaz de criar. O mesmo token ainda não consegue criar um repositório de usuário privado, e este bug não abre o git privado existente de outra pessoa.
Integridade, não um dump de git privado. Útil quando a vítima emitiu "public-only" de propósito: CI, um bot, um token de terceiro que ela achava que não poderia criar uma org privada.
A criação de repositório de org só verifica a visibilidade da org. O POST /org/{org}/repos obsoleto ignora completamente o public-only. Eu testei em lab a criação de org. Isso é suficiente.
Mesma passada de sobras do lab do hostmatcher 0.0.0.0/8: v1.27.3 após a onda de GHSAs, depois os handlers que ainda pulam uma verificação que um handler irmão já tem. Bugs de visibilidade e de escopo de token foram um tema dessa onda. Eu fiz grep de rejectPublicOnly em api.go. A criação de repositório de usuário tem. A criação de org não tem.
Eu emiti um PAT com escopos public-only,write:organization,write:repository,write:user. A criação de org privada retornou 201. O mesmo token, criação de repositório de usuário privado, 403 this endpoint is not available for public-only tokens. Esse 403 é o controle. Se ambos tivessem retornado 201, o middleware teria sumido por completo. Se ambos tivessem retornado 403, não haveria nada a reportar.
Caminhos errados já registrados: tratar o HTTP 201 da org como suficiente (confirmar visibility=private no GET); a criação de repositório de usuário privado ter sucesso (então rejectPublicOnly sumiu - o lab exige 403); ler o conteúdo de git privado existente; um reverse shell. Teatro.
cd lab
./run.sh
Alvo apenas http://127.0.0.1:18132. O Compose define 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
Colocar rejectPublicOnly() em POST /orgs, e tratar a criação de repositório de org como sensível a public-only também. A criação de org public-only deve retornar 403 da mesma forma que a criação de repositório de usuário privado já faz.
api.go (rejectPublicOnly, POST /orgs, POST /user/repos)GNU Affero GPL v3.0. Veja LICENSE. Apenas lab em loopback. Sem garantias.