-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathInsecureRandomness.ql
More file actions
108 lines (95 loc) · 3.61 KB
/
InsecureRandomness.ql
File metadata and controls
108 lines (95 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
* @name Insecure randomness
* @description Using a cryptographically weak pseudo-random number generator to generate a
* security sensitive value may allow an attacker to predict what sensitive value will
* be generated.
* @kind problem
* @problem.severity warning
* @precision high
* @id cs/insecure-randomness
* @tags security
* external/cwe/cwe-338
*/
import csharp
import semmle.code.csharp.frameworks.Test
module Random {
import semmle.code.csharp.dataflow.flowsources.Remote
import semmle.code.csharp.security.SensitiveActions
/**
* A data flow sink for insecure randomness in security sensitive context.
*/
abstract class Sink extends DataFlow::ExprNode { }
/**
* A data flow source for insecure randomness in security sensitive context.
*/
abstract class Source extends DataFlow::ExprNode { }
/**
* A sanitizer for insecure randomness in security sensitive context.
*/
abstract class Sanitizer extends DataFlow::ExprNode { }
/**
* A taint-tracking configuration for insecure randomness in security sensitive context.
*/
class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() {
this = "RandomDataFlowConfiguration"
}
override predicate isSource(DataFlow::Node source) {
source instanceof Source
}
override predicate isSink(DataFlow::Node sink) {
sink instanceof Sink
}
override predicate isSanitizer(DataFlow::Node node) {
node instanceof Sanitizer
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
// succ = array_or_indexer[pred] - use of random numbers in an index
succ.asExpr().(ElementAccess).getAnIndex() = pred.asExpr()
}
}
/** A source of cryptographically insecure random numbers. */
class RandomSource extends Source {
RandomSource() {
this.getExpr() = any(MethodCall mc | mc.getQualifier().getType().(RefType).hasQualifiedName("System", "Random"))
}
}
/** A value assigned to a property, variable or parameter which holds security sensitive data. */
class SensitiveSink extends Sink {
SensitiveSink() {
exists(Expr e |
// Simple assignment
e = this.getExpr() |
e = any(SensitiveVariable v).getAnAssignedValue() or
e = any(SensitiveProperty v).getAnAssignedValue() or
e = any(SensitiveLibraryParameter v).getAnAssignedArgument() or
// Assignment operation, e.g. += or similar
exists(AssignOperation ao |
ao.getRValue() = e and
// "expanded" assignments will be covered by simple assignment
not ao.hasExpandedAssignment() |
ao.getLValue() = any(SensitiveVariable v).getAnAccess() or
ao.getLValue() = any(SensitiveProperty v).getAnAccess() or
ao.getLValue() = any(SensitiveLibraryParameter v).getAnAccess()
)
)
}
}
/**
* Stop tracking beyond first assignment to sensitive element, so as to remove duplication in the
* reported results.
*/
class AlreadyTrackedSanitizer extends Sanitizer {
AlreadyTrackedSanitizer() {
exists(Expr e |
e = this.getExpr() |
e = any(SensitiveVariable v).getAnAccess() or
e = any(SensitiveProperty v).getAnAccess() or
e = any(SensitiveLibraryParameter v).getAnAccess()
)
}
}
}
from Random::TaintTrackingConfiguration randomTracking, Random::Source source, Random::Sink sink
where randomTracking.hasFlow(source, sink)
select sink, "Cryptographically insecure random number is generated at $@ and used here in a security context.", source, source.toString()