Back | Blog

Pre-authentication takeover in EzGED3 via Arbitrary File Read

During a black-box penetration test, Ballpoint identified critical security weaknesses in EzGED3 that allow full administrative compromise without prior authentication (CVE-2025-51539).

Written by Corentin Margraff Aug. 13, 2025 Technical analyzes
Tags - #pentest
Pre-authentication takeover in EzGED3 via Arbitrary File Read

Abstract

During a black-box penetration test, an instance of EzGED3 (1)  is discovered exposed to the internet. The application reveals critical security weaknesses that allow full admin compromise without prior authentication (CVE-2025-51539). Directory listing is enabled on a publicly accessible folder, revealing files that disclose internal implementation details. One of these files points to a PHP script that permits arbitrary file reading due to missing access controls and lack of input validation. 

Sensitive files, including database credentials, become accessible. This access leads to privilege escalation scenarios where user data, admin reset tokens, and weak password hashes are retrieved (CVE-2025-51540).

Vulnerable version < 3.5.72.27183

Write-up

1. Initial discovery : Directory Listing

During the initial reconnaissance phase, the application reveals that directory listing is enabled on the /data/ path. Accessing https://<target>/data/ returns a raw index of files and subdirectories hosted in that location. Among the listed files are several .html and .php files.

One particular HTML file (ezOpenFile.html) includes embedded PHP code that is not executed by the server. As a result, the raw source is displayed in the browser, exposing internal logic and a particularly interesting line :

<a class="MenuItem" href="showparaphdocs.php?download=0&path='.$path.'">[Cliquez ici pour afficher le document]</a>

The showparaphdocs.php file can be used to view (download=0) or download (download=1) other files.

2. Authentication bypass

The next step is to try reading the same PHP file found in the directory listing, since it’s confirmed to exist and might reveal how the script works. Looking at the code, no authentication is enforced.

The script checks if sessionid or token are set, but since they are not, the condition fails silently and the rest of the code runs anyway.

if(isset($_REQUEST["token"],$_REQUEST["sessionid"])) {
    if($_REQUEST["token"] == "<redacted>") {
        $sessionid = $_REQUEST["sessionid"];
        $params = Authentication::authenticate(array("sessionid" => $sessionid));
        if(!$params) {
            die("Requested authentication by session failed.");
        }
    }    
}

This only runs if both token and sessionid are provided in the request. If either parameter is missing, the entire block is skipped, including the authentication logic.

In the code, the value of the path parameter is used directly in a call to @readfile($path) without any sanitization or restriction. This function instructs PHP to read the file specified by $path from the server’s filesystem and output its contents directly to the HTTP response. Because there is no validation of the file path, it becomes possible to perform path traversal attacks, such as supplying ../../../../etc/passwd or pointing to application files like config.php, database dumps, or other sensitive resources.

Because the software can run on either Windows or Linux servers, it will depends on the context.

To extract the entire source code of the folder, we can use the following one liner :

for i in $(cat files.txt); do 
  curl -k -s "https://<ip>/data/showparaphdocs.php?download=0&path=$i" > $i;
done

3. Database access

While analyzing the contents of the files, a reference is found pointing to a local configuration file:

nchp/etc/nchp/ezged/instance.conf

This file contains sensitive database configuration, including:

  • Database hostname

  • Database username and password

  • Name of the target database used by the application

Some server have a phpMyAdmin interface exposed on the target system, and these credentials can be used to log in directly as the root user, giving access to all user data, including hashed passwords stored in internal tables.

Neat Trick: Reading MySQL Data Files Directly

With the following information:

  • Arbitrary file read capability

  • Known location of the MySQL data directory

  • Known name of the database

…it becomes possible to read the raw storage files used by MySQL to persist table data.

MySQL stores its data (depending on configuration) in the following structure:

mysql/data/<database_name>/<table_name>.<extension>

Relevant file extensions include .ibd, .frm, .myd, .opt, .sql, and .cnf

In this case, the table responsible for storing users and password hashes is named _secusr, and in InnoDB storage format, this table maps to:

mysql/data/<database_name>/_secusr.ibd

By retrieving this file via the arbitrary file read, a raw dump of the user table is obtained:

The raw content of the file is sufficient to extract user credentials. Passwords in EzGED3 are stored using the weak construct md5(md5(password)), which provides very little protection against offline cracking.

However, in this case, brute-forcing the hashes is not even necessary to achieve full administrative access.

The application provides a password reset mechanism. Tokens used for password recovery are stored in the same file. 

Once a valid reset token is retrieved, it becomes possible to initiate a password reset without knowing the original password or having access to the admin’s email address.

This bypass allows full administrative takeover of the system, purely through file reads, with no need for brute-force or privilege escalation via code execution.

Timeline

  • 2024-11-14 - Discovery of the vulnerability
  • 2024-11-15 - Report of the vulnerability to the editor
  • 2024-12-05 - EZDEV validates the report
  • 2025-02-17 - Follow-up
  • 2025-05-16 - CVE declaration
  • 2025-08-13 - Article released

Resources

  • (1) https://www.ezged.org