Skip to content

Commit 2b33265

Browse files
Added a query for ignored hostname verification
- Added IgnoredHostnameVerification.ql - Added a qhelp file with examples - Added tests
1 parent f78002b commit 2b33265

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

java/ql/src/experimental/Security/CWE/CWE-297/IgnoredHostnameVerification.ql

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,43 @@
77
* @precision medium
88
* @id java/ignored-hostname-verification
99
* @tags security
10-
* external/cwe/cwe-295
10+
* external/cwe/cwe-297
1111
*/
1212

1313
import java
1414
import semmle.code.java.controlflow.Guards
15-
import semmle.code.java.dataflow.TaintTracking
15+
import semmle.code.java.dataflow.DataFlow
1616

17+
/** The `HostnameVerifier.verify()` method. */
18+
private class HostnameVerifierVerifyMethod extends Method {
19+
HostnameVerifierVerifyMethod() {
20+
this.getDeclaringType().getASupertype*().hasQualifiedName("javax.net.ssl", "HostnameVerifier") and
21+
this.hasStringSignature("verify(String, SSLSession)")
22+
}
23+
}
24+
25+
/** Defines `HostnameVerifier.verity()` calls that are not wrapped by another `HostnameVerifier`. */
1726
private class HostnameVerificationCall extends MethodAccess {
1827
HostnameVerificationCall() {
19-
getMethod()
20-
.getDeclaringType()
21-
.getASupertype*()
22-
.hasQualifiedName("javax.net.ssl", "HostnameVerifier") and
23-
getMethod().hasStringSignature("verify(String, SSLSession)")
28+
this.getMethod() instanceof HostnameVerifierVerifyMethod and
29+
not this.getCaller() instanceof HostnameVerifierVerifyMethod
2430
}
2531

26-
predicate ignored() {
32+
/** Holds if the result if the call is not useds. */
33+
predicate isIgnored() {
2734
not exists(
2835
DataFlow::Node source, DataFlow::Node sink, CheckFailedHostnameVerificationConfig config
2936
|
30-
this = source.asExpr()
31-
|
32-
config.hasFlow(source, sink)
37+
this = source.asExpr() and config.hasFlow(source, sink)
3338
)
3439
}
3540
}
3641

37-
private class CheckFailedHostnameVerificationConfig extends TaintTracking::Configuration {
42+
/**
43+
* A configuration that tracks data flows from the result of a `HostnameVerifier.vefiry()` call
44+
* to a condition that controls a throw statement.
45+
*/
46+
private class CheckFailedHostnameVerificationConfig extends DataFlow::Configuration {
3847
CheckFailedHostnameVerificationConfig() { this = "CheckFailedHostnameVerificationConfig" }
3948

4049
override predicate isSource(DataFlow::Node source) {
@@ -54,5 +63,5 @@ private class CheckFailedHostnameVerificationConfig extends TaintTracking::Confi
5463
}
5564

5665
from HostnameVerificationCall verification
57-
where verification.ignored()
58-
select verification, "Ignored result of hostname verification."
66+
where verification.isIgnored()
67+
select verification, "Ignored result of hostname verification."

java/ql/test/experimental/query-tests/security/CWE-297/IgnoredHostnameVerification.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import java.io.IOException;
22
import javax.net.ssl.HostnameVerifier;
33
import javax.net.ssl.SSLException;
4+
import javax.net.ssl.SSLSession;
45
import javax.net.ssl.SSLSocket;
56
import javax.net.ssl.SSLSocketFactory;
67

@@ -89,4 +90,19 @@ public static SSLSocket connectWithHostnameVerification03(
8990
throw new SSLException("Oops! Hostname verification failed!");
9091
}
9192

92-
}
93+
public static class HostnameVerifierWrapper implements HostnameVerifier {
94+
95+
private final HostnameVerifier verifier;
96+
97+
public HostnameVerifierWrapper(HostnameVerifier verifier) {
98+
this.verifier = verifier;
99+
}
100+
101+
@Override
102+
public boolean verify(String hostname, SSLSession session) {
103+
return verifier.verify(hostname, session); // GOOD: wrapped calls should not be reported
104+
}
105+
106+
}
107+
108+
}

0 commit comments

Comments
 (0)