CVE-2025-69460 – Simple Image Gallery 1.0 - Remote Code Execution (Unauthenticated) | Tağmaç - root@Tagoletta:~#
Contents

CVE-2025-69460 – Simple Image Gallery 1.0 - Remote Code Execution (Unauthenticated)

Wed Jan 21 2026 · 3 min read

Category: Security Research

# Exploit# Zero-Day# RCE


Introduction

View Exploit Code

In this report, I will detail the discovery and exploitation of a critical Remote Code Execution (RCE) vulnerability in the "Simple Image Gallery 1.0" application. As a security researcher, my goal was to achieve full control over the server via an unauthenticated attack vector. The attack chain consists of two main vulnerabilities: SQL Injection to bypass authentication and Unrestricted File Upload to execute arbitrary code.

Vulnerability Analysis

Phase 1: Authentication Bypass (SQL Injection)

My first target was the application's login mechanism. Upon analyzing classes/Login.php, I noticed that user inputs were directly concatenated into the database query.

// Vulnerable Code in classes/Login.php
$qry = $this->conn->query("SELECT * from users where username = '$username' and password = md5('$password') ");

As seen, the $username variable is inserted into the SQL query without any sanitization. This allows an attacker to manipulate the query logic.

Payload: admin' or '1'='1'#

When this payload is used, the query becomes:

SELECT * from users where username = 'admin' or '1'='1'#' and password = md5('...')

The # character comments out the rest of the query (the password check), and since the 1=1 condition is always true, the database returns the first user (usually the administrator). Thus, access to the system is granted without a password.

Phase 2: Remote Code Execution (Unrestricted File Upload)

After gaining administrative access, I examined the file upload functions. During the user profile update process (classes/Users.php), I found that uploaded files were not sufficiently validated.

// Vulnerable Code in classes/Users.php
if(isset($_FILES['img']) && $_FILES['img']['tmp_name'] != ''){
    $fname = 'uploads/'.strtotime(date('y-m-d H:i')).'_'.$_FILES['img']['name'];
    $move = move_uploaded_file($_FILES['img']['tmp_name'],'../'. $fname);
    // ...
}

The vulnerabilities here are:

  1. No Extension Validation: The code uses the filename ($_FILES['img']['name']) directly and does not check if the extension is safe (e.g., only .jpg or .png).
  2. No Content Check: The file content or MIME type is not verified.
  3. Executable File: When a file with a .php extension is uploaded, the server treats it as a PHP script and executes it.

This vulnerability allows an attacker to upload a malicious PHP file (web shell) to the server and execute commands by calling this file via the browser.

Exploit Development

I developed a Python script (exploit.py) to automate this attack chain. The logic of the script is as follows:

  1. Session Initialization: An HTTP session is started using requests.session().
  2. Login Bypass: An SQL injection payload (admin' or '1'='1'#) is sent to classes/Login.php?f=login. Upon a successful response, the session is authenticated.
  3. Protecting User Data: Since the profile update process replaces all fields, the current user details (ID, Firstname, Lastname, Username) are first scraped from the ?page=user page. This step is crucial to prevent data corruption.
  4. Shell Upload: A multipart/form-data request is sent to classes/Users.php?f=save.
    • The scraped user details are added as form data.
    • A randomly named file containing PHP code and having a .php extension is added to the img field.
    • Payload: <?php if(isset($_GET['cmd'])){ echo '<pre>'; $cmd = ($_GET['cmd']); system($cmd); echo '</pre>'; die; } ?>
  5. Execution: After the upload, the profile page is checked again to find the path (src attribute) of the uploaded file. Finally, a command execution test is performed by appending ?cmd=whoami to this path.

Remediation

To fix these vulnerabilities, the following steps should be taken:

1. Prevent SQL Injection:
Use Prepared Statements instead of string concatenation in database queries.

Secure Example:

$stmt = $this->conn->prepare("SELECT * from users where username = ? and password = md5(?)");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();

2. Secure File Upload:
File extensions and types must be strictly validated. Filenames should not be taken from the user but should be randomly generated by the server.

Secure Example:

$allowed = array('jpg', 'jpeg', 'png', 'gif');
$ext = pathinfo($_FILES['img']['name'], PATHINFO_EXTENSION);
if(!in_array(strtolower($ext), $allowed)) {
    exit("Invalid file type");
}
$fname = 'uploads/' . uniqid() . '.' . $ext;

CVE ID: CVE-2025-69460
Original public disclosure: August 17, 2021
Researcher: Tağmaç "Tagoletta"
Canonical reference: https://www.exploit-db.com/exploits/50214
Github Repository: https://github.com/Tagoletta/CVE-2025-69460

Frequently Asked Questions

What is CVE-2025-69460?

An unauthenticated Remote Code Execution vulnerability in Simple Image Gallery 1.0, discovered as a zero-day by Tağmaç 'Tagoletta'.

What is the root cause of CVE-2025-69460?

An unrestricted file upload that lets an attacker upload an executable script such as PHP, which the server then runs, granting command execution without authentication.

How can an attacker exploit it?

By uploading a crafted image/script file that bypasses the type checks and then requesting its URL, triggering server-side code execution.

How do you remediate CVE-2025-69460?

Validate file type by content, store uploads outside the web root, rename files and strip execution permissions, and disable script execution in the upload directory.

Where is the PoC exploit writeup for CVE-2025-69460?

The full proof-of-concept exploit code and step-by-step writeup are published on this site — see the companion exploit page for the ready-to-run PoC that uploads a webshell via the unrestricted file upload for RCE.