-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust: Query for cleartext logging of sensitive information #18582
Open
geoffw0
wants to merge
20
commits into
github:main
Choose a base branch
from
geoffw0:logging
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+822
−30
Open
Changes from 13 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
bb3be2f
Rust: Add a test for the log crate + placeholder query.
geoffw0 173cfd5
Rust: Add test cases for various std:: bits.
geoffw0 4297d05
Rust: Implement the query.
geoffw0 1d2950c
Rust: Add some sinks.
geoffw0 484331c
Rust: Model StdoutLock, StderrLock methods and String.as_bytes.
geoffw0 2bbf493
Rust: Model assert_failed.
geoffw0 6444494
Rust: Add taint sinks for target and key-value arguments.
geoffw0 78c58aa
Rust: Allow implicit taint reads from tuple contents at sinks.
geoffw0 59c3ac6
Rust: Allow flow through reference taking (&).
geoffw0 e708167
Rust: Add the sinks to metrics.
geoffw0 ccc1243
Rust: Add .qhelp and examples.
geoffw0 4214c83
Rust: Clean up the query message.
geoffw0 613a165
Rust: Simplify QL slightly.
geoffw0 5570523
Update rust/ql/src/queries/security/CWE-312/CleartextLoggingBad.rs
geoffw0 d27a71e
Rust: Minor fixes.
geoffw0 951d1fc
Rust: Add missing file.
geoffw0 44b9a11
Rust: Another .qhelp fix.
geoffw0 f5459d7
Rust: Accept changes to integration test results.
geoffw0 814118d
Merge remote-tracking branch 'upstream/main' into logging
geoffw0 037d496
Rust: Fix some more tests (MaD ID changes and extraction consistency …
geoffw0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
extensions: | ||
- addsTo: | ||
pack: codeql/rust-all | ||
extensible: sinkModel | ||
data: | ||
- ["repo:https://github.com/rust-lang/log:log", "crate::__private_api::log", "Argument[0]", "log-injection", "manual"] # args | ||
- ["repo:https://github.com/rust-lang/log:log", "crate::__private_api::log", "Argument[2]", "log-injection", "manual"] # target | ||
- ["repo:https://github.com/rust-lang/log:log", "crate::__private_api::log", "Argument[3]", "log-injection", "manual"] # key value | ||
- ["lang:std", "crate::io::stdio::_print", "Argument[0]", "log-injection", "manual"] | ||
- ["lang:std", "crate::io::stdio::_eprint", "Argument[0]", "log-injection", "manual"] | ||
- ["lang:std", "<crate::io::stdio::StdoutLock as crate::io::Write>::write", "Argument[0]", "log-injection", "manual"] | ||
- ["lang:std", "<crate::io::stdio::StdoutLock as crate::io::Write>::write_all", "Argument[0]", "log-injection", "manual"] | ||
- ["lang:std", "<crate::io::stdio::StderrLock as crate::io::Write>::write", "Argument[0]", "log-injection", "manual"] | ||
- ["lang:std", "<crate::io::stdio::StderrLock as crate::io::Write>::write_all", "Argument[0]", "log-injection", "manual"] | ||
- ["lang:core", "crate::panicking::panic_fmt", "Argument[0]", "log-injection", "manual"] | ||
- ["lang:core", "crate::panicking::assert_failed", "Argument[3].Variant[crate::option::Option::Some(0)]", "log-injection", "manual"] | ||
- ["lang:core", "<crate::option::Option>::expect", "Argument[0]", "log-injection", "manual"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
rust/ql/src/queries/security/CWE-312/CleartextLogging.qhelp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<!DOCTYPE qhelp PUBLIC | ||
"-//Semmle//qhelp//EN" | ||
"qhelp.dtd"> | ||
<qhelp> | ||
|
||
<overview> | ||
<p> | ||
Sensitive user data and system information that is logged could be seen by an attacker when it is | ||
displayed. Also, external processes often store the standard output and standard error streams of | ||
an application, which will include logged sensitive information.</p> | ||
</p> | ||
</overview> | ||
|
||
<recommendation> | ||
<p> | ||
Do not log sensitive data. If it is necessary to log sensitive data, encrypt it before logging. | ||
</p> | ||
</recommendation> | ||
|
||
<example> | ||
<p> | ||
The following example code logs user credentials (in this case, their password) in plaintext: | ||
</p> | ||
<sample src="CleartextLoggingBad.rs"/> | ||
<p> | ||
Instead, you should encrypt the credentials, or better still omit them entirely: | ||
</p> | ||
<sample src="CleartextLoggingGood.rs"/> | ||
</example> | ||
|
||
<references> | ||
|
||
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li> | ||
<li>M. Howard and D. LeBlanc, <i>Writing Secure Code</i>, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.</li> | ||
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#data-to-exclude">Logging Cheat Sheet - Data to exclude</a>.<li> | ||
|
||
</references> | ||
</qhelp> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/** | ||
* @name Cleartext logging of sensitive information | ||
* @description Logging sensitive information in plaintext can | ||
* expose it to an attacker. | ||
* @kind path-problem | ||
* @problem.severity error | ||
* @security-severity 7.5 | ||
* @precision high | ||
* @id rust/cleartext-logging | ||
* @tags security | ||
* external/cwe/cwe-312 | ||
* external/cwe/cwe-359 | ||
* external/cwe/cwe-532 | ||
*/ | ||
|
||
import rust | ||
import codeql.rust.security.CleartextLoggingExtensions | ||
import codeql.rust.dataflow.DataFlow | ||
import codeql.rust.dataflow.TaintTracking | ||
import codeql.rust.dataflow.internal.DataFlowImpl | ||
|
||
/** | ||
* A taint-tracking configuration for cleartext logging vulnerabilities. | ||
*/ | ||
module CleartextLoggingConfig implements DataFlow::ConfigSig { | ||
import CleartextLogging | ||
|
||
predicate isSource(DataFlow::Node source) { source instanceof Source } | ||
|
||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink } | ||
|
||
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier } | ||
|
||
predicate isBarrierIn(DataFlow::Node node) { | ||
// make sources barriers so that we only report the closest instance | ||
isSource(node) | ||
} | ||
|
||
predicate isAdditionalFlowStep(Node node1, Node node2) { | ||
// flow from `a` to `&a` | ||
node2.asExpr().getExpr().(RefExpr).getExpr() = node1.asExpr().getExpr() | ||
} | ||
|
||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { | ||
// flow out from tuple content at sinks. | ||
isSink(node) and | ||
c.getAReadContent() instanceof TuplePositionContent | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't get tuple content to work in the models-as-data sink itself, so this might have to do for now. |
||
} | ||
} | ||
|
||
module CleartextLoggingFlow = TaintTracking::Global<CleartextLoggingConfig>; | ||
|
||
import CleartextLoggingFlow::PathGraph | ||
|
||
from CleartextLoggingFlow::PathNode source, CleartextLoggingFlow::PathNode sink | ||
where CleartextLoggingFlow::flowPath(source, sink) | ||
select sink.getNode(), source, sink, "This operation writes $@ to a log file.", source, | ||
source.getNode().toString() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
let password = "P@ssw0rd" | ||
geoffw0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
info!("User password changed to {password}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
let password = "P@ssw0rd" | ||
info!("User password changed") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We possibly want something like this as a general flow step. It matters for basically all the test cases that mention
&password
in the source I think. @paldepind what do you think?