VYPR
Medium severity6.1NVD Advisory· Published Sep 26, 2016· Updated May 6, 2026

CVE-2016-4993

CVE-2016-4993

Description

CRLF injection vulnerability in the Undertow web server in WildFly 10.0.0, as used in Red Hat JBoss Enterprise Application Platform (EAP) 7.x before 7.0.2, allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks via unspecified vectors.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.wildfly:wildfly-undertowMaven
>= 10.0.0.Final, < 11.0.0.Final11.0.0.Final

Patches

1
834496fb74dd

UNDERTOW-827 WFLY-6760 CVE-2016-4993 wildfly: HTTP header injection / response splitting

https://github.com/undertow-io/undertowStuart DouglasJun 24, 2016via ghsa
6 files changed · +114 3
  • core/src/main/java/io/undertow/protocols/http2/HpackEncoder.java+7 0 modified
    @@ -155,6 +155,13 @@ public State encode(HeaderMap headers, ByteBuffer target) {
                         int required = 11 + headerName.length(); //we use 11 to make sure we have enough room for the variable length itegers
     
                         String val = values.get(i);
    +                    for(int v = 0; v < val.length(); ++v) {
    +                        char c = val.charAt(v);
    +                        if(c == '\r' || c == '\n') {
    +                            val = val.replace('\r', ' ').replace('\n', ' ');
    +                            break;
    +                        }
    +                    }
                         TableEntry tableEntry = findInTable(headerName, val);
     
                         required += (1 + val.length());
    
  • core/src/main/java/io/undertow/server/protocol/ajp/AjpServerResponseConduit.java+6 1 modified
    @@ -151,7 +151,12 @@ private static void putString(final ByteBuffer buf, String value) {
             final int length = value.length();
             putInt(buf, length);
             for (int i = 0; i < length; ++i) {
    -            buf.put((byte) value.charAt(i));
    +            char c = value.charAt(i);
    +            if(c != '\r' && c != '\n'){
    +                buf.put((byte) c);
    +            } else {
    +                buf.put((byte)' ');
    +            }
             }
             buf.put((byte) 0);
         }
    
  • core/src/main/java/io/undertow/server/protocol/http/HttpResponseConduit.java+6 1 modified
    @@ -289,7 +289,12 @@ private void bufferDone() {
         private static void writeString(ByteBuffer buffer, String string) {
             int length = string.length();
             for (int charIndex = 0; charIndex < length; charIndex++) {
    -            buffer.put((byte) string.charAt(charIndex));
    +            char c = string.charAt(charIndex);
    +            if(c != '\r' && c != '\n') {
    +                buffer.put((byte) c);
    +            } else {
    +                buffer.put((byte) ' ');
    +            }
             }
         }
     
    
  • core/src/main/java/io/undertow/UndertowMessages.java+5 1 modified
    @@ -476,6 +476,10 @@ public interface UndertowMessages {
         @Message(id = 148, value = "Invalid HPack encoding. First byte: %s")
         HpackException invalidHpackEncoding(byte b);
     
    -    @Message(id = 149, value = "Pseudo header %s received after receiving normal headers. Pseudo headers must be the first headers in a HTTP/2 header block.")
    +    @Message(id = 149, value = "HttpString is not allowed to contain newlines. value: %s")
    +    IllegalArgumentException newlineNotSupportedInHttpString(String value);
    +
    +    @Message(id = 150, value = "Pseudo header %s received after receiving normal headers. Pseudo headers must be the first headers in a HTTP/2 header block.")
         IllegalArgumentException pseudoHeaderInWrongOrder(HttpString header);
    +
     }
    
  • core/src/main/java/io/undertow/util/HttpString.java+12 0 modified
    @@ -30,6 +30,8 @@
     import static java.lang.System.arraycopy;
     import static java.util.Arrays.copyOfRange;
     
    +import io.undertow.UndertowMessages;
    +
     /**
      * An HTTP case-insensitive Latin-1 string.
      *
    @@ -116,13 +118,23 @@ public HttpString(final String string) {
             this.bytes = bytes;
             this.hashCode = calcHashCode(bytes);
             this.string = string;
    +        checkForNewlines();
    +    }
    +
    +    private void checkForNewlines() {
    +        for(byte b : bytes) {
    +            if(b == '\r' || b == '\n') {
    +                throw UndertowMessages.MESSAGES.newlineNotSupportedInHttpString(string);
    +            }
    +        }
         }
     
         private HttpString(final byte[] bytes, final String string) {
             this.bytes = bytes;
             this.hashCode = calcHashCode(bytes);
             this.string = string;
             this.orderInt = 0;
    +        checkForNewlines();
         }
     
         /**
    
  • core/src/test/java/io/undertow/server/NewlineInHeadersTestCase.java+78 0 added
    @@ -0,0 +1,78 @@
    +/*
    + * JBoss, Home of Professional Open Source.
    + * Copyright 2014 Red Hat, Inc., and individual contributors
    + * as indicated by the @author tags.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + *  Unless required by applicable law or agreed to in writing, software
    + *  distributed under the License is distributed on an "AS IS" BASIS,
    + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + *  See the License for the specific language governing permissions and
    + *  limitations under the License.
    + */
    +
    +package io.undertow.server;
    +
    +import java.io.IOException;
    +
    +import org.apache.http.HttpResponse;
    +import org.apache.http.client.methods.HttpPost;
    +import org.apache.http.entity.StringEntity;
    +import org.junit.Assert;
    +import org.junit.Test;
    +import org.junit.runner.RunWith;
    +import io.undertow.io.Receiver;
    +import io.undertow.testutils.DefaultServer;
    +import io.undertow.testutils.HttpClientUtils;
    +import io.undertow.testutils.TestHttpClient;
    +import io.undertow.util.HttpString;
    +import io.undertow.util.StatusCodes;
    +
    +/**
    + * @author Stuart Douglas
    + */
    +@RunWith(DefaultServer.class)
    +public class NewlineInHeadersTestCase {
    +
    +    private static final String RESPONSE = "response";
    +    private static final String ECHO = "echo";
    +
    +    @Test
    +    public void testNewlineInHeaders() throws IOException {
    +        DefaultServer.setRootHandler(new HttpHandler() {
    +            @Override
    +            public void handleRequest(HttpServerExchange exchange) throws Exception {
    +                exchange.getRequestReceiver().receiveFullString(new Receiver.FullStringCallback() {
    +                    @Override
    +                    public void handle(HttpServerExchange exchange, String message) {
    +                        exchange.getResponseHeaders().put(HttpString.tryFromString(ECHO), message);
    +                        exchange.getResponseSender().send(RESPONSE);
    +                    }
    +                });
    +            }
    +        });
    +        final TestHttpClient client = new TestHttpClient();
    +        try {
    +            HttpPost post = new HttpPost(DefaultServer.getDefaultServerURL());
    +            post.setEntity(new StringEntity("test"));
    +            HttpResponse result = client.execute(post);
    +            Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
    +            Assert.assertEquals("test", result.getFirstHeader(ECHO).getValue());
    +            Assert.assertEquals(RESPONSE, HttpClientUtils.readResponse(result));
    +
    +            post = new HttpPost(DefaultServer.getDefaultServerURL());
    +            post.setEntity(new StringEntity("test\nnewline"));
    +            result = client.execute(post);
    +            Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
    +            Assert.assertEquals("test newline", result.getFirstHeader(ECHO).getValue());
    +            Assert.assertEquals(RESPONSE, HttpClientUtils.readResponse(result));
    +        } finally {
    +            client.getConnectionManager().shutdown();
    +        }
    +    }
    +}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

15

News mentions

0

No linked articles in our index yet.