Skip to content

Commit 0d0d34c

Browse files
authored
Merge pull request #21498 from Gregro/csharp/fix-log-forging-extension-methods
C#: Fix false positives in cs/log-forging for extension methods
2 parents be24535 + a59c865 commit 0d0d34c

File tree

4 files changed

+42
-2
lines changed

4 files changed

+42
-2
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The `cs/log-forging` query no longer treats arguments to extension methods with
5+
source code on `ILogger` types as sinks. Instead, taint is tracked interprocedurally
6+
through extension method bodies, reducing false positives when extension methods
7+
sanitize input internally.

csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,17 @@ private class HtmlSanitizer extends Sanitizer {
5252
}
5353

5454
/**
55-
* An argument to a call to a method on a logger class.
55+
* An argument to a call to a method on a logger class, excluding extension methods
56+
* with source code which are analyzed interprocedurally.
5657
*/
57-
private class LogForgingLogMessageSink extends Sink, LogMessageSink { }
58+
private class LogForgingLogMessageSink extends Sink, LogMessageSink {
59+
LogForgingLogMessageSink() {
60+
not exists(ExtensionMethodCall mc |
61+
this.getExpr() = mc.getAnArgument() and
62+
mc.getTarget().fromSource()
63+
)
64+
}
65+
}
5866

5967
/**
6068
* An argument to a call to a method on a trace class.

csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public void ProcessRequest(HttpContext ctx)
3333
Microsoft.Extensions.Logging.ILogger logger2 = null;
3434
// BAD: Logged as-is
3535
logger2.LogError(username); // $ Alert
36+
37+
// GOOD: uses safe extension method that sanitizes internally
38+
logger.WarnSafe(username + " logged in");
39+
// BAD: uses unsafe extension method that does not sanitize
40+
logger.WarnUnsafe(username + " logged in");
3641
}
3742

3843
public bool IsReusable
@@ -43,3 +48,16 @@ public bool IsReusable
4348
}
4449
}
4550
}
51+
52+
static class UserLoggerExtensions
53+
{
54+
public static void WarnSafe(this ILogger logger, string message)
55+
{
56+
logger.Warn(message.ReplaceLineEndings(""));
57+
}
58+
59+
public static void WarnUnsafe(this ILogger logger, string message)
60+
{
61+
logger.Warn(message); // $ Alert
62+
}
63+
}

csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
| LogForging.cs:21:21:21:43 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
33
| LogForging.cs:31:50:31:72 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:50:31:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
44
| LogForging.cs:35:26:35:33 | access to local variable username | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:35:26:35:33 | access to local variable username | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
5+
| LogForging.cs:61:21:61:27 | access to parameter message | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:61:21:61:27 | access to parameter message | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
56
| LogForgingAsp.cs:17:21:17:43 | ... + ... | LogForgingAsp.cs:13:32:13:39 | username : String | LogForgingAsp.cs:17:21:17:43 | ... + ... | This log entry depends on a $@. | LogForgingAsp.cs:13:32:13:39 | username | user-provided value |
67
edges
78
| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:21:21:21:43 | ... + ... | provenance | |
89
| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:31:50:31:72 | ... + ... | provenance | |
910
| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:35:26:35:33 | access to local variable username | provenance | |
11+
| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:40:27:40:49 | ... + ... : String | provenance | |
1012
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:16:18:23 | access to local variable username : String | provenance | |
1113
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String | provenance | MaD:1 |
1214
| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:18:16:18:23 | access to local variable username : String | provenance | |
15+
| LogForging.cs:40:27:40:49 | ... + ... : String | LogForging.cs:59:63:59:69 | message : String | provenance | |
16+
| LogForging.cs:59:63:59:69 | message : String | LogForging.cs:61:21:61:27 | access to parameter message | provenance | |
1317
| LogForgingAsp.cs:13:32:13:39 | username : String | LogForgingAsp.cs:17:21:17:43 | ... + ... | provenance | |
1418
models
1519
| 1 | Summary: System.Collections.Specialized; NameValueCollection; false; get_Item; (System.String); ; Argument[this]; ReturnValue; taint; df-generated |
@@ -20,6 +24,9 @@ nodes
2024
| LogForging.cs:21:21:21:43 | ... + ... | semmle.label | ... + ... |
2125
| LogForging.cs:31:50:31:72 | ... + ... | semmle.label | ... + ... |
2226
| LogForging.cs:35:26:35:33 | access to local variable username | semmle.label | access to local variable username |
27+
| LogForging.cs:40:27:40:49 | ... + ... : String | semmle.label | ... + ... : String |
28+
| LogForging.cs:59:63:59:69 | message : String | semmle.label | message : String |
29+
| LogForging.cs:61:21:61:27 | access to parameter message | semmle.label | access to parameter message |
2330
| LogForgingAsp.cs:13:32:13:39 | username : String | semmle.label | username : String |
2431
| LogForgingAsp.cs:17:21:17:43 | ... + ... | semmle.label | ... + ... |
2532
subpaths

0 commit comments

Comments
 (0)