Add support for Commons-Lang's RandomUtils

This is realised by somewhat generalising our interfaces for modelling RNGs. We also add tests for randomness-related queries that didn't have any, and addtest cases checking the Apache random-number generators are interchangeable with the stdlib ones.
This commit is contained in:
Chris Smowton
2021-03-05 11:40:11 +00:00
parent 8d292070a4
commit e3cf5c235e
30 changed files with 464 additions and 149 deletions

View File

@@ -1,6 +1,7 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.DefUse
import semmle.code.java.security.Random
private import BoundingChecks
/**
@@ -124,33 +125,16 @@ abstract class BoundedFlowSource extends DataFlow::Node {
}
/**
* Input that is constructed using a `Random` value.
* Input that is constructed using a random value.
*/
class RandomValueFlowSource extends BoundedFlowSource {
RandomValueFlowSource() {
exists(RefType random, MethodAccess nextAccess |
random.hasQualifiedName("java.util", "Random")
|
nextAccess.getCallee().getDeclaringType().getAnAncestor() = random and
nextAccess.getCallee().getName().matches("next%") and
nextAccess = this.asExpr()
)
}
RandomDataSource nextAccess;
override int lowerBound() {
// If this call is to `nextInt()`, the lower bound is zero.
this.asExpr().(MethodAccess).getCallee().hasName("nextInt") and
this.asExpr().(MethodAccess).getNumArgument() = 1 and
result = 0
}
RandomValueFlowSource() { this.asExpr() = nextAccess }
override int upperBound() {
// If this call specified an argument to `nextInt()`, and that argument is a compile time constant,
// it forms the upper bound.
this.asExpr().(MethodAccess).getCallee().hasName("nextInt") and
this.asExpr().(MethodAccess).getNumArgument() = 1 and
result = this.asExpr().(MethodAccess).getArgument(0).(CompileTimeConstantExpr).getIntValue()
}
override int lowerBound() { result = nextAccess.getLowerBound() }
override int upperBound() { result = nextAccess.getUpperBound() }
override string getDescription() { result = "Random value" }
}

View File

@@ -13,34 +13,14 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.Random
import semmle.code.java.security.SecurityTests
import ArithmeticCommon
import DataFlow::PathGraph
class TaintSource extends DataFlow::ExprNode {
TaintSource() {
// Either this is an access to a random number generating method of the right kind, ...
exists(Method def |
def = this.getExpr().(MethodAccess).getMethod() and
(
// Some random-number methods are omitted:
// `nextDouble` and `nextFloat` are between 0 and 1,
// `nextGaussian` is extremely unlikely to hit max values.
def.getName() = "nextInt" or
def.getName() = "nextLong"
) and
def.getNumberOfParameters() = 0 and
def.getDeclaringType().hasQualifiedName("java.util", "Random")
)
or
// ... or this is the array parameter of `nextBytes`, which is filled with random bytes.
exists(MethodAccess m, Method def |
m.getAnArgument() = this.getExpr() and
m.getMethod() = def and
def.getName() = "nextBytes" and
def.getNumberOfParameters() = 1 and
def.getDeclaringType().hasQualifiedName("java.util", "Random")
)
exists(RandomDataSource m | not m.resultMayBeBounded() | m.getOutput() = this.getExpr())
}
}