VYPR
Moderate severityNVD Advisory· Published Nov 12, 2024· Updated Nov 13, 2024

Denial of Service attack on windows app using Netty

CVE-2024-47535

Description

Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. An unsafe reading of environment file could potentially cause a denial of service in Netty. When loaded on an Windows application, Netty attempts to load a file that does not exist. If an attacker creates such a large file, the Netty application crashes. This vulnerability is fixed in 4.1.115.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
io.netty:netty-commonMaven
< 4.1.115.Final4.1.115.Final

Affected products

1

Patches

1
fbf7a704a82e

Merge commit from fork

https://github.com/netty/nettyNorman MaurerNov 12, 2024via ghsa
5 files changed · +142 10
  • common/src/main/java/io/netty/util/internal/BoundedInputStream.java+83 0 added
    @@ -0,0 +1,83 @@
    +/*
    + * Copyright 2024 The Netty Project
    + *
    + * The Netty Project licenses this file to you 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:
    + *
    + *   https://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.netty.util.internal;
    +
    +import org.jetbrains.annotations.NotNull;
    +
    +import java.io.FilterInputStream;
    +import java.io.IOException;
    +import java.io.InputStream;
    +
    +public final class BoundedInputStream extends FilterInputStream {
    +
    +    private final int maxBytesRead;
    +    private int numRead;
    +
    +    public BoundedInputStream(@NotNull InputStream in, int maxBytesRead) {
    +        super(in);
    +        this.maxBytesRead = ObjectUtil.checkPositive(maxBytesRead, "maxRead");
    +    }
    +
    +    public BoundedInputStream(@NotNull InputStream in) {
    +        this(in, 8 * 1024);
    +    }
    +
    +    @Override
    +    public int read() throws IOException {
    +        checkMaxBytesRead(1);
    +        try {
    +            int b = super.read();
    +            if (b <= 0) {
    +                // We couldn't read anything.
    +                numRead--;
    +            }
    +            return b;
    +        } catch (IOException e) {
    +            numRead--;
    +            throw e;
    +        }
    +    }
    +
    +    @Override
    +    public int read(byte[] buf, int off, int len) throws IOException {
    +        // Calculate the maximum number of bytes that we should try to read.
    +        int num = Math.min(len, maxBytesRead - numRead + 1);
    +        checkMaxBytesRead(num);
    +        try {
    +            int b = super.read(buf, off, num);
    +            if (b == -1) {
    +                // We couldn't read anything.
    +                numRead -= num;
    +            } else if (b != num) {
    +                // Correct numRead based on the actual amount we were able to read.
    +                numRead -= num - b;
    +            }
    +            return b;
    +        } catch (IOException e) {
    +            numRead -= num;
    +            throw e;
    +        }
    +    }
    +
    +    private void checkMaxBytesRead(int n) throws IOException {
    +        int sum = numRead + n;
    +        if (sum < 0 || sum > maxBytesRead) {
    +            numRead = maxBytesRead + 1;
    +            throw new IOException("Maximum number of bytes read: " + maxBytesRead);
    +        }
    +        numRead = sum;
    +    }
    +}
    
  • common/src/main/java/io/netty/util/internal/PlatformDependent.java+2 3 modified
    @@ -239,9 +239,8 @@ public Boolean run() {
                             if (file.exists()) {
                                 BufferedReader reader = null;
                                 try {
    -                                reader = new BufferedReader(
    -                                        new InputStreamReader(
    -                                                new FileInputStream(file), CharsetUtil.UTF_8));
    +                                reader = new BufferedReader(new InputStreamReader(
    +                                        new BoundedInputStream(new FileInputStream(file)), CharsetUtil.UTF_8));
     
                                     String line;
                                     while ((line = reader.readLine()) != null) {
    
  • common/src/main/java/io/netty/util/NetUtil.java+5 3 modified
    @@ -16,6 +16,7 @@
     package io.netty.util;
     
     import io.netty.util.NetUtilInitializations.NetworkIfaceAndInetAddress;
    +import io.netty.util.internal.BoundedInputStream;
     import io.netty.util.internal.PlatformDependent;
     import io.netty.util.internal.StringUtil;
     import io.netty.util.internal.SystemPropertyUtil;
    @@ -24,7 +25,7 @@
     
     import java.io.BufferedReader;
     import java.io.File;
    -import java.io.FileReader;
    +import java.io.FileInputStream;
     import java.io.IOException;
     import java.io.InputStream;
     import java.io.InputStreamReader;
    @@ -190,7 +191,8 @@ public Integer run() {
                     // try / catch block.
                     // See https://github.com/netty/netty/issues/4936
                     if (file.exists()) {
    -                    in = new BufferedReader(new FileReader(file));
    +                    in = new BufferedReader(new InputStreamReader(
    +                            new BoundedInputStream(new FileInputStream(file))));
                         somaxconn = Integer.parseInt(in.readLine());
                         if (logger.isDebugEnabled()) {
                             logger.debug("{}: {}", file, somaxconn);
    @@ -243,7 +245,7 @@ private static Integer sysctlGetInt(String sysctlKey) throws IOException {
             try {
                 // Suppress warnings about resource leaks since the buffered reader is closed below
                 InputStream is = process.getInputStream();
    -            InputStreamReader isr = new InputStreamReader(is);
    +            InputStreamReader isr = new InputStreamReader(new BoundedInputStream(is));
                 BufferedReader br = new BufferedReader(isr);
                 try {
                     String line = br.readLine();
    
  • common/src/test/java/io/netty/util/internal/BoundedInputStreamTest.java+44 0 added
    @@ -0,0 +1,44 @@
    +/*
    + * Copyright 2024 The Netty Project
    + *
    + * The Netty Project licenses this file to you 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:
    + *
    + *   https://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.netty.util.internal;
    +
    +import org.junit.jupiter.api.Test;
    +import org.junit.jupiter.api.function.Executable;
    +
    +import java.io.ByteArrayInputStream;
    +import java.io.IOException;
    +
    +import static org.junit.jupiter.api.Assertions.assertEquals;
    +import static org.junit.jupiter.api.Assertions.assertThrows;
    +
    +public class BoundedInputStreamTest {
    +
    +    @Test
    +    void testBoundEnforced() throws IOException {
    +        final byte[] bytes = new byte[64];
    +        PlatformDependent.threadLocalRandom().nextBytes(bytes);
    +        final BoundedInputStream reader = new BoundedInputStream(new ByteArrayInputStream(bytes), bytes.length - 1);
    +        assertEquals(bytes[0], (byte) reader.read());
    +
    +        assertThrows(IOException.class, new Executable() {
    +            @Override
    +            public void execute() throws Throwable {
    +                reader.read(new byte[64], 0, 64);
    +            }
    +        });
    +        reader.close();
    +    }
    +}
    
  • resolver-dns/src/main/java/io/netty/resolver/dns/ResolvConf.java+8 4 modified
    @@ -15,9 +15,12 @@
      */
     package io.netty.resolver.dns;
     
    +import io.netty.util.internal.BoundedInputStream;
    +
     import java.io.BufferedReader;
    -import java.io.FileReader;
    +import java.io.FileInputStream;
     import java.io.IOException;
    +import java.io.InputStreamReader;
     import java.net.InetSocketAddress;
     import java.util.ArrayList;
     import java.util.Collections;
    @@ -45,12 +48,13 @@ static ResolvConf fromReader(BufferedReader reader) throws IOException {
          * {@code /etc/resolv.conf} file, see {@code man resolv.conf}.
          */
         static ResolvConf fromFile(String file) throws IOException {
    -        FileReader fileReader = new FileReader(file);
    +        BufferedReader reader = new BufferedReader(new InputStreamReader(
    +                // Use 1 MB to be a bit conservative
    +                new BoundedInputStream(new FileInputStream(file), 1024 * 1024)));
             try {
    -            BufferedReader reader = new BufferedReader(new FileReader(file));
                 return fromReader(reader);
             } finally {
    -            fileReader.close();
    +            reader.close();
             }
         }
     
    

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

4

News mentions

0

No linked articles in our index yet.