mirror of
https://github.com/github/codeql.git
synced 2025-12-22 03:36:30 +01:00
Merge pull request #4312 from JLLeitschuh/feat/JLL/java/jhipster_CVE-2019-16303
Java: QL Query Detector for JHipster Generated CVE-2019-16303
This commit is contained in:
58
java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp
Normal file
58
java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.qhelp
Normal file
@@ -0,0 +1,58 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>This query detects instances of <code>RandomUtil.java</code> that were generated by a <a href="https://www.jhipster.tech/">JHipster</a> version that is vulnerable to <a href="https://github.com/jhipster/jhipster-kotlin/security/advisories/GHSA-j3rh-8vwq-wh84">CVE-2019-16303</a>.</p>
|
||||
|
||||
<p>If an app uses <code>RandomUtil.java</code> 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.</p>
|
||||
|
||||
<p>This vulnerability has a
|
||||
<a href="https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?name=CVE-2019-16303&vector=AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H&version=3.1&source=NIST">
|
||||
CVSS v3.0 Base Score of 9.8/10
|
||||
</a>.</p>
|
||||
</overview>
|
||||
|
||||
<example>
|
||||
|
||||
<p>The example below shows the vulnerable <code>RandomUtil</code> class generated by <a href="https://www.jhipster.tech/2019/09/13/jhipster-release-6.3.0.html">JHipster prior to version 6.3.0</a>.</p>
|
||||
<sample src="JHipsterGeneratedPRNGVulnerable.java" />
|
||||
|
||||
<p>Below is a fixed version of the <code>RandomUtil</code> class.</p>
|
||||
<sample src="JHipsterGeneratedPRNGFixed.java" />
|
||||
|
||||
</example>
|
||||
|
||||
<recommendation>
|
||||
|
||||
<p>You should refactor the <code>RandomUtil</code> class and replace every call to <code>RandomStringUtils.randomAlphaNumeric</code>. You could regenerate the class using the latest version of JHipster, or use an automated refactoring. For example, using the <a href="https://github.com/moderneinc/jhipster-cwe-338">Patching JHipster CWE-338</a> for the <a href="https://github.com/openrewrite/rewrite">Rewrite project</a>.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<references>
|
||||
|
||||
<li>
|
||||
Cloudflare Blog:
|
||||
<a href="https://blog.cloudflare.com/why-randomness-matters/">
|
||||
Why secure systems require random numbers
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
Hacker News:
|
||||
<a href="https://news.ycombinator.com/item?id=639976">
|
||||
How I Hacked Hacker News (with arc security advisory)
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
Posts by Pucara Information Security Team:
|
||||
<a href="https://blog.pucarasec.com/2020/05/09/the-java-soothsayer-a-practical-application-for-insecure-randomness-includes-free-0day/">
|
||||
The Java Soothsayer: A practical application for insecure randomness. (Includes free 0day)
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- LocalWords: CWE random RNG PRNG CSPRNG SecureRandom JHipster -->
|
||||
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
50
java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql
Normal file
50
java/ql/src/Security/CWE/CWE-338/JHipsterGeneratedPRNG.ql
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @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
|
||||
* @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 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
|
||||
}
|
||||
}
|
||||
|
||||
private class VulnerableJHipsterRandomUtilClass extends Class {
|
||||
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 {
|
||||
VulnerableJHipsterRandomUtilMethod() {
|
||||
this.getDeclaringType() instanceof VulnerableJHipsterRandomUtilClass and
|
||||
this.getName().matches("generate%") and
|
||||
this.getReturnType() instanceof TypeString and
|
||||
exists(ReturnStmt s |
|
||||
s = this.getBody().(SingletonBlock).getStmt() and
|
||||
s.getResult() instanceof PredictableApacheRandomStringUtilsMethodAccess
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from VulnerableJHipsterRandomUtilMethod method
|
||||
select method,
|
||||
"Weak random number generator used in security sensitive method (JHipster CVE-2019-16303)."
|
||||
@@ -0,0 +1,70 @@
|
||||
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(); // GOOD: Using SecureRandom
|
||||
|
||||
private static final int DEF_COUNT = 20;
|
||||
|
||||
static {
|
||||
SECURE_RANDOM.nextBytes(new byte[64]);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -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); // BAD: RandomStringUtils does not use SecureRandom
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an activation key.
|
||||
*
|
||||
* @return the generated activation key.
|
||||
*/
|
||||
public static String generateActivationKey() {
|
||||
return RandomStringUtils.randomNumeric(DEF_COUNT); // BAD: RandomStringUtils does not use SecureRandom
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a reset key.
|
||||
*
|
||||
* @return the generated reset key.
|
||||
*/
|
||||
public static String generateResetKey() {
|
||||
return RandomStringUtils.randomNumeric(DEF_COUNT); // BAD: RandomStringUtils does not use SecureRandom
|
||||
}
|
||||
|
||||
/**
|
||||
* 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); // BAD: RandomStringUtils does not use SecureRandom
|
||||
}
|
||||
|
||||
/**
|
||||
* 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); // BAD: RandomStringUtils does not use SecureRandom
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user