From ab618dcf2f6d1e970ebcd4a402c5441979db6fca Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Mon, 21 Sep 2020 17:41:51 -0400 Subject: [PATCH 01/10] Java: QL Query Detector for JHipster Generated CVE-2019-16303 --- .../CWE/CWE-338/JHipsterGeneratedPRNG.qhelp | 55 +++ .../CWE/CWE-338/JHipsterGeneratedPRNG.ql | 48 +++ .../CWE-338/JHipsterGeneratedPRNGFixed.java | 69 ++++ .../JHipsterGeneratedPRNGVulnerable.java | 58 +++ .../code/java/frameworks/apache/Lang.qll | 9 + .../tests/JHipsterGeneratedPRNG.expected | 5 + .../semmle/tests/JHipsterGeneratedPRNG.qlref | 1 + .../semmle/tests/fixed/RandomUtil.java | 71 ++++ .../security/CWE-338/semmle/tests/options | 1 + .../semmle/tests/vulnerable/RandomUtil.java | 60 +++ .../apache-commons-lang3-3.7/LICENSE.txt | 203 +++++++++ .../commons/lang3/RandomStringUtils.java | 388 ++++++++++++++++++ 12 files changed, 968 insertions(+) create mode 100644 java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp create mode 100644 java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql create mode 100644 java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGFixed.java create mode 100644 java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java create mode 100644 java/ql/src/semmle/code/java/frameworks/apache/Lang.qll create mode 100644 java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.expected create mode 100644 java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.qlref create mode 100644 java/ql/test/query-tests/security/CWE-338/semmle/tests/fixed/RandomUtil.java create mode 100644 java/ql/test/query-tests/security/CWE-338/semmle/tests/options create mode 100644 java/ql/test/query-tests/security/CWE-338/semmle/tests/vulnerable/RandomUtil.java create mode 100644 java/ql/test/stubs/apache-commons-lang3-3.7/LICENSE.txt create mode 100644 java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/RandomStringUtils.java diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp new file mode 100644 index 000000000000..8aa9f27c0288 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp @@ -0,0 +1,55 @@ + + + +

This query detects instances of RandomUtil.java generated by a JHipster version vulnerable to CVE-2019-16303. + +

Using one password reset token from your app combined with the proof of concept (POC) linked below, an attacker can determine all future password reset tokens to be generated by this server. +This allows an attacker to pick and choose what account they would like to takeover by sending account password reset requests for targeted accounts.

+ +

This vulnerability has a + + CVSS v3.0 Base Score of 9.8/10 +.

+
+ + + +

The example below shows the vulnerable RandomUtil class generated by JHipster. + + +

Below is a fixed version of the RandomUtil class.

+ + +
+ + + +An automated refactoring rewrite module can be found here. + + + + +
  • + + Cloudflare Blog: Why secure systems require random numbers + +
  • +
  • + + How I Hacked Hacker News (with arc security advisory) + +
  • +
  • + Research (Hacking Apache Commons RandomStringUtils): + + The Java Soothsayer: A practical application for insecure randomness. (Includes free 0day) + +
  • + + + +
    + +
    diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql new file mode 100644 index 000000000000..9717b9ce7e06 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql @@ -0,0 +1,48 @@ +/** + * @name Detect JHipster Generator Vulnnerability CVE-2019-16303 + * @description Detector for the CVE-2019-16303 vulnerability that existed in the JHipster code generator. + * @kind problem + * @problem.severity error + * @precision very-high + * @id java/jhipster-prng + * @tags security + * external/cwe/cwe-338 + */ + +import java +import semmle.code.java.frameworks.apache.Lang + +private class PredictableApacheRandomStringUtilsMethod extends Method { + PredictableApacheRandomStringUtilsMethod() { + this.getDeclaringType() instanceof TypeApacheRandomStringUtils + } +} + +private class PredictableApacheRandomStringUtilsMethodAccess extends MethodAccess { + PredictableApacheRandomStringUtilsMethodAccess() { + this.getMethod() instanceof PredictableApacheRandomStringUtilsMethod and + // The one valid use of this type that uses SecureRandom as a source of data. + not this.getMethod().getName() = "random" + } +} + +private class VulnerableJHipsterRandomUtilClass extends Class { + VulnerableJHipsterRandomUtilClass() { getName() = "RandomUtil" } +} + +private class VulnerableJHipsterRandomUtilMethod extends Method { + VulnerableJHipsterRandomUtilMethod() { + this.getDeclaringType() instanceof VulnerableJHipsterRandomUtilClass and + this.getName().matches("generate%") and + this.getReturnType() instanceof TypeString and + exists(ReturnStmt s, PredictableApacheRandomStringUtilsMethodAccess access | + s = this.getBody().(SingletonBlock).getStmt() + | + s.getResult() = access + ) + } +} + +from VulnerableJHipsterRandomUtilMethod the_method +select the_method, + "RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303" diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGFixed.java b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGFixed.java new file mode 100644 index 000000000000..42cf387806a6 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGFixed.java @@ -0,0 +1,69 @@ +import org.apache.commons.lang3.RandomStringUtils; + +import java.security.SecureRandom; + +/** + * Utility class for generating random Strings. + */ +public final class RandomUtil { + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + + private static final int DEF_COUNT = 20; + + static { + SECURE_RANDOM.nextBytes(new byte[64]); + } + + private RandomUtil() { + } + + private static String generateRandomAlphanumericString() { + return RandomStringUtils.random(DEF_COUNT, 0, 0, true, true, null, SECURE_RANDOM); + } + + /** + * Generate a password. + * + * @return the generated password. + */ + public static String generatePassword() { + return generateRandomAlphanumericString(); + } + + /** + * Generate an activation key. + * + * @return the generated activation key. + */ + public static String generateActivationKey() { + return generateRandomAlphanumericString(); + } + + /** + * Generate a reset key. + * + * @return the generated reset key. + */ + public static String generateResetKey() { + return generateRandomAlphanumericString(); + } + + /** + * Generate a unique series to validate a persistent token, used in the + * authentication remember-me mechanism. + * + * @return the generated series data. + */ + public static String generateSeriesData() { + return generateRandomAlphanumericString(); + } + + /** + * Generate a persistent token, used in the authentication remember-me mechanism. + * + * @return the generated token data. + */ + public static String generateTokenData() { + return generateRandomAlphanumericString(); + } +} diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java new file mode 100644 index 000000000000..d1a7f4cd9248 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java @@ -0,0 +1,58 @@ +import org.apache.commons.lang3.RandomStringUtils; + +/** + * Utility class for generating random Strings. + */ +public final class RandomUtil { + + private static final int DEF_COUNT = 20; + + private RandomUtil() { + } + + /** + * Generate a password. + * + * @return the generated password. + */ + public static String generatePassword() { + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + } + + /** + * Generate an activation key. + * + * @return the generated activation key. + */ + public static String generateActivationKey() { + return RandomStringUtils.randomNumeric(DEF_COUNT); + } + + /** + * Generate a reset key. + * + * @return the generated reset key. + */ + public static String generateResetKey() { + return RandomStringUtils.randomNumeric(DEF_COUNT); + } + + /** + * Generate a unique series to validate a persistent token, used in the + * authentication remember-me mechanism. + * + * @return the generated series data. + */ + public static String generateSeriesData() { + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + } + + /** + * Generate a persistent token, used in the authentication remember-me mechanism. + * + * @return the generated token data. + */ + public static String generateTokenData() { + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + } +} diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll new file mode 100644 index 000000000000..2aa00a007f37 --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -0,0 +1,9 @@ +/* Definitions related to the Apache Commons Exec library. */ +import semmle.code.java.Type + +class TypeApacheRandomStringUtils extends Class { + TypeApacheRandomStringUtils() { + hasQualifiedName("org.apache.commons.lang", "RandomStringUtils") or + hasQualifiedName("org.apache.commons.lang3", "RandomStringUtils") + } +} diff --git a/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.expected b/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.expected new file mode 100644 index 000000000000..7234f316b6e4 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.expected @@ -0,0 +1,5 @@ +| vulnerable/RandomUtil.java:20:26:20:41 | generatePassword | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | +| vulnerable/RandomUtil.java:29:26:29:46 | generateActivationKey | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | +| vulnerable/RandomUtil.java:38:26:38:41 | generateResetKey | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | +| vulnerable/RandomUtil.java:48:26:48:43 | generateSeriesData | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | +| vulnerable/RandomUtil.java:57:26:57:42 | generateTokenData | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | diff --git a/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.qlref b/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.qlref new file mode 100644 index 000000000000..441bcf25929b --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql diff --git a/java/ql/test/query-tests/security/CWE-338/semmle/tests/fixed/RandomUtil.java b/java/ql/test/query-tests/security/CWE-338/semmle/tests/fixed/RandomUtil.java new file mode 100644 index 000000000000..076115bad7d0 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-338/semmle/tests/fixed/RandomUtil.java @@ -0,0 +1,71 @@ +package test.cwe338.cwe.examples.fixed; + +import org.apache.commons.lang3.RandomStringUtils; + +import java.security.SecureRandom; + +/** + * Utility class for generating random Strings. + */ +public final class RandomUtil { + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + + private static final int DEF_COUNT = 20; + + static { + SECURE_RANDOM.nextBytes(new byte[64]); + } + + private RandomUtil() { + } + + private static String generateRandomAlphanumericString() { + return RandomStringUtils.random(DEF_COUNT, 0, 0, true, true, null, SECURE_RANDOM); + } + + /** + * Generate a password. + * + * @return the generated password. + */ + public static String generatePassword() { + return generateRandomAlphanumericString(); + } + + /** + * Generate an activation key. + * + * @return the generated activation key. + */ + public static String generateActivationKey() { + return generateRandomAlphanumericString(); + } + + /** + * Generate a reset key. + * + * @return the generated reset key. + */ + public static String generateResetKey() { + return generateRandomAlphanumericString(); + } + + /** + * Generate a unique series to validate a persistent token, used in the + * authentication remember-me mechanism. + * + * @return the generated series data. + */ + public static String generateSeriesData() { + return generateRandomAlphanumericString(); + } + + /** + * Generate a persistent token, used in the authentication remember-me mechanism. + * + * @return the generated token data. + */ + public static String generateTokenData() { + return generateRandomAlphanumericString(); + } +} diff --git a/java/ql/test/query-tests/security/CWE-338/semmle/tests/options b/java/ql/test/query-tests/security/CWE-338/semmle/tests/options new file mode 100644 index 000000000000..2154f71c2258 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-338/semmle/tests/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/apache-commons-lang3-3.7 diff --git a/java/ql/test/query-tests/security/CWE-338/semmle/tests/vulnerable/RandomUtil.java b/java/ql/test/query-tests/security/CWE-338/semmle/tests/vulnerable/RandomUtil.java new file mode 100644 index 000000000000..22e0c0b91502 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-338/semmle/tests/vulnerable/RandomUtil.java @@ -0,0 +1,60 @@ +package test.cwe338.cwe.examples.vulnerable; + +import org.apache.commons.lang3.RandomStringUtils; + +/** + * Utility class for generating random Strings. + */ +public final class RandomUtil { + + private static final int DEF_COUNT = 20; + + private RandomUtil() { + } + + /** + * Generate a password. + * + * @return the generated password. + */ + public static String generatePassword() { + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + } + + /** + * Generate an activation key. + * + * @return the generated activation key. + */ + public static String generateActivationKey() { + return RandomStringUtils.randomNumeric(DEF_COUNT); + } + + /** + * Generate a reset key. + * + * @return the generated reset key. + */ + public static String generateResetKey() { + return RandomStringUtils.randomNumeric(DEF_COUNT); + } + + /** + * Generate a unique series to validate a persistent token, used in the + * authentication remember-me mechanism. + * + * @return the generated series data. + */ + public static String generateSeriesData() { + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + } + + /** + * Generate a persistent token, used in the authentication remember-me mechanism. + * + * @return the generated token data. + */ + public static String generateTokenData() { + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + } +} diff --git a/java/ql/test/stubs/apache-commons-lang3-3.7/LICENSE.txt b/java/ql/test/stubs/apache-commons-lang3-3.7/LICENSE.txt new file mode 100644 index 000000000000..f4f87bd4ed6d --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang3-3.7/LICENSE.txt @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + \ No newline at end of file diff --git a/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/RandomStringUtils.java b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/RandomStringUtils.java new file mode 100644 index 000000000000..e4066410ec85 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/RandomStringUtils.java @@ -0,0 +1,388 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 + * + * 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 org.apache.commons.lang3; + +import java.util.Random; + +/** + *

    Operations for random {@code String}s.

    + *

    Currently private high surrogate characters are ignored. + * These are Unicode characters that fall between the values 56192 (db80) + * and 56319 (dbff) as we don't know how to handle them. + * High and low surrogates are correctly dealt with - that is if a + * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f) + * then it is followed by a low surrogate. If a low surrogate is chosen, + * 56320 (dc00) to 57343 (dfff) then it is placed after a randomly + * chosen high surrogate.

    + *

    RandomStringUtils is intended for simple use cases. For more advanced + * use cases consider using commons-text + * + * RandomStringGenerator instead.

    + * + *

    #ThreadSafe#

    + * @since 1.0 + */ +public class RandomStringUtils { + + /** + *

    Random object used by random method. This has to be not local + * to the random method so as to not return the same value in the + * same millisecond.

    + */ + private static final Random RANDOM = new Random(); + + /** + *

    {@code RandomStringUtils} instances should NOT be constructed in + * standard programming. Instead, the class should be used as + * {@code RandomStringUtils.random(5);}.

    + * + *

    This constructor is public to permit tools that require a JavaBean instance + * to operate.

    + */ + public RandomStringUtils() { + super(); + } + + // Random + //----------------------------------------------------------------------- + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of all characters.

    + * + * @param count the length of random string to create + * @return the random string + */ + public static String random(final int count) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of characters whose + * ASCII value is between {@code 32} and {@code 126} (inclusive).

    + * + * @param count the length of random string to create + * @return the random string + */ + public static String randomAscii(final int count) { + return ""; + } + + /** + *

    Creates a random string whose length is between the inclusive minimum and + * the exclusive maximum.

    + * + *

    Characters will be chosen from the set of characters whose + * ASCII value is between {@code 32} and {@code 126} (inclusive).

    + * + * @param minLengthInclusive the inclusive minimum length of the string to generate + * @param maxLengthExclusive the exclusive maximum length of the string to generate + * @return the random string + * @since 3.5 + */ + public static String randomAscii(final int minLengthInclusive, final int maxLengthExclusive) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of Latin alphabetic + * characters (a-z, A-Z).

    + * + * @param count the length of random string to create + * @return the random string + */ + public static String randomAlphabetic(final int count) { + return ""; + } + + /** + *

    Creates a random string whose length is between the inclusive minimum and + * the exclusive maximum.

    + * + *

    Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).

    + * + * @param minLengthInclusive the inclusive minimum length of the string to generate + * @param maxLengthExclusive the exclusive maximum length of the string to generate + * @return the random string + * @since 3.5 + */ + public static String randomAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of Latin alphabetic + * characters (a-z, A-Z) and the digits 0-9.

    + * + * @param count the length of random string to create + * @return the random string + */ + public static String randomAlphanumeric(final int count) { + return ""; + } + + /** + *

    Creates a random string whose length is between the inclusive minimum and + * the exclusive maximum.

    + * + *

    Characters will be chosen from the set of Latin alphabetic + * characters (a-z, A-Z) and the digits 0-9.

    + * + * @param minLengthInclusive the inclusive minimum length of the string to generate + * @param maxLengthExclusive the exclusive maximum length of the string to generate + * @return the random string + * @since 3.5 + */ + public static String randomAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters specified.

    + * + *

    Characters will be chosen from the set of characters which match the POSIX [:graph:] + * regular expression character class. This class contains all visible ASCII characters + * (i.e. anything except spaces and control characters).

    + * + * @param count the length of random string to create + * @return the random string + * @since 3.5 + */ + public static String randomGraph(final int count) { + return ""; + } + + /** + *

    Creates a random string whose length is between the inclusive minimum and + * the exclusive maximum.

    + * + *

    Characters will be chosen from the set of \p{Graph} characters.

    + * + * @param minLengthInclusive the inclusive minimum length of the string to generate + * @param maxLengthExclusive the exclusive maximum length of the string to generate + * @return the random string + * @since 3.5 + */ + public static String randomGraph(final int minLengthInclusive, final int maxLengthExclusive) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of numeric + * characters.

    + * + * @param count the length of random string to create + * @return the random string + */ + public static String randomNumeric(final int count) { + return ""; + } + + /** + *

    Creates a random string whose length is between the inclusive minimum and + * the exclusive maximum.

    + * + *

    Characters will be chosen from the set of \p{Digit} characters.

    + * + * @param minLengthInclusive the inclusive minimum length of the string to generate + * @param maxLengthExclusive the exclusive maximum length of the string to generate + * @return the random string + * @since 3.5 + */ + public static String randomNumeric(final int minLengthInclusive, final int maxLengthExclusive) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters specified.

    + * + *

    Characters will be chosen from the set of characters which match the POSIX [:print:] + * regular expression character class. This class includes all visible ASCII characters and spaces + * (i.e. anything except control characters).

    + * + * @param count the length of random string to create + * @return the random string + * @since 3.5 + */ + public static String randomPrint(final int count) { + return ""; + } + + /** + *

    Creates a random string whose length is between the inclusive minimum and + * the exclusive maximum.

    + * + *

    Characters will be chosen from the set of \p{Print} characters.

    + * + * @param minLengthInclusive the inclusive minimum length of the string to generate + * @param maxLengthExclusive the exclusive maximum length of the string to generate + * @return the random string + * @since 3.5 + */ + public static String randomPrint(final int minLengthInclusive, final int maxLengthExclusive) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of alpha-numeric + * characters as indicated by the arguments.

    + * + * @param count the length of random string to create + * @param letters if {@code true}, generated string may include + * alphabetic characters + * @param numbers if {@code true}, generated string may include + * numeric characters + * @return the random string + */ + public static String random(final int count, final boolean letters, final boolean numbers) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of alpha-numeric + * characters as indicated by the arguments.

    + * + * @param count the length of random string to create + * @param start the position in set of chars to start at + * @param end the position in set of chars to end before + * @param letters if {@code true}, generated string may include + * alphabetic characters + * @param numbers if {@code true}, generated string may include + * numeric characters + * @return the random string + */ + public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers) { + return ""; + } + + /** + *

    Creates a random string based on a variety of options, using + * default source of randomness.

    + * + *

    This method has exactly the same semantics as + * {@link #random(int,int,int,boolean,boolean,char[],Random)}, but + * instead of using an externally supplied source of randomness, it uses + * the internal static {@link Random} instance.

    + * + * @param count the length of random string to create + * @param start the position in set of chars to start at + * @param end the position in set of chars to end before + * @param letters only allow letters? + * @param numbers only allow numbers? + * @param chars the set of chars to choose randoms from. + * If {@code null}, then it will use the set of all chars. + * @return the random string + * @throws ArrayIndexOutOfBoundsException if there are not + * {@code (end - start) + 1} characters in the set array. + */ + public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers, final char... chars) { + return ""; + } + + /** + *

    Creates a random string based on a variety of options, using + * supplied source of randomness.

    + * + *

    If start and end are both {@code 0}, start and end are set + * to {@code ' '} and {@code 'z'}, the ASCII printable + * characters, will be used, unless letters and numbers are both + * {@code false}, in which case, start and end are set to + * {@code 0} and {@link Character#MAX_CODE_POINT}. + * + *

    If set is not {@code null}, characters between start and + * end are chosen.

    + * + *

    This method accepts a user-supplied {@link Random} + * instance to use as a source of randomness. By seeding a single + * {@link Random} instance with a fixed seed and using it for each call, + * the same random sequence of strings can be generated repeatedly + * and predictably.

    + * + * @param count the length of random string to create + * @param start the position in set of chars to start at (inclusive) + * @param end the position in set of chars to end before (exclusive) + * @param letters only allow letters? + * @param numbers only allow numbers? + * @param chars the set of chars to choose randoms from, must not be empty. + * If {@code null}, then it will use the set of all chars. + * @param random a source of randomness. + * @return the random string + * @throws ArrayIndexOutOfBoundsException if there are not + * {@code (end - start) + 1} characters in the set array. + * @throws IllegalArgumentException if {@code count} < 0 or the provided chars array is empty. + * @since 2.0 + */ + public static String random(int count, int start, int end, final boolean letters, final boolean numbers, + final char[] chars, final Random random) { + return ""; + } + + + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of characters + * specified by the string, must not be empty. + * If null, the set of all characters is used.

    + * + * @param count the length of random string to create + * @param chars the String containing the set of characters to use, + * may be null, but must not be empty + * @return the random string + * @throws IllegalArgumentException if {@code count} < 0 or the string is empty. + */ + public static String random(final int count, final String chars) { + return ""; + } + + /** + *

    Creates a random string whose length is the number of characters + * specified.

    + * + *

    Characters will be chosen from the set of characters specified.

    + * + * @param count the length of random string to create + * @param chars the character array containing the set of characters to use, + * may be null + * @return the random string + * @throws IllegalArgumentException if {@code count} < 0. + */ + public static String random(final int count, final char... chars) { + return ""; + } + +} From 24fe3d066389f85240a6751f80b552d40da65f6c Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Tue, 22 Sep 2020 13:11:11 -0400 Subject: [PATCH 02/10] Apply suggestions from code review Co-authored-by: Felicity Chapman --- .../ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp index 8aa9f27c0288..b6bbf62622ee 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp @@ -3,7 +3,7 @@ "qhelp.dtd"> -

    This query detects instances of RandomUtil.java generated by a JHipster version vulnerable to CVE-2019-16303. +

    This query detects instances of RandomUtil.java generated by a JHipster version vulnerable to CVE-2019-16303.

    Using one password reset token from your app combined with the proof of concept (POC) linked below, an attacker can determine all future password reset tokens to be generated by this server. This allows an attacker to pick and choose what account they would like to takeover by sending account password reset requests for targeted accounts.

    @@ -16,7 +16,7 @@ This allows an attacker to pick and choose what account they would like to takeo -

    The example below shows the vulnerable RandomUtil class generated by JHipster. +

    The example below shows the vulnerable RandomUtil class generated by JHipster.

    Below is a fixed version of the RandomUtil class.

    @@ -26,7 +26,7 @@ This allows an attacker to pick and choose what account they would like to takeo -An automated refactoring rewrite module can be found here. +

    An automated refactoring rewrite module can be found here.

    From 8578bc5cf0f8f08153770e6206e877575b19634e Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Tue, 22 Sep 2020 15:02:00 -0400 Subject: [PATCH 03/10] Update java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp Co-authored-by: Felicity Chapman --- java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp index b6bbf62622ee..88a5474e5e8e 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp @@ -40,7 +40,7 @@ This allows an attacker to pick and choose what account they would like to takeo How I Hacked Hacker News (with arc security advisory) -
  • +
  • Research (Hacking Apache Commons RandomStringUtils): From 645d7c883114915937f002f99bb63a4a8bc8d903 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Tue, 22 Sep 2020 15:04:06 -0400 Subject: [PATCH 04/10] Fix documentation in `apache/Lang.qll` --- java/ql/src/semmle/code/java/frameworks/apache/Lang.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll index 2aa00a007f37..394ba2014ab5 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -1,6 +1,8 @@ -/* Definitions related to the Apache Commons Exec library. */ +/* Definitions related to the Apache Commons Lang library. */ import semmle.code.java.Type +/*--- Types ---*/ +/** The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`. */ class TypeApacheRandomStringUtils extends Class { TypeApacheRandomStringUtils() { hasQualifiedName("org.apache.commons.lang", "RandomStringUtils") or From 17603c80915c7598ea22fccd0af635348e411e82 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Wed, 23 Sep 2020 13:59:49 -0400 Subject: [PATCH 05/10] Update java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp Co-authored-by: Felicity Chapman --- java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp index 88a5474e5e8e..8c0bea090e69 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp @@ -17,7 +17,7 @@ This allows an attacker to pick and choose what account they would like to takeo

    The example below shows the vulnerable RandomUtil class generated by JHipster.

    - +

    Below is a fixed version of the RandomUtil class.

    From ab3772eaeb5d7740373e5a0885c6b8a481cfb923 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Thu, 1 Oct 2020 15:38:56 -0400 Subject: [PATCH 06/10] Update JHipster CodeQL query from code review --- .../CWE/CWE-338/JHipsterGeneratedPRNG.ql | 26 ++++++++++--------- .../tests/JHipsterGeneratedPRNG.expected | 10 +++---- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql index 9717b9ce7e06..b184b5d047fe 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql @@ -14,20 +14,23 @@ import semmle.code.java.frameworks.apache.Lang private class PredictableApacheRandomStringUtilsMethod extends Method { PredictableApacheRandomStringUtilsMethod() { - this.getDeclaringType() instanceof TypeApacheRandomStringUtils + this.getDeclaringType() instanceof TypeApacheRandomStringUtils and + // The one valid use of this type that uses SecureRandom as a source of data. + not this.getName() = "random" } } private class PredictableApacheRandomStringUtilsMethodAccess extends MethodAccess { PredictableApacheRandomStringUtilsMethodAccess() { - this.getMethod() instanceof PredictableApacheRandomStringUtilsMethod and - // The one valid use of this type that uses SecureRandom as a source of data. - not this.getMethod().getName() = "random" + this.getMethod() instanceof PredictableApacheRandomStringUtilsMethod } } private class VulnerableJHipsterRandomUtilClass extends Class { - VulnerableJHipsterRandomUtilClass() { getName() = "RandomUtil" } + VulnerableJHipsterRandomUtilClass() { + // The package name that JHipster generated the 'RandomUtil' class in was dynamic. Thus 'hasQualifiedName' can not be used here. + getName() = "RandomUtil" + } } private class VulnerableJHipsterRandomUtilMethod extends Method { @@ -35,14 +38,13 @@ private class VulnerableJHipsterRandomUtilMethod extends Method { this.getDeclaringType() instanceof VulnerableJHipsterRandomUtilClass and this.getName().matches("generate%") and this.getReturnType() instanceof TypeString and - exists(ReturnStmt s, PredictableApacheRandomStringUtilsMethodAccess access | - s = this.getBody().(SingletonBlock).getStmt() - | - s.getResult() = access + exists(ReturnStmt s | + s = this.getBody().(SingletonBlock).getStmt() and + s.getResult() instanceof PredictableApacheRandomStringUtilsMethodAccess ) } } -from VulnerableJHipsterRandomUtilMethod the_method -select the_method, - "RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303" +from VulnerableJHipsterRandomUtilMethod method +select method, + "Weak random number generator used in security sensitive method (JHipster CVE-2019-16303)." diff --git a/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.expected b/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.expected index 7234f316b6e4..0a2e98cc7cb6 100644 --- a/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.expected +++ b/java/ql/test/query-tests/security/CWE-338/semmle/tests/JHipsterGeneratedPRNG.expected @@ -1,5 +1,5 @@ -| vulnerable/RandomUtil.java:20:26:20:41 | generatePassword | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | -| vulnerable/RandomUtil.java:29:26:29:46 | generateActivationKey | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | -| vulnerable/RandomUtil.java:38:26:38:41 | generateResetKey | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | -| vulnerable/RandomUtil.java:48:26:48:43 | generateSeriesData | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | -| vulnerable/RandomUtil.java:57:26:57:42 | generateTokenData | RandomUtil was generated by JHipster Generator version vulnerable to CVE-2019-16303 | +| vulnerable/RandomUtil.java:20:26:20:41 | generatePassword | Weak random number generator used in security sensitive method (JHipster CVE-2019-16303). | +| vulnerable/RandomUtil.java:29:26:29:46 | generateActivationKey | Weak random number generator used in security sensitive method (JHipster CVE-2019-16303). | +| vulnerable/RandomUtil.java:38:26:38:41 | generateResetKey | Weak random number generator used in security sensitive method (JHipster CVE-2019-16303). | +| vulnerable/RandomUtil.java:48:26:48:43 | generateSeriesData | Weak random number generator used in security sensitive method (JHipster CVE-2019-16303). | +| vulnerable/RandomUtil.java:57:26:57:42 | generateTokenData | Weak random number generator used in security sensitive method (JHipster CVE-2019-16303). | From 8272d591b6a368a6a743e9ab4c0a08787bf49cea Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Mon, 5 Oct 2020 14:12:03 -0400 Subject: [PATCH 07/10] Apply suggestions from code review https://github.com/github/codeql/pull/4312 Co-authored-by: Felicity Chapman Co-authored-by: Arthur Baars --- .../CWE/CWE-338/JHipsterGeneratedPRNG.qhelp | 17 ++++++++++------- .../CWE/CWE-338/JHipsterGeneratedPRNG.ql | 4 ++-- .../semmle/code/java/frameworks/apache/Lang.qll | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp index 8c0bea090e69..075e18ad50f6 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp @@ -3,10 +3,10 @@ "qhelp.dtd"> -

    This query detects instances of RandomUtil.java generated by a JHipster version vulnerable to CVE-2019-16303.

    +

    This query detects instances of RandomUtil.java that were generated by a JHipster version that is vulnerable to CVE-2019-16303.

    -

    Using one password reset token from your app combined with the proof of concept (POC) linked below, an attacker can determine all future password reset tokens to be generated by this server. -This allows an attacker to pick and choose what account they would like to takeover by sending account password reset requests for targeted accounts.

    +

    If an app uses RandomUtil.java generated by a vulnerable version of JHipster, attackers can request a password reset token and use this to predict the value of future reset tokens generated by this server. +Using this information, they can create a reset link that allows them to take over any account.

    This vulnerability has a @@ -26,24 +26,27 @@ This allows an attacker to pick and choose what account they would like to takeo -

    An automated refactoring rewrite module can be found here.

    +

    You should refactor the RandomUtil class and replace every call to RandomStringUtils.randomAlphaNumeric. You could regenerate the class using the latest version of JHipster, or use an automated refactoring. For example, using the Patching JHipster CWE-338 for the Rewrite project. +

  • + Cloudflare Blog: - Cloudflare Blog: Why secure systems require random numbers + Why secure systems require random numbers
  • + Hacker News: How I Hacked Hacker News (with arc security advisory)
  • - Research (Hacking Apache Commons RandomStringUtils): - + Posts by Pucara Information Security Team: + The Java Soothsayer: A practical application for insecure randomness. (Includes free 0day)
  • diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql index b184b5d047fe..8eda68ebe703 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql @@ -1,6 +1,6 @@ /** - * @name Detect JHipster Generator Vulnnerability CVE-2019-16303 - * @description Detector for the CVE-2019-16303 vulnerability that existed in the JHipster code generator. + * @name Detect JHipster Generator Vulnerability CVE-2019-16303 + * @description Using a vulnerable version of JHipster to generate random numbers makes it easier for attackers to take over accounts. * @kind problem * @problem.severity error * @precision very-high diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll index 394ba2014ab5..b66b9f0b306a 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -1,4 +1,4 @@ -/* Definitions related to the Apache Commons Lang library. */ +/** Definitions related to the Apache Commons Lang library. */ import semmle.code.java.Type /*--- Types ---*/ From 895f4d0ea686b613c7feee25005b576e5fb6b169 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Mon, 12 Oct 2020 11:00:05 -0400 Subject: [PATCH 08/10] JHipster Vuln: Add GOOD/BAD & release note links --- .../Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp | 2 +- .../CWE/CWE-338/JHipsterGeneratedPRNGFixed.java | 3 ++- .../CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp index 075e18ad50f6..ba7192567bd6 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp @@ -16,7 +16,7 @@ Using this information, they can create a reset link that allows them to take ov -

    The example below shows the vulnerable RandomUtil class generated by JHipster.

    +

    The example below shows the vulnerable RandomUtil class generated by JHipster prior to version 6.3.0.

    Below is a fixed version of the RandomUtil class.

    diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGFixed.java b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGFixed.java index 42cf387806a6..02ef4e4a3fe0 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGFixed.java +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGFixed.java @@ -6,7 +6,7 @@ * Utility class for generating random Strings. */ public final class RandomUtil { - private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); // GOOD: Using SecureRandom private static final int DEF_COUNT = 20; @@ -18,6 +18,7 @@ private RandomUtil() { } private static String generateRandomAlphanumericString() { + // GOOD: Passing Secure Random to RandomStringUtils::random return RandomStringUtils.random(DEF_COUNT, 0, 0, true, true, null, SECURE_RANDOM); } diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java index d1a7f4cd9248..0532a8a9d3ca 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java @@ -16,7 +16,7 @@ private RandomUtil() { * @return the generated password. */ public static String generatePassword() { - return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom } /** @@ -25,7 +25,7 @@ public static String generatePassword() { * @return the generated activation key. */ public static String generateActivationKey() { - return RandomStringUtils.randomNumeric(DEF_COUNT); + return RandomStringUtils.randomNumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom } /** @@ -34,7 +34,7 @@ public static String generateActivationKey() { * @return the generated reset key. */ public static String generateResetKey() { - return RandomStringUtils.randomNumeric(DEF_COUNT); + return RandomStringUtils.randomNumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom } /** @@ -44,7 +44,7 @@ public static String generateResetKey() { * @return the generated series data. */ public static String generateSeriesData() { - return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom } /** @@ -53,6 +53,6 @@ public static String generateSeriesData() { * @return the generated token data. */ public static String generateTokenData() { - return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom } } From 48f4b6c058205c32585475e2e0ed6d27e11cb759 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Mon, 12 Oct 2020 11:16:21 -0400 Subject: [PATCH 09/10] Apply suggestions from code review Co-authored-by: Felicity Chapman --- .../CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java index 0532a8a9d3ca..996ef35038ee 100644 --- a/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java +++ b/java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNGVulnerable.java @@ -16,7 +16,7 @@ private RandomUtil() { * @return the generated password. */ public static String generatePassword() { - return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils does not use SecureRandom } /** @@ -25,7 +25,7 @@ public static String generatePassword() { * @return the generated activation key. */ public static String generateActivationKey() { - return RandomStringUtils.randomNumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom + return RandomStringUtils.randomNumeric(DEF_COUNT); // BAD: RandomStringUtils does not use SecureRandom } /** @@ -34,7 +34,7 @@ public static String generateActivationKey() { * @return the generated reset key. */ public static String generateResetKey() { - return RandomStringUtils.randomNumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom + return RandomStringUtils.randomNumeric(DEF_COUNT); // BAD: RandomStringUtils does not use SecureRandom } /** @@ -44,7 +44,7 @@ public static String generateResetKey() { * @return the generated series data. */ public static String generateSeriesData() { - return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils does not use SecureRandom } /** @@ -53,6 +53,6 @@ public static String generateSeriesData() { * @return the generated token data. */ public static String generateTokenData() { - return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils oes not use SecureRandom + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); // BAD: RandomStringUtils does not use SecureRandom } } From a9c5551284b64bda5cc23d65916ed4a997a3be57 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Thu, 15 Oct 2020 08:51:40 -0400 Subject: [PATCH 10/10] Fix formatting in Lang.qll --- java/ql/src/semmle/code/java/frameworks/apache/Lang.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll index b66b9f0b306a..e9a9ca742039 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -1,5 +1,6 @@ /** Definitions related to the Apache Commons Lang library. */ -import semmle.code.java.Type + +import java /*--- Types ---*/ /** The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`. */