-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathReusedNonce.ql
More file actions
88 lines (79 loc) · 3.07 KB
/
ReusedNonce.ql
File metadata and controls
88 lines (79 loc) · 3.07 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
/**
* @name Reuse of cryptographic nonce
* @description Reuse of nonce in cryptographic operations can lead to vulnerabilities.
* @id java/quantum/examples/reused-nonce
* @kind path-problem
* @problem.severity error
* @tags quantum
* experimental
*/
import java
import ArtifactReuse
module NonceSrcFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::GenericSourceInstance i).getOutputNode() or
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
}
predicate isSink(DataFlow::Node sink) {
exists(Crypto::NonceArtifactNode nonce | sink.asExpr() = nonce.asElement())
}
predicate isBarrierOut(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getInputNode()
}
predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
or
exists(MethodCall m |
m.getMethod().hasQualifiedName("java.lang", "String", "getBytes") and
node1.asExpr() = m.getQualifier() and
node2.asExpr() = m
)
}
}
module NonceSrcFlow = TaintTracking::Global<NonceSrcFlowConfig>;
import NonceSrcFlow::PathGraph
from
Crypto::NonceArtifactNode nonce1, Crypto::NonceArtifactNode nonce2, Crypto::NodeBase src,
NonceSrcFlow::PathNode srcNode, NonceSrcFlow::PathNode sinkNode
where
isArtifactReuse(nonce1, nonce2) and
// NOTE: in general we may not know a source, but see possible reuse,
// we are not detecting these cases here (only where the source is the same).
src = nonce1.getSourceNode() and
src = nonce2.getSourceNode() and
// Null literals are typically used for initialization, and if two 'nulls'
// are reused, it is likely an uninitialization path that would result in a NullPointerException.
not src.asElement() instanceof NullLiteral and
// if the nonce is used in an encryption and decryption, ignore that reuse
not exists(Crypto::CipherOperationNode op1, Crypto::CipherOperationNode op2 |
op1 != op2 and
op1.getANonce() = nonce1 and
op2.getANonce() = nonce2 and
(
(
op1.getKeyOperationSubtype() instanceof Crypto::TEncryptMode or
op1.getKeyOperationSubtype() instanceof Crypto::TWrapMode
) and
(
op2.getKeyOperationSubtype() instanceof Crypto::TDecryptMode or
op2.getKeyOperationSubtype() instanceof Crypto::TUnwrapMode
)
or
(
op2.getKeyOperationSubtype() instanceof Crypto::TEncryptMode or
op2.getKeyOperationSubtype() instanceof Crypto::TWrapMode
) and
(
op1.getKeyOperationSubtype() instanceof Crypto::TDecryptMode or
op1.getKeyOperationSubtype() instanceof Crypto::TUnwrapMode
)
)
) and
srcNode.getNode().asExpr() = src.asElement() and
sinkNode.getNode().asExpr() = nonce1.asElement() and
NonceSrcFlow::flowPath(srcNode, sinkNode)
select sinkNode, srcNode, sinkNode, "Nonce source is reused, see alternate sink $@", nonce2,
nonce2.toString()