Repository: aries-rsa Updated Branches: refs/heads/master 248ac56ce -> d2ecd241f
prevent out of memory in fastbin if the tcp transport receives a malicious packet (or a packet not originating from a fastbin server/client) the size field can contain any kind of int. For very high int values this will lead to OOM errors. Adds a max size of (default) 10MB to prevent a DOS attack. Project: http://git-wip-us.apache.org/repos/asf/aries-rsa/repo Commit: http://git-wip-us.apache.org/repos/asf/aries-rsa/commit/d2ecd241 Tree: http://git-wip-us.apache.org/repos/asf/aries-rsa/tree/d2ecd241 Diff: http://git-wip-us.apache.org/repos/asf/aries-rsa/diff/d2ecd241 Branch: refs/heads/master Commit: d2ecd241fd16d285c1d144a37fd40455adcff91c Parents: 248ac56 Author: Johannes Utzig <[email protected]> Authored: Thu Jul 28 14:31:24 2016 +0200 Committer: Johannes Utzig <[email protected]> Committed: Thu Apr 13 17:47:45 2017 +0200 ---------------------------------------------------------------------- .../fastbin/tcp/LengthPrefixedCodec.java | 6 +++++- .../fastbin/tcp/LengthPrefixedCodecTest.java | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d2ecd241/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodec.java ---------------------------------------------------------------------- diff --git a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodec.java b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodec.java index 86b06c9..7724f9e 100644 --- a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodec.java +++ b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodec.java @@ -34,11 +34,12 @@ import org.fusesource.hawtbuf.Buffer; public class LengthPrefixedCodec implements ProtocolCodec { + /** prevent DOS attacks in case a very large size field is sent. Default is 10MB */ + private static final int MAX_PACKET_SIZE = Integer.getInteger("aries.fastbin.max.packet.bytes", 1024 * 1024 * 10) <= 0 ? Integer.MAX_VALUE : Integer.getInteger("aries.fastbin.max.packet.bytes", 1024 * 1024 * 10); final int write_buffer_size = 1024 * 64; long write_counter = 0L; WritableByteChannel write_channel; - final Queue<ByteBuffer> next_write_buffers = new LinkedList<ByteBuffer>(); int next_write_size = 0; @@ -150,6 +151,9 @@ public class LengthPrefixedCodec implements ProtocolCodec { if( size < 4 ) { throw new ProtocolException("Expecting a size greater than 3"); } + else if( size > MAX_PACKET_SIZE ) { + throw new ProtocolException("Paket length was declared as " + size + " but at most " + MAX_PACKET_SIZE + "is allowed. You can configure this limit with the system property aries.fastbin.max.packet.bytes"); + } if( size == 4 ) { // weird.. empty frame.. guess it could happen. Buffer rc = new Buffer(read_buffer); http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d2ecd241/provider/fastbin/src/test/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodecTest.java ---------------------------------------------------------------------- diff --git a/provider/fastbin/src/test/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodecTest.java b/provider/fastbin/src/test/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodecTest.java index 5a1f669..f440a72 100644 --- a/provider/fastbin/src/test/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodecTest.java +++ b/provider/fastbin/src/test/java/org/apache/aries/rsa/provider/fastbin/tcp/LengthPrefixedCodecTest.java @@ -18,12 +18,14 @@ */ package org.apache.aries.rsa.provider.fastbin.tcp; +import java.net.ProtocolException; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import org.apache.aries.rsa.provider.fastbin.io.ProtocolCodec.BufferState; +import org.easymock.EasyMock; import org.easymock.IAnswer; import org.fusesource.hawtbuf.Buffer; import org.junit.After; @@ -138,6 +140,23 @@ public class LengthPrefixedCodecTest { assertEquals(bytesThatWillBeWritten, codec.getWriteCounter()); } + @Test(expected=ProtocolException.class) + public void testReadEvilPackage() throws Exception { + + expect(readableByteChannel.read(EasyMock.anyObject())).andAnswer(new IAnswer<Integer>() { + + @Override + public Integer answer() throws Throwable { + ByteBuffer buffer = (ByteBuffer)EasyMock.getCurrentArguments()[0]; + // an attacker could do that to provoke out of memory + buffer.putInt(Integer.MAX_VALUE-1); + return 1; + } + }); + replay(readableByteChannel); + codec.read(); + } + private IAnswer<Integer> createWriteAnswer(final int length) { return new IAnswer<Integer>() { @Override
