Skip to content
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

C#: Take more sources and sinks into account when reporting in the te… #16215

Merged
merged 6 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/** Provides classes representing various flow sinks for data flow / taint tracking. */

private import semmle.code.csharp.dataflow.internal.ExternalFlow

/**
* A data flow sink node.
*/
abstract class SinkNode extends DataFlow::Node { }

/**
* Module that adds all sinks to `SinkNode`, excluding sinks for cryptography based
* queries, and queries where sinks are not succifiently explicit.
*/
private module AllSinks {
private import ParallelSink as ParallelSink
private import Remote as Remote
private import semmle.code.csharp.security.dataflow.CodeInjectionQuery as CodeInjectionQuery
private import semmle.code.csharp.security.dataflow.ConditionalBypassQuery as ConditionalBypassQuery
private import semmle.code.csharp.security.dataflow.ExposureOfPrivateInformationQuery as ExposureOfPrivateInformationQuery
private import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery as HardcodedCredentialsQuery
private import semmle.code.csharp.security.dataflow.LDAPInjectionQuery as LdapInjectionQuery
private import semmle.code.csharp.security.dataflow.LogForgingQuery as LogForgingQuery
private import semmle.code.csharp.security.dataflow.MissingXMLValidationQuery as MissingXmlValidationQuery
private import semmle.code.csharp.security.dataflow.ReDoSQuery as ReDosQuery
private import semmle.code.csharp.security.dataflow.RegexInjectionQuery as RegexInjectionQuery
private import semmle.code.csharp.security.dataflow.ResourceInjectionQuery as ResourceInjectionQuery
private import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjectionQuery
private import semmle.code.csharp.security.dataflow.TaintedPathQuery as TaintedPathQuery
private import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery as UnsafeDeserializationQuery
private import semmle.code.csharp.security.dataflow.UrlRedirectQuery as UrlRedirectQuery
private import semmle.code.csharp.security.dataflow.XMLEntityInjectionQuery as XmlEntityInjectionQuery
private import semmle.code.csharp.security.dataflow.XPathInjectionQuery as XpathInjectionQuery
private import semmle.code.csharp.security.dataflow.XSSSinks as XssSinks
private import semmle.code.csharp.security.dataflow.ZipSlipQuery as ZipSlipQuery

private class ParallelSink extends SinkNode instanceof ParallelSink::ParallelSink { }

private class RemoteSinkFlowSinks extends SinkNode instanceof Remote::RemoteFlowSink { }

private class CodeInjectionSink extends SinkNode instanceof CodeInjectionQuery::Sink { }

private class ConditionalBypassSink extends SinkNode instanceof ConditionalBypassQuery::Sink { }

private class ExposureOfPrivateInformationSink extends SinkNode instanceof ExposureOfPrivateInformationQuery::Sink
{ }

private class HardcodedCredentialsSink extends SinkNode instanceof HardcodedCredentialsQuery::Sink
{ }

private class LdapInjectionSink extends SinkNode instanceof LdapInjectionQuery::Sink { }

private class LogForgingSink extends SinkNode instanceof LogForgingQuery::Sink { }

private class MissingXmlValidationSink extends SinkNode instanceof MissingXmlValidationQuery::Sink
{ }

private class ReDosSink extends SinkNode instanceof ReDosQuery::Sink { }

private class RegexInjectionSink extends SinkNode instanceof RegexInjectionQuery::Sink { }

private class ResourceInjectionSink extends SinkNode instanceof ResourceInjectionQuery::Sink { }

private class SqlInjectionSink extends SinkNode instanceof SqlInjectionQuery::Sink { }

private class TaintedPathSink extends SinkNode instanceof TaintedPathQuery::Sink { }

private class UnsafeDeserializationSink extends SinkNode instanceof UnsafeDeserializationQuery::Sink
{ }

private class UrlRedirectSink extends SinkNode instanceof UrlRedirectQuery::Sink { }

private class XmlEntityInjectionSink extends SinkNode instanceof XmlEntityInjectionQuery::Sink { }

private class XpathInjectionSink extends SinkNode instanceof XpathInjectionQuery::Sink { }

private class XssSink extends SinkNode instanceof XssSinks::Sink { }

/**
* Add all models as data sinks.
*/
private class SinkNodeExternal extends SinkNode {
SinkNodeExternal() { sinkNode(this, _) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Provides class representing parallel sink nodes.
*/

import csharp

/**
* A data flow sink node for parallel execution.
*/
abstract class ParallelSink extends DataFlow::Node { }

/**
* A data flow sink node for lambda parallel sink.
*/
class LambdaParallelSink extends ParallelSink {
LambdaParallelSink() {
exists(Class c, Method m, MethodCall mc, Expr e | e = this.asExpr() |
c.getABaseType*().hasFullyQualifiedName("System.Threading.Tasks", "Parallel") and
c.getAMethod() = m and
m.getName() = "Invoke" and
m.getACall() = mc and
mc.getAnArgument() = e
)
}
}

/**
* A data flow sink node for thread start parallel sink.
*/
class ThreadStartParallelSink extends ParallelSink {
ThreadStartParallelSink() {
exists(DelegateCreation dc, Expr e | e = this.asExpr() |
dc.getArgument() = e and
dc.getType().getName().matches("%Start")
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/** Provides classes representing various flow sources for data flow / taint tracking. */

private import semmle.code.csharp.dataflow.internal.ExternalFlow

/**
* A data flow source node.
*/
abstract class SourceNode extends DataFlow::Node { }

/**
* Module that adds all sources to `SourceNode`, excluding source for cryptography based
* queries, and queries where sources are not succifiently explicit or mainly hardcoded constants.
*/
private module AllSources {
private import FlowSources as FlowSources
private import semmle.code.csharp.security.cryptography.HardcodedSymmetricEncryptionKey
private import semmle.code.csharp.security.dataflow.CleartextStorageQuery as CleartextStorageQuery
private import semmle.code.csharp.security.dataflow.CodeInjectionQuery as CodeInjectionQuery
private import semmle.code.csharp.security.dataflow.ConditionalBypassQuery as ConditionalBypassQuery
private import semmle.code.csharp.security.dataflow.ExposureOfPrivateInformationQuery as ExposureOfPrivateInformationQuery
private import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery as HardcodedCredentialsQuery
private import semmle.code.csharp.security.dataflow.LDAPInjectionQuery as LdapInjectionQuery
private import semmle.code.csharp.security.dataflow.LogForgingQuery as LogForgingQuery
private import semmle.code.csharp.security.dataflow.MissingXMLValidationQuery as MissingXmlValidationQuery
private import semmle.code.csharp.security.dataflow.ReDoSQuery as ReDosQuery
private import semmle.code.csharp.security.dataflow.RegexInjectionQuery as RegexInjectionQuery
private import semmle.code.csharp.security.dataflow.ResourceInjectionQuery as ResourceInjectionQuery
private import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjectionQuery
private import semmle.code.csharp.security.dataflow.TaintedPathQuery as TaintedPathQuery
private import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery as UnsafeDeserializationQuery
private import semmle.code.csharp.security.dataflow.UrlRedirectQuery as UrlRedirectQuery
private import semmle.code.csharp.security.dataflow.XMLEntityInjectionQuery as XmlEntityInjectionQuery
private import semmle.code.csharp.security.dataflow.XPathInjectionQuery as XpathInjectionQuery
private import semmle.code.csharp.security.dataflow.ZipSlipQuery as ZipSlipQuery

private class FlowSourcesSources extends SourceNode instanceof FlowSources::SourceNode { }

private class CodeInjectionSource extends SourceNode instanceof CodeInjectionQuery::Source { }

private class ConditionalBypassSource extends SourceNode instanceof ConditionalBypassQuery::Source
{ }

private class LdapInjectionSource extends SourceNode instanceof LdapInjectionQuery::Source { }

private class LogForgingSource extends SourceNode instanceof LogForgingQuery::Source { }

private class MissingXmlValidationSource extends SourceNode instanceof MissingXmlValidationQuery::Source
{ }

private class ReDosSource extends SourceNode instanceof ReDosQuery::Source { }

private class RegexInjectionSource extends SourceNode instanceof RegexInjectionQuery::Source { }

private class ResourceInjectionSource extends SourceNode instanceof ResourceInjectionQuery::Source
{ }

private class SqlInjectionSource extends SourceNode instanceof SqlInjectionQuery::Source { }

private class TaintedPathSource extends SourceNode instanceof TaintedPathQuery::Source { }

private class UnsafeDeserializationSource extends SourceNode instanceof UnsafeDeserializationQuery::Source
{ }

private class UrlRedirectSource extends SourceNode instanceof UrlRedirectQuery::Source { }

private class XmlEntityInjectionSource extends SourceNode instanceof XmlEntityInjectionQuery::Source
{ }

private class XpathInjectionSource extends SourceNode instanceof XpathInjectionQuery::Source { }

/**
* Add all models as data sources.
*/
private class SourceNodeExternal extends SourceNode {
SourceNodeExternal() { sourceNode(this, _) }
}
}
28 changes: 5 additions & 23 deletions csharp/ql/src/Likely Bugs/ParallelSink.qll
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
import csharp

abstract class ParallelSink extends DataFlow::Node { }
/**
* DEPRECATED: Use `ParallelSink` from `flowsinks.ParallelSink` instead.
*/

class LambdaParallelSink extends ParallelSink {
LambdaParallelSink() {
exists(Class c, Method m, MethodCall mc, Expr e | e = this.asExpr() |
c.getABaseType*().hasFullyQualifiedName("System.Threading.Tasks", "Parallel") and
c.getAMethod() = m and
m.getName() = "Invoke" and
m.getACall() = mc and
mc.getAnArgument() = e
)
}
}

class ThreadStartParallelSink extends ParallelSink {
ThreadStartParallelSink() {
exists(DelegateCreation dc, Expr e | e = this.asExpr() |
dc.getArgument() = e and
dc.getType().getName().matches("%Start")
)
}
}
import csharp
deprecated import semmle.code.csharp.security.dataflow.flowsinks.ParallelSink
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import csharp
import ParallelSink
import semmle.code.csharp.security.dataflow.flowsinks.ParallelSink
import ICryptoTransform

module NotThreadSafeCryptoUsageIntoParallelInvokeConfig implements DataFlow::ConfigSig {
Expand Down
9 changes: 4 additions & 5 deletions csharp/ql/src/Telemetry/ExternalApi.qll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ private import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlow
private import semmle.code.csharp.dataflow.internal.ExternalFlow
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate
private import semmle.code.csharp.security.dataflow.flowsources.Remote
private import semmle.code.csharp.security.dataflow.flowsources.AllSources
private import semmle.code.csharp.security.dataflow.flowsinks.AllSinks
private import TestLibrary

/** Holds if the given callable is not worth supporting. */
Expand Down Expand Up @@ -84,13 +85,11 @@ class ExternalApi extends Callable {

/** Holds if this API is a known source. */
pragma[nomagic]
predicate isSource() {
this.getAnOutput() instanceof RemoteFlowSource or sourceNode(this.getAnOutput(), _)
}
predicate isSource() { this.getAnOutput() instanceof SourceNode }

/** Holds if this API is a known sink. */
pragma[nomagic]
predicate isSink() { sinkNode(this.getAnInput(), _) }
predicate isSink() { this.getAnInput() instanceof SinkNode }

/** Holds if this API is a known neutral. */
pragma[nomagic]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,9 @@ public void M5()
Console.SetError(Console.Out); // Has no flow summary, supported as neutral summary model
var x = Console.Read(); // Known source
}

public void M6()
{
var html = new HtmlString("html"); // Supported HtmlSink defined in QL.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
| System#DateTime.AddDays(System.Double) | 1 |
| System#DateTime.DateTime(System.Int32,System.Int32,System.Int32) | 1 |
| System#Guid.Parse(System.String) | 1 |
| System.Web#HtmlString.HtmlString(System.String) | 1 |
| System.Web#HttpResponse.WriteFile(System.String) | 1 |
Loading