Skip to content

Commit e630bf8

Browse files
Copilotgeoffw0
andcommitted
Implement Rust non-HTTPS URL query (CWE-319)
Co-authored-by: geoffw0 <40627776+geoffw0@users.noreply.github.com>
1 parent 459f00a commit e630bf8

File tree

15 files changed

+1902
-0
lines changed

15 files changed

+1902
-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: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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.elements.LiteralExprExt
10+
private import codeql.rust.Concepts
11+
12+
/**
13+
* Provides default sources, sinks and barriers for detecting use of
14+
* non-HTTPS URLs, as well as extension points for adding your own.
15+
*/
16+
module UseOfHttp {
17+
/**
18+
* A data flow source for use of non-HTTPS URLs.
19+
*/
20+
abstract class Source extends DataFlow::Node { }
21+
22+
/**
23+
* A data flow sink for use of non-HTTPS URLs.
24+
*/
25+
abstract class Sink extends QuerySink::Range {
26+
override string getSinkType() { result = "UseOfHttp" }
27+
}
28+
29+
/**
30+
* A barrier for use of non-HTTPS URLs.
31+
*/
32+
abstract class Barrier extends DataFlow::Node { }
33+
34+
/**
35+
* A string containing an HTTP URL.
36+
*/
37+
class HttpStringLiteral extends StringLiteralExpr {
38+
HttpStringLiteral() {
39+
exists(string s | this.getTextValue() = s |
40+
// Match HTTP URLs that are not private/local
41+
s.regexpMatch("\"http://.*\"") and
42+
not s.regexpMatch("\"http://(localhost|127\\.0\\.0\\.1|192\\.168\\.[0-9]+\\.[0-9]+|10\\.[0-9]+\\.[0-9]+\\.[0-9]+|172\\.16\\.[0-9]+\\.[0-9]+|\\[::1\\]|\\[0:0:0:0:0:0:0:1\\]).*\"")
43+
)
44+
}
45+
}
46+
47+
/**
48+
* An HTTP string literal as a source.
49+
*/
50+
private class HttpStringLiteralAsSource extends Source {
51+
HttpStringLiteralAsSource() { this.asExpr().getExpr() instanceof HttpStringLiteral }
52+
}
53+
54+
/**
55+
* A sink for use of HTTP URLs from model data.
56+
*/
57+
private class ModelsAsDataSink extends Sink {
58+
ModelsAsDataSink() { sinkNode(this, "request-url") }
59+
}
60+
}
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: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 unsecured 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 SSL/TLS connections.</p>
18+
19+
</recommendation>
20+
<example>
21+
22+
<p>The following example shows 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. When the request is made using an HTTPS URL, the connection is a secure SSL/TLS connection.</p>
25+
26+
<sample src="UseOfHttpBad.rs" />
27+
28+
<p>A better approach is to use HTTPS:</p>
29+
30+
<sample src="UseOfHttpGood.rs" />
31+
32+
</example>
33+
<references>
34+
35+
<li>
36+
OWASP:
37+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html">Transport Layer Protection Cheat Sheet</a>.
38+
</li>
39+
<li>
40+
OWASP Top 10:
41+
<a href="https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/">A08:2021 - Software and Data Integrity Failures</a>.
42+
</li>
43+
<li>Rust reqwest documentation:
44+
<a href="https://docs.rs/reqwest/">reqwest crate</a>.
45+
</li>
46+
47+
</references>
48+
</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)