Skip to content

Commit 96424e7

Browse files
Merge pull request #1006 from rajeshnair/master
Add check for size in V2Decoder
2 parents 1fd4b95 + 97c7f41 commit 96424e7

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

jeromq-core/src/main/java/zmq/io/coder/v2/V2Decoder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.nio.ByteBuffer;
44

55
import zmq.Msg;
6+
import zmq.ZError;
67
import zmq.io.coder.Decoder;
78
import zmq.msg.MsgAllocator;
89
import zmq.util.Errno;
@@ -51,6 +52,10 @@ protected Step.Result eightByteSizeReady()
5152
tmpbuf.position(0);
5253
tmpbuf.limit(8);
5354
final long size = Wire.getUInt64(tmpbuf, 0);
55+
if ( size <= 0 ) {
56+
errno(ZError.EPROTO);
57+
return Step.Result.ERROR;
58+
}
5459

5560
Step.Result rc = sizeReady(size);
5661
if (rc != Step.Result.ERROR) {

jeromq-core/src/test/java/org/zeromq/ByteBuffersTest.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static org.junit.Assert.assertEquals;
55

66
import java.io.IOException;
7+
import java.io.OutputStream;
78
import java.nio.ByteBuffer;
89
import java.nio.ByteOrder;
910

@@ -235,4 +236,93 @@ public void testByteBufferLargeDirect() throws IOException
235236
}
236237
}
237238
}
239+
240+
@Test
241+
public void testByteBufferZMQExploitPayload() throws IOException
242+
{
243+
int port = Utils.findOpenPort();
244+
ZMQ.Context context = new ZMQ.Context(1);
245+
246+
ZMQ.Socket push = null;
247+
ZMQ.Socket pull = null;
248+
ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder());
249+
try {
250+
push = context.socket(SocketType.PUSH);
251+
pull = context.socket(SocketType.PULL);
252+
pull.bind("tcp://*:" + port);
253+
push.connect("tcp://localhost:" + port);
254+
255+
bb.put("PING".getBytes(ZMQ.CHARSET));
256+
bb.flip();
257+
258+
Thread.sleep(1000);
259+
push.sendByteBuffer(bb, 0);
260+
String actual = new String(pull.recv(), ZMQ.CHARSET);
261+
assertEquals("PING", actual);
262+
263+
writeExploitPayload(port);
264+
265+
bb.put("PONG".getBytes(ZMQ.CHARSET));
266+
bb.flip();
267+
push.sendByteBuffer(bb, 0);
268+
String newMsg = new String(pull.recv(), ZMQ.CHARSET);
269+
assertEquals("PONG", newMsg);
270+
271+
} catch (Exception e) {
272+
e.printStackTrace();
273+
Assert.fail();
274+
} finally {
275+
try {
276+
push.close();
277+
} catch (Exception ignore) {
278+
ignore.printStackTrace();
279+
}
280+
try {
281+
pull.close();
282+
} catch (Exception ignore) {
283+
ignore.printStackTrace();
284+
}
285+
try {
286+
context.term();
287+
} catch (Exception ignore) {
288+
ignore.printStackTrace();
289+
}
290+
}
291+
}
292+
293+
public void writeExploitPayload(int port) throws IOException {
294+
byte[] greeting = {
295+
(byte) 0xFF, /* Indicates 'versioned' in zmq::stream_engine_t::receive_greeting */
296+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Unused */
297+
0x01, /* Indicates 'versioned' in zmq::stream_engine_t::receive_greeting */
298+
0x01, // Selects ZMTP_2_0 handshake selection
299+
0x00 // Padding
300+
};
301+
byte[] v2msg = {
302+
0x02, // Eight Byte Size
303+
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
304+
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF // Oversized frame length
305+
};
306+
byte[] prePayload = new byte[8183];
307+
308+
ByteBuffer contentTReplacement = ByteBuffer.allocate(32);
309+
contentTReplacement.putLong(0, (long) System.identityHashCode(new byte[8]));
310+
contentTReplacement.putLong(16, (long) System.identityHashCode("ping google.com".getBytes()));
311+
contentTReplacement.putLong(24, 0L);
312+
313+
// Total size of all components
314+
int totalSize = greeting.length + v2msg.length + prePayload.length + contentTReplacement.capacity();
315+
ByteBuffer bSend = ByteBuffer.allocate(totalSize);
316+
317+
// Combine all byte arrays into the buffer
318+
bSend.put(greeting);
319+
bSend.put(v2msg);
320+
bSend.put(prePayload);
321+
bSend.put(contentTReplacement.array());
322+
323+
java.net.Socket pushSocket = new java.net.Socket("localhost", port);
324+
OutputStream push = pushSocket.getOutputStream();
325+
push.write(bSend.array());
326+
push.flush();
327+
}
238328
}

0 commit comments

Comments
 (0)