Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8225404

Potential DOS using UUID.fromString

XMLWordPrintable

    • x86_64
    • windows_10

      A DESCRIPTION OF THE PROBLEM :
      In Java 8 UUID.fromString parses the string by using String.split without any validation before that [1].
      This can be quite problematic because that method is rather inefficient. Since UUIDs are used by web services which might not perform additional validation before using UUID.fromString this might allow causing a Denial of Service.
      In Java 9 the implementation has been changed (JDK-8006627) and is not affected by this problem [2].

      [1] https://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/d0cccfd32b1e/src/share/classes/java/util/UUID.java#l192
      [2] https://hg.openjdk.java.net/jdk/jdk/file/905b2a416250/src/java.base/share/classes/java/util/UUID.java#l198

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Parsing the ~42MB string consisting only of hypens (-) should fail fast.
      ACTUAL -
      Parsing takes multiple seconds and consumes ~800MB before failing.

      ---------- BEGIN SOURCE ----------
      import java.util.Arrays;
      import java.util.UUID;

      public class UUIDTest {
          public static void main(String[] args) {
              final char[] uuidStringChars = new char[Integer.MAX_VALUE / 100];
              Arrays.fill(uuidStringChars, '-');
              
              final long preString = getUsedMemory();
              final String uuidString = new String(uuidStringChars);
              printUsedMemory("String", getUsedMemory() - preString);
              
              System.gc();
              final long preUuid = getUsedMemory();
              
              try {
                  UUID.fromString(uuidString);
              }
              catch (final IllegalArgumentException e) {
                  printUsedMemory("UUID parsing", getUsedMemory() - preUuid);
              }
          }
          
          private static long getUsedMemory() {
              return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
          }
          
          private static void printUsedMemory(final String message, final long usedMemory) {
              System.out.println(message + ": " + usedMemory / 1_000_000 + "MB (" + usedMemory + " bytes)");
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Validate the UUID string length before calling UUID.fromString, a UUID string longer than 36 characters is malformed and will not work in Java 9(+) anyways.

      FREQUENCY : always


            psonal Pallavi Sonal (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: