Skip to content

Commit c2c85d3

Browse files
Java: Added a query for timing attacks
1 parent cb686ea commit c2c85d3

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* @name Using a not-constant time algorithm for comparison results of a cryptographic operation
3+
* @description When comparing results of a cryptographic operation, a constant time algorithm should be used.
4+
* Otherwise, an attacker may be able to implement a timing attack.
5+
* A successful attack may result in leaking secrets or authentication bypass.
6+
* @kind path-problem
7+
* @problem.severity error
8+
* @precision high
9+
* @id java/not-constant-time-crypto-comparison
10+
* @tags security
11+
* external/cwe/cwe-208
12+
*/
13+
14+
import java
15+
import semmle.code.java.dataflow.TaintTracking
16+
import DataFlow::PathGraph
17+
18+
/**
19+
* A method that returns a result of a cryptographic operation
20+
* such as encryption, decryption, signing, etc.
21+
*/
22+
private class ReturnCryptoOperatinoResultMethod extends Method {
23+
ReturnCryptoOperatinoResultMethod() {
24+
getDeclaringType().hasQualifiedName("javax.crypto", ["Mac", "Cipher"]) and
25+
hasName("doFinal")
26+
or
27+
getDeclaringType().hasQualifiedName("java.security", "Signature") and
28+
hasName("sign")
29+
or
30+
getDeclaringType().hasQualifiedName("java.security", "MessageDigest") and
31+
hasName("digest")
32+
}
33+
}
34+
35+
/**
36+
* A configuration that tracks data flows from cryptographic operations
37+
* to methods that compare data using a not-constant time algorithm.
38+
*/
39+
private class NotConstantTimeCryptoComparisonConfig extends TaintTracking::Configuration {
40+
NotConstantTimeCryptoComparisonConfig() { this = "NotConstantTimeCryptoComparisonConfig" }
41+
42+
override predicate isSource(DataFlow::Node source) {
43+
exists(MethodAccess ma | ma.getMethod() instanceof ReturnCryptoOperatinoResultMethod |
44+
ma = source.asExpr()
45+
)
46+
}
47+
48+
override predicate isSink(DataFlow::Node sink) {
49+
exists(MethodAccess ma, Method m | m = ma.getMethod() |
50+
m.getDeclaringType() instanceof TypeString and
51+
m.hasName(["equals", "contentEquals", "equalsIgnoreCase"]) and
52+
sink.asExpr() = [ma.getQualifier(), ma.getAnArgument()]
53+
or
54+
m.getDeclaringType().hasQualifiedName("java.util", "Arrays") and
55+
m.hasName("equals") and
56+
ma.getAnArgument() = sink.asExpr()
57+
or
58+
m.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "StringUtils") and
59+
m.hasName(["equals", "equalsAny", "equalsAnyIgnoreCase", "equalsIgnoreCase"]) and
60+
ma.getAnArgument() = sink.asExpr()
61+
)
62+
}
63+
}
64+
65+
from DataFlow::PathNode source, DataFlow::PathNode sink, NotConstantTimeCryptoComparisonConfig conf
66+
where conf.hasFlowPath(source, sink)
67+
select sink.getNode(), source, sink,
68+
"Using a not-constant time algorithm for comparison results of a cryptographic operation."

0 commit comments

Comments
 (0)