Skip to content

Commit 56921a6

Browse files
authored
Merge pull request #14040 from egregius313/egregius313/weak-hashing-properties
Java: Add support for algorithm names specified in `.properties` files to `java/potentially-weak-cryptographic-algorithm`
2 parents d5f47a3 + 0524289 commit 56921a6

File tree

7 files changed

+78
-7
lines changed

7 files changed

+78
-7
lines changed

java/ql/lib/semmle/code/java/frameworks/Properties.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import semmle.code.java.Type
44
private import semmle.code.java.dataflow.FlowSteps
5+
private import semmle.code.configfiles.ConfigFiles
6+
private import semmle.code.java.dataflow.RangeUtils
57

68
/**
79
* The `java.util.Properties` class.
@@ -43,3 +45,22 @@ class PropertiesStoreMethod extends Method {
4345
(this.getName().matches("store%") or this.getName() = "save")
4446
}
4547
}
48+
49+
/**
50+
* A call to the `getProperty` method of the class `java.util.Properties`.
51+
*/
52+
class PropertiesGetPropertyMethodCall extends MethodCall {
53+
PropertiesGetPropertyMethodCall() { this.getMethod() instanceof PropertiesGetPropertyMethod }
54+
55+
private ConfigPair getPair() {
56+
this.getArgument(0).(ConstantStringExpr).getStringValue() = result.getNameElement().getName()
57+
}
58+
59+
/**
60+
* Get the potential string values that can be associated with the given property name.
61+
*/
62+
string getPropertyValue() {
63+
result = this.getPair().getValueElement().getValue() or
64+
result = this.getArgument(1).(ConstantStringExpr).getStringValue()
65+
}
66+
}

java/ql/lib/semmle/code/java/security/MaybeBrokenCryptoAlgorithmQuery.qll

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
*/
44

55
import java
6+
private import semmle.code.configfiles.ConfigFiles
67
private import semmle.code.java.security.Encryption
78
private import semmle.code.java.dataflow.TaintTracking
9+
private import semmle.code.java.dataflow.RangeUtils
810
private import semmle.code.java.dispatch.VirtualDispatch
11+
private import semmle.code.java.frameworks.Properties
912

1013
private class ShortStringLiteral extends StringLiteral {
1114
ShortStringLiteral() { this.getValue().length() < 100 }
@@ -38,7 +41,15 @@ private predicate objectToString(MethodCall ma) {
3841
* A taint-tracking configuration to reason about the use of potentially insecure cryptographic algorithms.
3942
*/
4043
module InsecureCryptoConfig implements DataFlow::ConfigSig {
41-
predicate isSource(DataFlow::Node n) { n.asExpr() instanceof InsecureAlgoLiteral }
44+
predicate isSource(DataFlow::Node n) {
45+
n.asExpr() instanceof InsecureAlgoLiteral
46+
or
47+
exists(PropertiesGetPropertyMethodCall mc | n.asExpr() = mc |
48+
// Since properties pairs are not included in the java/weak-crypto-algorithm,
49+
// The check for values from properties files can be less strict than `InsecureAlgoLiteral`.
50+
not mc.getPropertyValue().regexpMatch(getSecureAlgorithmRegex())
51+
)
52+
}
4253

4354
predicate isSink(DataFlow::Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) }
4455

java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,27 @@
1313

1414
import java
1515
import semmle.code.java.security.Encryption
16+
import semmle.code.java.dataflow.DataFlow
17+
import semmle.code.java.frameworks.Properties
1618
import semmle.code.java.security.MaybeBrokenCryptoAlgorithmQuery
1719
import InsecureCryptoFlow::PathGraph
1820

19-
from
20-
InsecureCryptoFlow::PathNode source, InsecureCryptoFlow::PathNode sink, CryptoAlgoSpec c,
21-
InsecureAlgoLiteral s
21+
/**
22+
* Get the string value represented by the given expression.
23+
*
24+
* If the value is a string literal, get the literal value.
25+
* If the value is a call to `java.util.Properties::getProperty`, get the potential values of the property.
26+
*/
27+
string getStringValue(DataFlow::Node algo) {
28+
result = algo.asExpr().(StringLiteral).getValue()
29+
or
30+
result = algo.asExpr().(PropertiesGetPropertyMethodCall).getPropertyValue()
31+
}
32+
33+
from InsecureCryptoFlow::PathNode source, InsecureCryptoFlow::PathNode sink, CryptoAlgoSpec c
2234
where
2335
sink.getNode().asExpr() = c.getAlgoSpec() and
24-
source.getNode().asExpr() = s and
2536
InsecureCryptoFlow::flowPath(source, sink)
2637
select c, source, sink,
27-
"Cryptographic algorithm $@ may not be secure, consider using a different algorithm.", s,
28-
s.getValue()
38+
"Cryptographic algorithm $@ may not be secure, consider using a different algorithm.", source,
39+
getStringValue(source.getNode())
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Modified the `java/potentially-weak-cryptographic-algorithm` query to include the use of weak cryptographic algorithms from configuration values specified in properties files.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
edges
22
nodes
33
| Test.java:34:48:34:52 | "foo" | semmle.label | "foo" |
4+
| WeakHashing.java:15:55:15:83 | getProperty(...) | semmle.label | getProperty(...) |
45
subpaths
56
#select
67
| Test.java:34:21:34:53 | new SecretKeySpec(...) | Test.java:34:48:34:52 | "foo" | Test.java:34:48:34:52 | "foo" | Cryptographic algorithm $@ may not be secure, consider using a different algorithm. | Test.java:34:48:34:52 | "foo" | foo |
8+
| WeakHashing.java:15:29:15:84 | getInstance(...) | WeakHashing.java:15:55:15:83 | getProperty(...) | WeakHashing.java:15:55:15:83 | getProperty(...) | Cryptographic algorithm $@ may not be secure, consider using a different algorithm. | WeakHashing.java:15:55:15:83 | getProperty(...) | MD5 |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package test.cwe327.semmle.tests;
2+
3+
import java.util.Properties;
4+
import java.io.FileInputStream;
5+
import java.io.IOException;
6+
import java.security.MessageDigest;
7+
import java.security.NoSuchAlgorithmException;
8+
9+
public class WeakHashing {
10+
void hashing() throws NoSuchAlgorithmException, IOException {
11+
java.util.Properties props = new java.util.Properties();
12+
props.load(new FileInputStream("example.properties"));
13+
14+
// BAD: Using a weak hashing algorithm
15+
MessageDigest bad = MessageDigest.getInstance(props.getProperty("hashAlg1"));
16+
17+
// GOOD: Using a strong hashing algorithm
18+
MessageDigest ok = MessageDigest.getInstance(props.getProperty("hashAlg2"));
19+
}
20+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
hashAlg1=MD5
2+
hashAlg2=SHA-256

0 commit comments

Comments
 (0)