Intro We discovered and developed an exploit for a pre-authentication remote code execution vulnerability in IBM i Management Central (MGTC). The vulnerability allows an unauthenticated attacker to execute arbitrary CL commands as QSECOFR – the root-equivalent profile on IBM i – by abusing the MGTC packet protocol on port 5555. What is Management Central? Management Central is a Java-based system management framework that has been part of IBM i since the early 2000s. It provides centralized task scheduling, system monitoring, software distribution, and remote command execution across groups of IBM i systems. If that sounds like a powerful service to expose on the network, it is. The service runs as two listeners. Port 5544 is an RMI-based interface that uses McRMISocketFactory – a custom RMISocketFactory – to wrap every incoming connection in a serialized McSocketBundle exchange before any RMI method calls occur. There was a deserialization vulnerability in Management Central that we discovered and reported to IBM PSIRT. ( CVE-2024-31879 ). Port 5555 runs McSocketListener , which extends java.net.ServerSocket directly, skipping RMI and Java serialization. It accepts raw TCP connections, performs a custom binary handshake, and then creates a McPacketConnection that processes packets using McBuffer , a custom binary serialization format. This is the port and protocol we exploit in this post. Both ports are started by the MGTC server job ( QYPSJSVR ) when the service is active. The CL command is STRTCPSVR SERVER(*MGTC) . IBM has been deprecating Management Central. Starting with V7R5, the service is no longer part of the operating system. On V7R4 and earlier, it is a standard component and often starts automatically. Given IBM i’s long upgrade cycles, there are plenty of V7R4 systems in production. Finding the Pieces The MGTC implementation ships as a set of JAR files. The client-side classes are included in IBM i Access Client Solutions (ACS): McClient.jar , McPacketClient.jar , McServer.jar , and McOSClient.jar . On the server side, the same JARs live under /QIBM/ProdData/OS400/Mgtc/ – over 40 JARs in total, plus jt400.jar from /QIBM/ProdData/OS400/jt400/lib/ . Decompiling these JARs gives us the complete picture. The MGTC protocol has no public documentation – everything described in this post was reconstructed from the bytecode using javap -p -c on the class files. The key classes are: Class Role McSocketListener Server socket for port 5555 (extends ServerSocket ) McSocketConnection Handles the binary handshake, sends/receives packets McPacketConnection Wraps McSocketConnection , manages the packet lifecycle McBuffer Custom binary serializer (not ObjectInputStream ) McPacket Base class for all packets; carries routing + auth data McClassManager Maps integer classIds to Java class names McPacketableAuthenticationData Per-packet auth structure (the vulnerable component) McPacketManager Routes packets, calls authenticate() and execute() The Class ID System MGTC uses integer class identifiers to map packet types to Java classes. McClassManager maintains a static array of 3000 entries initialized at startup. The important ones for this exploit: classId 3 → McCreateRequest (registers a managed object) classId 16 → McStartRequest (starts/executes an activity) classId 21 → McTaskRequest (task lifecycle operations) classId 82 → McStatusReply (success response) classId 87 → McManagedObjectReply (returns created object with assigned ID) classId 99 → McSlashedAndBurnedReply (error response) classId 251 → McEndpointManagedCmdData (command task data) classId 252 → McManagedCmdDefinition (command definition with CL string) When the server receives a packet, it reads the classId from the wire, looks up the corresponding class name in the array, instantiates it via reflection, and calls inflate() to deserialize the packet from a McBuffer . The McBuffer Format McBuffer is the serialization engine for all MGTC packet data. Instead of using the built-in Java ObjectInputStream , it uses a custom binary format with explicit type encoding. The primitives: Method Wire format deflate(int) 4 bytes big-endian deflate(long) 8 bytes big-endian deflate(float) 4 bytes IEEE 754 deflate(byte) 1 byte deflate(byte[]) raw bytes, no length prefix deflate(String) 2-byte length (short) + UTF-16BE data deflate(String, (short)4) 4-byte length (int) + UTF-16BE data When the server creates a McBuffer for outgoing data, it calls allocate() which writes a 4-byte version float (e.g., 7.2f = 0x40e66666 ) as the first bytes. Incoming data is expected to start with this version header. The Binary Handshake The handshake on port 5555 is the first barrier. McSocketConnection.sendHandshake() and receiveHandshake() implement a multi-step exchange. The connector (client) sends a 1144-byte structure for IPv4: Buffer (1120 bytes): Offset 0-511: hostname (UTF-16BE, zero-padded) Offset 512-1023: hostname (repeated) Offset 1024-1055: IP address (UTF-16BE, 32 bytes...
This vulnerability (CVE-2024-31879, CVSS 7.5 HIGH) allows unauthenticated remote code execution as the QSECOFR superuser on IBM i by exploiting a client-controlled verification flag in the Management Central packet protocol on port 5555. The flaw affects IBM i versions 7.2, 7.3, and 7.4. As Management Central is deprecated and removed in V7R5, the primary mitigation is to disable the service via `ENDTCPSVR SERVER(*MGTC)` and ensure ports 5544 and 5555 are not exposed to untrusted networks.