Skip to content

Commit 3d9e8a2

Browse files
authored
Combine best of PR #1643: handle += compound assignment and ignore dead-code returns
1 parent 677afff commit 3d9e8a2

3 files changed

Lines changed: 84 additions & 17 deletions

File tree

csharp/ql/src/Security Features/CWE-295/AcceptAnyCertificate.ql

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import AcceptAnyCertificate::PathGraph
2121
*/
2222
predicate alwaysReturnsTrue(Callable c) {
2323
c.getReturnType() instanceof BoolType and
24-
// There is at least one returned value, and every returned value is the
25-
// constant `true`.
26-
forex(Expr ret | c.canReturn(ret) | ret.getValue() = "true")
24+
// There is at least one live returned value, and every live returned value is
25+
// the constant `true`. Dead (unreachable) returns are ignored.
26+
forex(Expr ret | c.canReturn(ret) and ret.isLive() | ret.getValue() = "true")
2727
}
2828

2929
/**
@@ -59,6 +59,21 @@ Callable getAcceptingCallable(Expr e) {
5959
alwaysReturnsTrue(result)
6060
}
6161

62+
/**
63+
* Gets the expression that produces the delegate value assigned to `a`,
64+
* handling both simple assignments (`a = ...`) and compound assignments such as
65+
* `a += ...` (used to combine delegates).
66+
*/
67+
Expr getAssignedDelegate(Assignable a) {
68+
exists(Expr source | source = a.getAnAssignedValue() |
69+
// `a += ...` combines delegates; the delegate value is the right operand.
70+
result = source.(AssignOperation).getRightOperand()
71+
or
72+
// `a = ...` assigns the delegate value directly.
73+
result = source and not source instanceof AssignOperation
74+
)
75+
}
76+
6277
module AcceptAnyCertificateConfig implements DataFlow::ConfigSig {
6378
predicate isSource(DataFlow::Node source) {
6479
exists(getAcceptingCallable(source.asExpr()))
@@ -77,7 +92,7 @@ module AcceptAnyCertificateConfig implements DataFlow::ConfigSig {
7792
// validation callback type.
7893
exists(Assignable a |
7994
a.getType() instanceof CertificateValidationCallbackType and
80-
sink.asExpr() = a.getAnAssignedValue()
95+
sink.asExpr() = getAssignedDelegate(a)
8196
)
8297
or
8398
// The value passed as a certificate validation callback argument, e.g. to
Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
edges
2-
| Test.cs:64:45:64:52 | access to local variable callback : (...) => ... | Test.cs:67:48:67:55 | access to local variable callback | provenance | |
3-
| Test.cs:65:13:65:56 | (...) => ... : (...) => ... | Test.cs:64:45:64:52 | access to local variable callback : (...) => ... | provenance | |
2+
| Test.cs:88:45:88:52 | access to local variable callback : (...) => ... | Test.cs:91:48:91:55 | access to local variable callback | provenance | |
3+
| Test.cs:89:13:89:56 | (...) => ... : (...) => ... | Test.cs:88:45:88:52 | access to local variable callback : (...) => ... | provenance | |
44
nodes
55
| Test.cs:14:13:14:57 | (...) => ... | semmle.label | (...) => ... |
66
| Test.cs:22:13:25:13 | (...) => ... | semmle.label | (...) => ... |
77
| Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | semmle.label | access to property DangerousAcceptAnyServerCertificateValidator |
88
| Test.cs:40:13:40:56 | (...) => ... | semmle.label | (...) => ... |
9-
| Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | semmle.label | delegate creation of type RemoteCertificateValidationCallback |
10-
| Test.cs:59:13:59:56 | (...) => ... | semmle.label | (...) => ... |
11-
| Test.cs:64:45:64:52 | access to local variable callback : (...) => ... | semmle.label | access to local variable callback : (...) => ... |
12-
| Test.cs:65:13:65:56 | (...) => ... | semmle.label | (...) => ... |
13-
| Test.cs:65:13:65:56 | (...) => ... : (...) => ... | semmle.label | (...) => ... : (...) => ... |
14-
| Test.cs:67:48:67:55 | access to local variable callback | semmle.label | access to local variable callback |
9+
| Test.cs:47:13:47:61 | (...) => ... | semmle.label | (...) => ... |
10+
| Test.cs:49:68:49:87 | (...) => ... | semmle.label | (...) => ... |
11+
| Test.cs:51:68:51:92 | delegate(...) { ... } | semmle.label | delegate(...) { ... } |
12+
| Test.cs:69:67:69:75 | delegate creation of type RemoteCertificateValidationCallback | semmle.label | delegate creation of type RemoteCertificateValidationCallback |
13+
| Test.cs:76:13:76:76 | delegate creation of type RemoteCertificateValidationCallback | semmle.label | delegate creation of type RemoteCertificateValidationCallback |
14+
| Test.cs:83:13:83:56 | (...) => ... | semmle.label | (...) => ... |
15+
| Test.cs:88:45:88:52 | access to local variable callback : (...) => ... | semmle.label | access to local variable callback : (...) => ... |
16+
| Test.cs:89:13:89:56 | (...) => ... | semmle.label | (...) => ... |
17+
| Test.cs:89:13:89:56 | (...) => ... : (...) => ... | semmle.label | (...) => ... : (...) => ... |
18+
| Test.cs:91:48:91:55 | access to local variable callback | semmle.label | access to local variable callback |
1519
subpaths
1620
#select
1721
| Test.cs:14:13:14:57 | (...) => ... | Test.cs:14:13:14:57 | (...) => ... | Test.cs:14:13:14:57 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:14:13:14:57 | (...) => ... | uses a callback |
1822
| Test.cs:22:13:25:13 | (...) => ... | Test.cs:22:13:25:13 | (...) => ... | Test.cs:22:13:25:13 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:22:13:25:13 | (...) => ... | uses a callback |
1923
| Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | This TLS certificate validation $@, which trusts any certificate. | Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | uses a callback |
2024
| Test.cs:40:13:40:56 | (...) => ... | Test.cs:40:13:40:56 | (...) => ... | Test.cs:40:13:40:56 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:40:13:40:56 | (...) => ... | uses a callback |
21-
| Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | This TLS certificate validation $@, which trusts any certificate. | Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | uses a callback |
22-
| Test.cs:59:13:59:56 | (...) => ... | Test.cs:59:13:59:56 | (...) => ... | Test.cs:59:13:59:56 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:59:13:59:56 | (...) => ... | uses a callback |
23-
| Test.cs:65:13:65:56 | (...) => ... | Test.cs:65:13:65:56 | (...) => ... | Test.cs:65:13:65:56 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:65:13:65:56 | (...) => ... | uses a callback |
24-
| Test.cs:67:48:67:55 | access to local variable callback | Test.cs:65:13:65:56 | (...) => ... : (...) => ... | Test.cs:67:48:67:55 | access to local variable callback | This TLS certificate validation $@, which trusts any certificate. | Test.cs:65:13:65:56 | (...) => ... | uses a callback |
25+
| Test.cs:47:13:47:61 | (...) => ... | Test.cs:47:13:47:61 | (...) => ... | Test.cs:47:13:47:61 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:47:13:47:61 | (...) => ... | uses a callback |
26+
| Test.cs:49:68:49:87 | (...) => ... | Test.cs:49:68:49:87 | (...) => ... | Test.cs:49:68:49:87 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:49:68:49:87 | (...) => ... | uses a callback |
27+
| Test.cs:51:68:51:92 | delegate(...) { ... } | Test.cs:51:68:51:92 | delegate(...) { ... } | Test.cs:51:68:51:92 | delegate(...) { ... } | This TLS certificate validation $@, which trusts any certificate. | Test.cs:51:68:51:92 | delegate(...) { ... } | uses a callback |
28+
| Test.cs:69:67:69:75 | delegate creation of type RemoteCertificateValidationCallback | Test.cs:69:67:69:75 | delegate creation of type RemoteCertificateValidationCallback | Test.cs:69:67:69:75 | delegate creation of type RemoteCertificateValidationCallback | This TLS certificate validation $@, which trusts any certificate. | Test.cs:69:67:69:75 | delegate creation of type RemoteCertificateValidationCallback | uses a callback |
29+
| Test.cs:76:13:76:76 | delegate creation of type RemoteCertificateValidationCallback | Test.cs:76:13:76:76 | delegate creation of type RemoteCertificateValidationCallback | Test.cs:76:13:76:76 | delegate creation of type RemoteCertificateValidationCallback | This TLS certificate validation $@, which trusts any certificate. | Test.cs:76:13:76:76 | delegate creation of type RemoteCertificateValidationCallback | uses a callback |
30+
| Test.cs:83:13:83:56 | (...) => ... | Test.cs:83:13:83:56 | (...) => ... | Test.cs:83:13:83:56 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:83:13:83:56 | (...) => ... | uses a callback |
31+
| Test.cs:89:13:89:56 | (...) => ... | Test.cs:89:13:89:56 | (...) => ... | Test.cs:89:13:89:56 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:89:13:89:56 | (...) => ... | uses a callback |
32+
| Test.cs:91:48:91:55 | access to local variable callback | Test.cs:89:13:89:56 | (...) => ... : (...) => ... | Test.cs:91:48:91:55 | access to local variable callback | This TLS certificate validation $@, which trusts any certificate. | Test.cs:89:13:89:56 | (...) => ... | uses a callback |

csharp/ql/test/query-tests/Security Features/CWE-295/AcceptAnyCertificate/Test.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,42 @@ public void ServicePointManagerBad()
4040
(sender, certificate, chain, errors) => true;
4141
}
4242

43+
public void ServicePointManagerCompoundBad()
44+
{
45+
// BAD: always trusts any certificate (compound assignment).
46+
ServicePointManager.ServerCertificateValidationCallback +=
47+
(sender, cert, chain, errors) => { return true; };
48+
// BAD
49+
ServicePointManager.ServerCertificateValidationCallback += (a, b, c, d) => true;
50+
// BAD: parameterless anonymous method.
51+
ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };
52+
}
53+
4354
private static bool AcceptAll(object sender, X509Certificate certificate, X509Chain chain,
4455
SslPolicyErrors errors)
4556
{
4657
return true;
4758
}
4859

60+
public bool AcceptAllNonStatic(object sender, X509Certificate certificate, X509Chain chain,
61+
SslPolicyErrors errors)
62+
{
63+
return true;
64+
}
65+
4966
public void MethodGroupBad()
5067
{
51-
// BAD: the referenced method always returns true.
68+
// BAD: the referenced static method always returns true.
5269
ServicePointManager.ServerCertificateValidationCallback = AcceptAll;
5370
}
5471

72+
public void MethodGroupNonStaticBad()
73+
{
74+
// BAD: the referenced instance method always returns true.
75+
ServicePointManager.ServerCertificateValidationCallback =
76+
new RemoteCertificateValidationCallback(this.AcceptAllNonStatic);
77+
}
78+
5579
public void SslStreamBad(Stream stream)
5680
{
5781
// BAD: the validation callback always returns true.
@@ -75,6 +99,26 @@ public void HttpClientHandlerGood()
7599
(request, certificate, chain, errors) => errors == SslPolicyErrors.None;
76100
}
77101

102+
public void ControlFlowGood()
103+
{
104+
// GOOD: not every returned value is `true`.
105+
ServicePointManager.ServerCertificateValidationCallback +=
106+
(sender, cert, chain, errors) =>
107+
{
108+
if (cert == null)
109+
{
110+
return false;
111+
}
112+
113+
if (errors != SslPolicyErrors.None)
114+
{
115+
return false;
116+
}
117+
118+
return true;
119+
};
120+
}
121+
78122
private static bool Validate(object sender, X509Certificate certificate, X509Chain chain,
79123
SslPolicyErrors errors)
80124
{

0 commit comments

Comments
 (0)