Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process dump caused by malicious response headers #5678

Open
reganxt opened this issue Jun 15, 2024 · 3 comments
Open

Process dump caused by malicious response headers #5678

reganxt opened this issue Jun 15, 2024 · 3 comments

Comments

@reganxt
Copy link

reganxt commented Jun 15, 2024

We've observer an issue with Jersey 2.40+。When the Jersey client is used to access the server, if the server returns a malicious request header (containing an oversized packet), the client process will be dumped, causing a DoS attack.
A malicious server adds a 1 GB packet to the response header. The payload is as follows:

urls = (
    '/v1/uniagent/baseInfo/ping1','baseInfo_ping',
    '/v1/uniagent/baseInfo/ping','baseInfo_ping1'
    )

class baseInfo_ping:
    def GET(self):
        web.header('Set-Cookie', 'SESSION=ZTgwODZkYzMtOGMxYi00ODFmLTk0ZjItM2VjZmJlNDFmOGRi; 
              Path=/; Secure; HttpOnly; SameSite=None')
    text = open('data.json', 'rb').read()
    web.header('s',text)
    return '{"resultCode":"0"}'

When the client uses Jersey for HTTP connection, the response header is loaded to the memory. As a result, a dump occurs. The stack is as follows:

Thread Stack

https-jsse-nio-127.0.0.1-25920-exec-8
    at java.net.SocketInputStream.socketRead0(Ljava/io/FileDescriptor;[BIII)I (Native Method)
    at java.net.SocketInputStream.socketRead(Ljava/io/FileDescriptor;[BIII)I (SocketInputStream.java:116)
    at java.net.SocketInputStream.read([BIII)I (SocketInputStream.java:171)
    at java.net.SocketInputStream.read([BII)I (SocketInputStream.java:141)
    at sun.security.ssl.SSLSocketInputRecord.read(Ljava/io/InputStream;[BII)I (SSLSocketInputRecord.java:475)
    at sun.security.ssl.SSLSocketInputRecord.readHeader()I (SSLSocketInputRecord.java:469)
    at sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket()I (SSLSocketInputRecord.java:69)
    at sun.security.ssl.SSLSocketImpl.readApplicationRecord(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer; (SSLSocketImpl.java:1352)
    at sun.security.ssl.SSLSocketImpl.access$300(Lsun/security/ssl/SSLSocketImpl;Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer; 
          (SSLSocketImpl.java:73)
    at sun.security.ssl.SSLSocketImpl$AppInputStream.read([BII)I (SSLSocketImpl.java:969)
    at java.io.BufferedInputStream.fill()V (BufferedInputStream.java:246)
    at java.io.BufferedInputStream.read1([BII)I (BufferedInputStream.java:286)
    at java.io.BufferedInputStream.read([BII)I (BufferedInputStream.java:345)
    at sun.net.www.http.ChunkedInputStream.fastRead([BII)I (ChunkedInputStream.java:244)
    at sun.net.www.http.ChunkedInputStream.read([BII)I (ChunkedInputStream.java:689)
    at java.io.FilterInputStream.read([BII)I (FilterInputStream.java:133)
    at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read([BII)I (HttpURLConnection.java:3460)
    at org.glassfish.jersey.client.internal.HttpUrlConnector$2.read([BII)I (HttpUrlConnector.java:216)
    at org.glassfish.jersey.message.internal.EntityInputStream.read([BII)I (EntityInputStream.java:79)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream.read([BII)I 
        (ReaderInterceptorExecutor.java:273)
    at org.glassfish.jersey.message.internal.ReaderWriter.readAllBytes(Ljava/io/InputStream;)[B (ReaderWriter.java:183)
    at org.glassfish.jersey.message.internal.ReaderWriter.readFromAsString
        (Ljava/io/InputStream;Ljavax/ws/rs/core/MediaType;)Ljava/lang/String; (ReaderWriter.java:140)
    at org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider.readFromAsString
        (Ljava/io/InputStream;Ljavax/ws/rs/core/MediaType;)Ljava/lang/String; (AbstractMessageReaderWriterProvider.java:94)
    at org.glassfish.jersey.message.internal.StringMessageProvider.readFrom
        (Ljava/lang/Class;Ljava/lang/reflect/Type; [Ljava/lang/annotation/Annotation;Ljavax/ws/rs/core/MediaType;
        Ljavax/ws/rs/core/MultivaluedMap;Ljava/io/InputStream;)Ljava/lang/String; (StringMessageProvider.java:54)
    at org.glassfish.jersey.message.internal.StringMessageProvider.readFrom(Ljava/lang/Class;Ljava/lang/reflect/Type; 
        [Ljava/lang/annotation/Annotation;Ljavax/ws/rs/core/MediaType;
        Ljavax/ws/rs/core/MultivaluedMap;Ljava/io/InputStream;)Ljava/lang/Object; (StringMessageProvider.java:36)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom
        (Ljavax/ws/rs/ext/ReaderInterceptorContext;Ljavax/ws/rs/ext/MessageBodyReader;
        Lorg/glassfish/jersey/message/internal/EntityInputStream;)Ljava/lang/Object; (ReaderInterceptorExecutor.java:233)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom
        (Ljavax/ws/rs/ext/ReaderInterceptorContext;)Ljava/lang/Object; (ReaderInterceptorExecutor.java:212)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed()Ljava/lang/Object; 
        (ReaderInterceptorExecutor.java:132)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom
        (Ljava/lang/Class;Ljava/lang/reflect/Type;[Ljava/lang/annotation/Annotation;Ljavax/ws/rs/core/MediaType;
        Ljavax/ws/rs/core/MultivaluedMap;Lorg/glassfish/jersey/internal/PropertiesDelegate;
        Ljava/io/InputStream;Ljava/lang/Iterable;Z)Ljava/lang/Object; (MessageBodyFactory.java:1072)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(Ljava/lang/Class;Ljava/lang/reflect/Type; 
        [Ljava/lang/annotation/Annotation;Lorg/glassfish/jersey/internal/PropertiesDelegate;)Ljava/lang/Object; 
        (InboundMessageContext.java:919)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity
        (Ljava/lang/Class;Lorg/glassfish/jersey/internal/PropertiesDelegate;)Ljava/lang/Object; (InboundMessageContext.java:853)
    at org.glassfish.jersey.client.ClientResponse.readEntity(Ljava/lang/Class;)Ljava/lang/Object; (ClientResponse.java:298)
    at org.glassfish.jersey.client.InboundJaxrsResponse$1.call()Ljava/lang/Object; (InboundJaxrsResponse.java:93)
    at org.glassfish.jersey.internal.Errors.process(Ljava/util/concurrent/Callable;Z)Ljava/lang/Object; (Errors.java:292)
    at org.glassfish.jersey.internal.Errors.process(Lorg/glassfish/jersey/internal/util/Producer;Z)Ljava/lang/Object; (Errors.java:274)
    at org.glassfish.jersey.internal.Errors.process(Lorg/glassfish/jersey/internal/util/Producer;)Ljava/lang/Object; (Errors.java:205)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope
        (Lorg/glassfish/jersey/process/internal/RequestContext;Lorg/glassfish/jersey/internal/util/Producer;)
        Ljava/lang/Object; (RequestScope.java:365)
   at org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible
        (Lorg/glassfish/jersey/internal/util/Producer;)Ljava/lang/Object; (InboundJaxrsResponse.java:244)
   at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(Ljava/lang/Class;)Ljava/lang/Object; (InboundJaxrsResponse.java:90)
@jansupol
Copy link
Contributor

Yes, Jersey tries to read the whole String when you call Response.readEntity(String.class).

It might be possible to add a property to optionally limit the size of the entity.

However, this stacktrace does not seem to show the actual issue with a long header, rather the result of full memory when the entity is read. (SSLSocketInputRecord.readHeader() actually reads 5 bytes). I am not sure we can prevent reading the headers by the JDK as the headers are parsed by HttpUrlConnection#getHeaderFields()

@fantasy1713
Copy link

@jansupol which property should be used to limit the reponse header size?

@jansupol
Copy link
Contributor

HttpUrlConnection does not seem to allow to limit the response header size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants