CVE-2023-38890 – Online Shopping Portal 3.1 Remote Code Execution

CVE-2023-38890 – Online Shopping Portal 3.1 Remote Code Execution

Exploit / Project Details

Python Thu Jun 17 2021

CVE-2023-38890 - Zero-Day Discovery & Exploit Development: Online Shopping Portal

Detailed Write-up

CVE-2023-38890 – Online Shopping Portal 3.1 Unauthenticated RCE

This vulnerability affects SourceCodester Online Shopping Portal version 3.1.
It results in remote unauthenticated code execution via SQL injection and unrestricted file upload.

1. Reconnaissance & Discovery: The Entry Point (SQL Injection)

My initial target was the administrative interface. As a black-box tester, the first logical step is to test the authentication mechanism for weaknesses.

The Discovery Process

I navigated to /admin/index.php and was presented with a standard login form. Instead of guessing passwords, I tested for SQL Injection (SQLi) by injecting special characters into the username field.

  • Attempt 1: admin' -> Result: Potential error or invalid login.
  • Attempt 2: ' OR 1=1-- -> Result: Successful Login.

By inputting ' OR 1=1--, I effectively tricked the database. The query logic was altered to "Select user where username is empty OR 1 equals 1". Since 1=1 is always true, the database returned the first record in the admin table, logging me in as the administrator without a password.

Root Cause Analysis

Upon reviewing the source code in admin/index.php, the vulnerability became obvious:

$username=$_POST['username'];
$ret=mysqli_query($con,"SELECT * FROM admin WHERE username='$username' and password='$password'");

Why this is vulnerable: The developer directly concatenated user input ($username) into the SQL query string. There is no input sanitization, no escaping of special characters, and most importantly, no use of Prepared Statements. This is a textbook SQL Injection vulnerability.

2. Escalation: Hunting for RCE (Unrestricted File Upload)

Having gained administrative access, my goal shifted from access to control (Remote Code Execution). I began mapping the application's features, looking for any functionality that interacts with the file system.

The Discovery Process

I found the "Insert Product" page (admin/insert-product.php). This form allows administrators to upload product images. This is a prime target for malicious file uploads.

I attempted to upload a file named shell.php containing a simple PHP script instead of a valid image (JPG/PNG).

  • Result: The application accepted the file without any error.
  • Verification: I checked the upload directory (productimages/{id}/) and found my .php file was stored and executable by the web server.

Root Cause Analysis

The code responsible for handling uploads in admin/insert-product.php is critically flawed:

move_uploaded_file($_FILES["productimage1"]["tmp_name"],"productimages/$productid/".$_FILES["productimage1"]["name"]);

Why this is vulnerable:

  1. No Extension Validation: The code does not check if the file extension is safe (e.g., .jpg, .png). It blindly accepts .php, .exe, etc.
  2. No MIME Type Check: It does not verify the actual content of the file.
  3. No Renaming: It saves the file using the original name provided by the user ($_FILES["..."]["name"]). This allows an attacker to predict the file path easily.

3. Weaponization: Developing the Exploit

With the two vulnerabilities identified, I chained them together to create a fully automated exploit script (exploit.py).

The Exploit Logic

  1. Session Initialization: I use requests.session() to maintain cookies, simulating a browser.

  2. Authentication Bypass: The script sends a POST request to /admin/ with the payload ' OR 1=1-- a in the username field. This establishes an authenticated administrator session.

  3. Payload Generation: I generate a random string for the product name and the shell filename to avoid collisions and detection. The payload is a simple PHP web shell:

    <?php if(isset($_GET['cmd'])){ system($_GET['cmd']); } ?>
    
  4. Malicious Upload: The script constructs a multipart/form-data POST request to insert-product.php. It fills in the required product fields and attaches the PHP shell as productimage1.

  5. Path Extraction: After the upload, the script searches for the newly created product to find the exact path where the server stored the shell.

  6. Execution: Finally, it prints the URL of the uploaded shell. Accessing this URL with ?cmd=whoami executes commands on the server.

4. Remediation: How to Fix

To secure this application, the code must be refactored significantly.

Fixing the SQL Injection

Use Prepared Statements (Parameterized Queries). This ensures that the database treats user input as data, not executable code.

Secure Code Example (admin/index.php):

$stmt = $con->prepare("SELECT id, username, password FROM admin WHERE username=? AND password=?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();
if ($row = $result->fetch_assoc()) {
    // Login successful
}

Fixing the File Upload

Implement strict validation and file renaming.

Secure Code Example (admin/insert-product.php):

$allowed_extensions = array("jpg", "jpeg", "png", "gif");
$filename = $_FILES["productimage1"]["name"];
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));

// 1. Check Extension
if (!in_array($ext, $allowed_extensions)) {
    die("Invalid file type.");
}

// 2. Check MIME Type (Content)
$check = getimagesize($_FILES["productimage1"]["tmp_name"]);
if ($check === false) {
    die("File is not an image.");
}

// 3. Rename File (Prevent overwriting and execution)
$new_filename = md5(time() . $filename) . '.' . $ext;
move_uploaded_file($_FILES["productimage1"]["tmp_name"], "productimages/$productid/" . $new_filename);

CVE ID: CVE-2023-38890
Original public disclosure: June 17, 2021 (Exploit-DB)
Researcher: Tağmaç "Tagoletta"
Canonical reference: https://www.exploit-db.com/exploits/50029

Source Code Explorer
/
Select a file
2024 © Tağmaç Han