Summary
RabbitMQ Java Client's inbound AMQP command assembly accepts a content header declaring a small body and then processes a larger body frame by throwing a raw UnsupportedOperationException from CommandAssembler. A broker peer that the client has connected to can use this malformed frame sequence to fail frame processing and tear down the client connection instead of receiving a clean protocol-level malformed-frame error.
This was discovered based on a existing vulnerability CVE-2017-15699. However, the crash site code doesn't seem to be fully implemented yet, so I would like to know if it is just a code that would be fixed.
Details
Inbound frames enter the client through SocketFrameHandler.readFrame, which returns frames parsed from the peer-controlled input stream (src/main/java/com/rabbitmq/client/impl/SocketFrameHandler.java:197). AMQConnection.MainLoop reads each frame (src/main/java/com/rabbitmq/client/impl/AMQConnection.java:692) and dispatches non-zero-channel frames to the channel while the connection is open (src/main/java/com/rabbitmq/client/impl/AMQConnection.java:748 and src/main/java/com/rabbitmq/client/impl/AMQConnection.java:766). The channel then passes the frame to the current command assembler through AMQChannel.handleFrame and AMQCommand.handleFrame (src/main/java/com/rabbitmq/client/impl/AMQChannel.java:121, src/main/java/com/rabbitmq/client/impl/AMQCommand.java:114). When a content-bearing method is followed by a content header, CommandAssembler.consumeHeaderFrame records the header's declared body size in remainingBodyBytes after only checking it against the configured maximum (src/main/java/com/rabbitmq/client/impl/CommandAssembler.java:126 through src/main/java/com/rabbitmq/client/impl/CommandAssembler.java:139). The body-frame path subtracts the received payload length from that remaining count before validating that the payload fits (src/main/java/com/rabbitmq/client/impl/CommandAssembler.java:145 through src/main/java/com/rabbitmq/client/impl/CommandAssembler.java:149), so a body frame larger than the declared size drives the count negative and reaches the raw UnsupportedOperationException at src/main/java/com/rabbitmq/client/impl/CommandAssembler.java:150 and src/main/java/com/rabbitmq/client/impl/CommandAssembler.java:151. AMQConnection catches the resulting throwable in frame processing and performs connection failure handling and final shutdown (src/main/java/com/rabbitmq/client/impl/AMQConnection.java:695 through src/main/java/com/rabbitmq/client/impl/AMQConnection.java:705).
PoC
poc.zip
Exception in thread "main" java.lang.UnsupportedOperationException: %%%%%% FIXME unimplemented
The UnsupportedOperationException: %%%%%% FIXME unimplemented fingerprint is the raw exception thrown at the negative remainingBodyBytes check in CommandAssembler.consumeBodyFrame. This line shows the malformed declared-size/body-size sequence reached the vulnerable assembler path.
Impact
The attacker model is a remote AMQP broker peer that the RabbitMQ Java Client application has accepted, including a malicious broker endpoint, a compromised broker, or routing that sends the client to an attacker-controlled peer. The peer needs a non-zero open channel that can receive a content-bearing server-to-client method such as basic.deliver, then sends the method frame, a content header declaring a body below the configured maximum, and a body frame whose payload exceeds that declared size. Under those conditions, the peer can force frame processing to fail with UnsupportedOperationException and close the AMQP connection, producing a client-side denial of service for work depending on that connection; the finding does not indicate memory corruption, data disclosure, or code execution.
Summary
RabbitMQ Java Client's inbound AMQP command assembly accepts a content header declaring a small body and then processes a larger body frame by throwing a raw
UnsupportedOperationExceptionfromCommandAssembler. A broker peer that the client has connected to can use this malformed frame sequence to fail frame processing and tear down the client connection instead of receiving a clean protocol-level malformed-frame error.This was discovered based on a existing vulnerability CVE-2017-15699. However, the crash site code doesn't seem to be fully implemented yet, so I would like to know if it is just a code that would be fixed.
Details
Inbound frames enter the client through
SocketFrameHandler.readFrame, which returns frames parsed from the peer-controlled input stream (src/main/java/com/rabbitmq/client/impl/SocketFrameHandler.java:197).AMQConnection.MainLoopreads each frame (src/main/java/com/rabbitmq/client/impl/AMQConnection.java:692) and dispatches non-zero-channel frames to the channel while the connection is open (src/main/java/com/rabbitmq/client/impl/AMQConnection.java:748andsrc/main/java/com/rabbitmq/client/impl/AMQConnection.java:766). The channel then passes the frame to the current command assembler throughAMQChannel.handleFrameandAMQCommand.handleFrame(src/main/java/com/rabbitmq/client/impl/AMQChannel.java:121,src/main/java/com/rabbitmq/client/impl/AMQCommand.java:114). When a content-bearing method is followed by a content header,CommandAssembler.consumeHeaderFramerecords the header's declared body size inremainingBodyBytesafter only checking it against the configured maximum (src/main/java/com/rabbitmq/client/impl/CommandAssembler.java:126throughsrc/main/java/com/rabbitmq/client/impl/CommandAssembler.java:139). The body-frame path subtracts the received payload length from that remaining count before validating that the payload fits (src/main/java/com/rabbitmq/client/impl/CommandAssembler.java:145throughsrc/main/java/com/rabbitmq/client/impl/CommandAssembler.java:149), so a body frame larger than the declared size drives the count negative and reaches the rawUnsupportedOperationExceptionatsrc/main/java/com/rabbitmq/client/impl/CommandAssembler.java:150andsrc/main/java/com/rabbitmq/client/impl/CommandAssembler.java:151.AMQConnectioncatches the resulting throwable in frame processing and performs connection failure handling and final shutdown (src/main/java/com/rabbitmq/client/impl/AMQConnection.java:695throughsrc/main/java/com/rabbitmq/client/impl/AMQConnection.java:705).PoC
poc.zip
The
UnsupportedOperationException: %%%%%% FIXME unimplementedfingerprint is the raw exception thrown at the negativeremainingBodyBytescheck inCommandAssembler.consumeBodyFrame. This line shows the malformed declared-size/body-size sequence reached the vulnerable assembler path.Impact
The attacker model is a remote AMQP broker peer that the RabbitMQ Java Client application has accepted, including a malicious broker endpoint, a compromised broker, or routing that sends the client to an attacker-controlled peer. The peer needs a non-zero open channel that can receive a content-bearing server-to-client method such as
basic.deliver, then sends the method frame, a content header declaring a body below the configured maximum, and a body frame whose payload exceeds that declared size. Under those conditions, the peer can force frame processing to fail withUnsupportedOperationExceptionand close the AMQP connection, producing a client-side denial of service for work depending on that connection; the finding does not indicate memory corruption, data disclosure, or code execution.