Skip to content

Commit 5ad332e

Browse files
authored
Merge pull request #20432 from github/copilot/fix-f50317f8-0a91-4bb4-a01b-353dcf0f6f3f
Rust: Implement new query for non-HTTPS URLs (CWE-319)
2 parents 463f79b + c26a07b commit 5ad332e

File tree

15 files changed

+1921
-0
lines changed

15 files changed

+1921
-0
lines changed

rust/ql/integration-tests/query-suite/rust-code-scanning.qls.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ ql/rust/ql/src/queries/security/CWE-089/SqlInjection.ql
1414
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
1515
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
1616
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
17+
ql/rust/ql/src/queries/security/CWE-319/UseOfHttp.ql
1718
ql/rust/ql/src/queries/security/CWE-327/BrokenCryptoAlgorithm.ql
1819
ql/rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql
1920
ql/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql

rust/ql/integration-tests/query-suite/rust-security-and-quality.qls.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ ql/rust/ql/src/queries/security/CWE-117/LogInjection.ql
1515
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
1616
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
1717
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
18+
ql/rust/ql/src/queries/security/CWE-319/UseOfHttp.ql
1819
ql/rust/ql/src/queries/security/CWE-327/BrokenCryptoAlgorithm.ql
1920
ql/rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql
2021
ql/rust/ql/src/queries/security/CWE-696/BadCtorInitialization.ql

rust/ql/integration-tests/query-suite/rust-security-extended.qls.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ ql/rust/ql/src/queries/security/CWE-117/LogInjection.ql
1515
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
1616
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
1717
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
18+
ql/rust/ql/src/queries/security/CWE-319/UseOfHttp.ql
1819
ql/rust/ql/src/queries/security/CWE-327/BrokenCryptoAlgorithm.ql
1920
ql/rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql
2021
ql/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Provides classes and predicates for reasoning about the use of
3+
* non-HTTPS URLs in Rust code.
4+
*/
5+
6+
import rust
7+
private import codeql.rust.dataflow.DataFlow
8+
private import codeql.rust.dataflow.FlowSink
9+
private import codeql.rust.Concepts
10+
11+
/**
12+
* Provides default sources, sinks and barriers for detecting use of
13+
* non-HTTPS URLs, as well as extension points for adding your own.
14+
*/
15+
module UseOfHttp {
16+
/**
17+
* A data flow source for use of non-HTTPS URLs.
18+
*/
19+
abstract class Source extends DataFlow::Node { }
20+
21+
/**
22+
* A data flow sink for use of non-HTTPS URLs.
23+
*/
24+
abstract class Sink extends QuerySink::Range {
25+
override string getSinkType() { result = "UseOfHttp" }
26+
}
27+
28+
/**
29+
* A barrier for use of non-HTTPS URLs.
30+
*/
31+
abstract class Barrier extends DataFlow::Node { }
32+
33+
/**
34+
* A string containing an HTTP URL.
35+
*/
36+
class HttpStringLiteral extends StringLiteralExpr {
37+
HttpStringLiteral() {
38+
exists(string s | this.getTextValue() = s |
39+
// match HTTP URLs
40+
s.regexpMatch("(?i)\"http://.*\"") and
41+
// exclude private/local addresses:
42+
// - IPv4: localhost / 127.0.0.1, 192.168.x.x, 10.x.x.x, 172.16.x.x -> 172.31.x.x
43+
// - IPv6 (address inside []): ::1 (or 0:0:0:0:0:0:0:1), fc00::/7 (i.e. anything beginning `fcxx:` or `fdxx:`)
44+
not s.regexpMatch("(?i)\"http://(localhost|127\\.0\\.0\\.1|192\\.168\\.[0-9]+\\.[0-9]+|10\\.[0-9]+\\.[0-9]+\\.[0-9]+|172\\.(1[6-9]|2[0-9]|3[01])\\.[0-9]+|\\[::1\\]|\\[0:0:0:0:0:0:0:1\\]|\\[f[cd][0-9a-f]{2}:.*\\]).*\"")
45+
)
46+
}
47+
}
48+
49+
/**
50+
* An HTTP string literal as a source.
51+
*/
52+
private class HttpStringLiteralAsSource extends Source {
53+
HttpStringLiteralAsSource() { this.asExpr().getExpr() instanceof HttpStringLiteral }
54+
}
55+
56+
/**
57+
* A sink for use of HTTP URLs from model data.
58+
*/
59+
private class ModelsAsDataSink extends Sink {
60+
ModelsAsDataSink() { sinkNode(this, "request-url") }
61+
}
62+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: newQuery
3+
---
4+
* Added a new query, `rust/non-https-url`, for detecting the use of non-HTTPS URLs that can be intercepted by third parties.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
7+
<p>Constructing URLs with the HTTP protocol can lead to insecure connections.</p>
8+
9+
<p>Furthermore, constructing URLs with the HTTP protocol can create problems if other parts of the
10+
code expect HTTPS URLs. A typical pattern is to use libraries that expect secure connections,
11+
which may fail or fall back to insecure behavior when provided with HTTP URLs instead of HTTPS URLs.</p>
12+
13+
</overview>
14+
<recommendation>
15+
16+
<p>When you construct a URL for network requests, ensure that you use an HTTPS URL rather than an HTTP URL.
17+
Then, any connections that are made using that URL are secure TLS connections.</p>
18+
19+
</recommendation>
20+
<example>
21+
22+
<p>The following examples show two ways of making a network request using a URL. When the request is
23+
made using an HTTP URL rather than an HTTPS URL, the connection is unsecured and can be intercepted
24+
by attackers:</p>
25+
26+
<sample src="UseOfHttpBad.rs" />
27+
28+
<p>A better approach is to use HTTPS. When the request is made using an HTTPS URL, the connection
29+
is a secure TLS connection:</p>
30+
31+
<sample src="UseOfHttpGood.rs" />
32+
33+
</example>
34+
<references>
35+
36+
<li>
37+
OWASP:
38+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html">Transport Layer Security Cheat Sheet</a>.
39+
</li>
40+
<li>
41+
OWASP Top 10:
42+
<a href="https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/">A08:2021 - Software and Data Integrity Failures</a>.
43+
</li>
44+
<li>Rust reqwest documentation:
45+
<a href="https://docs.rs/reqwest/">reqwest crate</a>.
46+
</li>
47+
48+
</references>
49+
</qhelp>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* @name Failure to use HTTPS URLs
3+
* @description Non-HTTPS connections can be intercepted by third parties.
4+
* @kind path-problem
5+
* @problem.severity warning
6+
* @security-severity 8.1
7+
* @precision high
8+
* @id rust/non-https-url
9+
* @tags security
10+
* external/cwe/cwe-319
11+
* external/cwe/cwe-345
12+
*/
13+
14+
import rust
15+
import codeql.rust.dataflow.DataFlow
16+
import codeql.rust.dataflow.TaintTracking
17+
import codeql.rust.security.UseOfHttpExtensions
18+
19+
/**
20+
* A taint configuration for HTTP URL strings that flow to URL-using sinks.
21+
*/
22+
module UseOfHttpConfig implements DataFlow::ConfigSig {
23+
import UseOfHttp
24+
25+
predicate isSource(DataFlow::Node node) { node instanceof Source }
26+
27+
predicate isSink(DataFlow::Node node) { node instanceof Sink }
28+
29+
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
30+
31+
predicate observeDiffInformedIncrementalMode() { any() }
32+
}
33+
34+
module UseOfHttpFlow = TaintTracking::Global<UseOfHttpConfig>;
35+
36+
import UseOfHttpFlow::PathGraph
37+
38+
from UseOfHttpFlow::PathNode sourceNode, UseOfHttpFlow::PathNode sinkNode
39+
where UseOfHttpFlow::flowPath(sourceNode, sinkNode)
40+
select sinkNode.getNode(), sourceNode, sinkNode,
41+
"This URL may be constructed with the HTTP protocol, from $@.", sourceNode.getNode(),
42+
"this HTTP URL"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// BAD: Using HTTP URL which can be intercepted
2+
use reqwest;
3+
4+
fn main() {
5+
let url = "http://example.com/sensitive-data";
6+
7+
// This makes an insecure HTTP request that can be intercepted
8+
let response = reqwest::blocking::get(url).unwrap();
9+
println!("Response: {}", response.text().unwrap());
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// GOOD: Using HTTPS URL which provides encryption
2+
use reqwest;
3+
4+
fn main() {
5+
let url = "https://example.com/sensitive-data";
6+
7+
// This makes a secure HTTPS request that is encrypted
8+
let response = reqwest::blocking::get(url).unwrap();
9+
println!("Response: {}", response.text().unwrap());
10+
}

rust/ql/src/queries/summary/Stats.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ private import codeql.rust.security.LogInjectionExtensions
2727
private import codeql.rust.security.SqlInjectionExtensions
2828
private import codeql.rust.security.TaintedPathExtensions
2929
private import codeql.rust.security.UncontrolledAllocationSizeExtensions
30+
private import codeql.rust.security.UseOfHttpExtensions
3031
private import codeql.rust.security.WeakSensitiveDataHashingExtensions
3132
private import codeql.rust.security.HardcodedCryptographicValueExtensions
3233

0 commit comments

Comments
 (0)