Files
2023-11-20 11:57:03 -08:00

728 lines
49 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Analyzing data flow in C# &#8212; CodeQL</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css?v=93459777" />
<script src="../_static/documentation_options.js?v=5929fcd5"></script>
<script src="../_static/doctools.js?v=888ff710"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="CodeQL for Go" href="codeql-for-go.html" />
<link rel="prev" title="CodeQL library for C#" href="codeql-library-for-csharp.html" />
<title>CodeQL docs</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
<link rel="stylesheet" href="../_static/primer.css" type="text/css" />
</head><body>
<header class="Header">
<div class="Header-item--full">
<a href="https://codeql.github.com/docs" class="Header-link f2 d-flex flex-items-center">
<!-- <%= octicon "mark-github", class: "mr-2", height: 32 %> -->
<svg height="32" class="octicon octicon-mark-github mr-2" viewBox="0 0 16 16" version="1.1" width="32"
aria-hidden="true">
<path fill-rule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">
</path>
</svg>
<span class="hide-sm">CodeQL documentation</span>
</a>
</div>
<div class="Header-item hide-sm hide-md">
<script src="https://addsearch.com/js/?key=93b4d287e2fc079a4089412b669785d5&categories=!0xhelp.semmle.com,0xcodeql.github.com,1xdocs,1xcodeql-standard-libraries,1xcodeql-query-help"></script>
</div>
<div class="Header-item">
<details class="dropdown details-reset details-overlay d-inline-block">
<summary class="btn bg-gray-dark text-white border" aria-haspopup="true">
CodeQL resources
<div class="dropdown-caret"></div>
</summary>
<ul class="dropdown-menu dropdown-menu-se dropdown-menu-dark">
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-overview">CodeQL overview</a></li>
<li class="dropdown-divider" role="separator"></li>
<div class="dropdown-header">
CodeQL tools
</div>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-for-visual-studio-code">CodeQL for VS Code</a>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-cli">CodeQL CLI</a>
</li>
<li class="dropdown-divider" role="separator"></li>
<div class="dropdown-header">
CodeQL guides
</div>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/writing-codeql-queries">Writing CodeQL queries</a></li>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-language-guides">CodeQL language guides</a>
<li class="dropdown-divider" role="separator"></li>
<div class="dropdown-header">
Reference docs
</div>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/ql-language-reference/">QL language
reference</a>
<li><a class="dropdown-item" href="https://codeql.github.com/codeql-standard-libraries">CodeQL
standard-libraries</a>
<li><a class="dropdown-item" href="https://codeql.github.com/codeql-query-help">CodeQL
query help</a>
<li class="dropdown-divider" role="separator"></li>
<div class="dropdown-header">
Source files
</div>
<li><a class="dropdown-item" href="https://github.com/github/codeql">CodeQL repository</a>
</ul>
</details>
</div>
</header>
<main class="bg-gray-light clearfix">
<nav class="SideNav position-sticky top-0 col-lg-3 col-md-3 float-left p-4 hide-sm hide-md overflow-y-auto">
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../codeql-overview/index.html">CodeQL overview</a></li>
<li class="toctree-l1"><a class="reference internal" href="../codeql-for-visual-studio-code/index.html">CodeQL for Visual Studio Code</a></li>
<li class="toctree-l1"><a class="reference internal" href="../codeql-cli/index.html">CodeQL CLI</a></li>
<li class="toctree-l1"><a class="reference internal" href="../writing-codeql-queries/index.html">Writing CodeQL queries</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">CodeQL language guides</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="codeql-for-cpp.html">CodeQL for C and C++</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="codeql-for-csharp.html">CodeQL for C#</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="basic-query-for-csharp-code.html">Basic query for C# code</a></li>
<li class="toctree-l3"><a class="reference internal" href="codeql-library-for-csharp.html">CodeQL library for C#</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Analyzing data flow in C#</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-go.html">CodeQL for Go</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-java.html">CodeQL for Java</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-javascript.html">CodeQL for JavaScript</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-python.html">CodeQL for Python</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-ruby.html">CodeQL for Ruby</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../ql-language-reference/index.html">QL language reference</a></li>
</ul>
</nav>
<div class="body col-sm-12 col-md-9 col-lg-9 float-left border-left">
<div class="hide-lg hide-xl px-4 pt-4">
<div class="related" role="navigation" aria-label="related navigation">
<ul>
<li class="nav-item nav-item-0"><a href="../contents.html">CodeQL</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html"
>CodeQL language guides</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="codeql-for-csharp.html"
accesskey="U">CodeQL for C#</a> &#187;</li>
</ul>
</div>
</div>
<article class="p-4 col-lg-10 col-md-10 col-sm-12">
<section id="analyzing-data-flow-in-c">
<span id="analyzing-data-flow-in-csharp"></span><h1>Analyzing data flow in C#<a class="headerlink" href="#analyzing-data-flow-in-c" title="Link to this heading"></a></h1>
<p>You can use CodeQL to track the flow of data through a C# program to its use.</p>
<section id="about-this-article">
<h2>About this article<a class="headerlink" href="#about-this-article" title="Link to this heading"></a></h2>
<p>This article describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries.
The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking.
For a more general introduction to modeling data flow, see “<a class="reference internal" href="../writing-codeql-queries/about-data-flow-analysis.html#about-data-flow-analysis"><span class="std std-ref">About data flow analysis</span></a>.”</p>
</section>
<section id="local-data-flow">
<h2>Local data flow<a class="headerlink" href="#local-data-flow" title="Link to this heading"></a></h2>
<p>Local data flow is data flow within a single method or callable. Local data flow is easier, faster, and more precise than global data flow, and is sufficient for many queries.</p>
<section id="using-local-data-flow">
<h3>Using local data flow<a class="headerlink" href="#using-local-data-flow" title="Link to this heading"></a></h3>
<p>The local data flow library is in the module <code class="docutils literal notranslate"><span class="pre">DataFlow</span></code>, which defines the class <code class="docutils literal notranslate"><span class="pre">Node</span></code> denoting any element that data can flow through. <code class="docutils literal notranslate"><span class="pre">Node</span></code>s are divided into expression nodes (<code class="docutils literal notranslate"><span class="pre">ExprNode</span></code>) and parameter nodes (<code class="docutils literal notranslate"><span class="pre">ParameterNode</span></code>). You can map between data flow nodes and expressions/parameters using the member predicates <code class="docutils literal notranslate"><span class="pre">asExpr</span></code> and <code class="docutils literal notranslate"><span class="pre">asParameter</span></code>:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>class Node {
/** Gets the expression corresponding to this node, if any. */
Expr asExpr() { ... }
/** Gets the parameter corresponding to this node, if any. */
Parameter asParameter() { ... }
...
}
</pre></div>
</div>
<p>or using the predicates <code class="docutils literal notranslate"><span class="pre">exprNode</span></code> and <code class="docutils literal notranslate"><span class="pre">parameterNode</span></code>:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>/**
* Gets the node corresponding to expression `e`.
*/
ExprNode exprNode(Expr e) { ... }
/**
* Gets the node corresponding to the value of parameter `p` at function entry.
*/
ParameterNode parameterNode(Parameter p) { ... }
</pre></div>
</div>
<p>The predicate <code class="docutils literal notranslate"><span class="pre">localFlowStep(Node</span> <span class="pre">nodeFrom,</span> <span class="pre">Node</span> <span class="pre">nodeTo)</span></code> holds if there is an immediate data flow edge from the node <code class="docutils literal notranslate"><span class="pre">nodeFrom</span></code> to the node <code class="docutils literal notranslate"><span class="pre">nodeTo</span></code>. You can apply the predicate recursively, by using the <code class="docutils literal notranslate"><span class="pre">+</span></code> and <code class="docutils literal notranslate"><span class="pre">*</span></code> operators, or you can use the predefined recursive predicate <code class="docutils literal notranslate"><span class="pre">localFlow</span></code>.</p>
<p>For example, you can find flow from a parameter <code class="docutils literal notranslate"><span class="pre">source</span></code> to an expression <code class="docutils literal notranslate"><span class="pre">sink</span></code> in zero or more local steps:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>DataFlow::localFlow(DataFlow::parameterNode(source), DataFlow::exprNode(sink))
</pre></div>
</div>
</section>
<section id="using-local-taint-tracking">
<h3>Using local taint tracking<a class="headerlink" href="#using-local-taint-tracking" title="Link to this heading"></a></h3>
<p>Local taint tracking extends local data flow by including non-value-preserving flow steps. For example:</p>
<div class="highlight-csharp notranslate"><div class="highlight"><pre><span></span><span class="kt">var</span><span class="w"> </span><span class="n">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="kt">var</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">temp</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">&quot;, &quot;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">temp</span><span class="p">;</span>
</pre></div>
</div>
<p>If <code class="docutils literal notranslate"><span class="pre">x</span></code> is a tainted string then <code class="docutils literal notranslate"><span class="pre">y</span></code> is also tainted.</p>
<p>The local taint tracking library is in the module <code class="docutils literal notranslate"><span class="pre">TaintTracking</span></code>. Like local data flow, a predicate <code class="docutils literal notranslate"><span class="pre">localTaintStep(DataFlow::Node</span> <span class="pre">nodeFrom,</span> <span class="pre">DataFlow::Node</span> <span class="pre">nodeTo)</span></code> holds if there is an immediate taint propagation edge from the node <code class="docutils literal notranslate"><span class="pre">nodeFrom</span></code> to the node <code class="docutils literal notranslate"><span class="pre">nodeTo</span></code>. You can apply the predicate recursively, by using the <code class="docutils literal notranslate"><span class="pre">+</span></code> and <code class="docutils literal notranslate"><span class="pre">*</span></code> operators, or you can use the predefined recursive predicate <code class="docutils literal notranslate"><span class="pre">localTaint</span></code>.</p>
<p>For example, you can find taint propagation from a parameter <code class="docutils literal notranslate"><span class="pre">source</span></code> to an expression <code class="docutils literal notranslate"><span class="pre">sink</span></code> in zero or more local steps:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>TaintTracking::localTaint(DataFlow::parameterNode(source), DataFlow::exprNode(sink))
</pre></div>
</div>
</section>
<section id="examples">
<h3>Examples<a class="headerlink" href="#examples" title="Link to this heading"></a></h3>
<p>This query finds the filename passed to <code class="docutils literal notranslate"><span class="pre">System.IO.File.Open</span></code>:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
from Method fileOpen, MethodCall call
where fileOpen.hasQualifiedName(&quot;System.IO.File.Open&quot;)
and call.getTarget() = fileOpen
select call.getArgument(0)
</pre></div>
</div>
<p>Unfortunately this will only give the expression in the argument, not the values which could be passed to it. So we use local data flow to find all expressions that flow into the argument:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
from Method fileOpen, MethodCall call, Expr src
where fileOpen.hasQualifiedName(&quot;System.IO.File.Open&quot;)
and call.getTarget() = fileOpen
and DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(call.getArgument(0)))
select src
</pre></div>
</div>
<p>Then we can make the source more specific, for example an access to a public parameter. This query finds instances where a public parameter is used to open a file:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
from Method fileOpen, MethodCall call, Parameter p
where fileOpen.hasQualifiedName(&quot;System.IO.File.Open&quot;)
and call.getTarget() = fileOpen
and DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(call.getArgument(0)))
and call.getEnclosingCallable().(Member).isPublic()
select p, &quot;Opening a file from a public method.&quot;
</pre></div>
</div>
<p>This query finds calls to <code class="docutils literal notranslate"><span class="pre">String.Format</span></code> where the format string isnt hard-coded:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
from Method format, MethodCall call, Expr formatString
where format.hasQualifiedName(&quot;System.String.Format&quot;)
and call.getTarget() = format
and formatString = call.getArgument(0)
and formatString.getType() instanceof StringType
and not exists(StringLiteral source | DataFlow::localFlow(DataFlow::exprNode(source), DataFlow::exprNode(formatString)))
select call, &quot;Argument to &#39;string.Format&#39; isn&#39;t hard-coded.&quot;
</pre></div>
</div>
</section>
<section id="exercises">
<h3>Exercises<a class="headerlink" href="#exercises" title="Link to this heading"></a></h3>
<p>Exercise 1: Write a query that finds all hard-coded strings used to create a <code class="docutils literal notranslate"><span class="pre">System.Uri</span></code>, using local data flow. (<a class="reference external" href="#exercise-1">Answer</a>)</p>
</section>
</section>
<section id="global-data-flow">
<h2>Global data flow<a class="headerlink" href="#global-data-flow" title="Link to this heading"></a></h2>
<p>Global data flow tracks data flow throughout the entire program, and is therefore more powerful than local data flow. However, global data flow is less precise than local data flow, and the analysis typically requires significantly more time and memory to perform.</p>
<blockquote class="pull-quote">
<div><p>Note</p>
<p>You can model data flow paths in CodeQL by creating path queries. To view data flow paths generated by a path query in CodeQL for VS Code, you need to make sure that it has the correct metadata and <code class="docutils literal notranslate"><span class="pre">select</span></code> clause. For more information, see <a class="reference internal" href="../writing-codeql-queries/creating-path-queries.html#creating-path-queries"><span class="std std-ref">Creating path queries</span></a>.</p>
</div></blockquote>
<section id="using-global-data-flow">
<h3>Using global data flow<a class="headerlink" href="#using-global-data-flow" title="Link to this heading"></a></h3>
<p>The global data flow library is used by extending the class <code class="docutils literal notranslate"><span class="pre">DataFlow::Configuration</span></code>:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
class MyDataFlowConfiguration extends DataFlow::Configuration {
MyDataFlowConfiguration() { this = &quot;...&quot; }
override predicate isSource(DataFlow::Node source) {
...
}
override predicate isSink(DataFlow::Node sink) {
...
}
}
</pre></div>
</div>
<p>These predicates are defined in the configuration:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">isSource</span></code> - defines where data may flow from.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">isSink</span></code> - defines where data may flow to.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">isBarrier</span></code> - optionally, restricts the data flow.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">isAdditionalFlowStep</span></code> - optionally, adds additional flow steps.</p></li>
</ul>
<p>The characteristic predicate (<code class="docutils literal notranslate"><span class="pre">MyDataFlowConfiguration()</span></code>) defines the name of the configuration, so <code class="docutils literal notranslate"><span class="pre">&quot;...&quot;</span></code> must be replaced with a unique name.</p>
<p>The data flow analysis is performed using the predicate <code class="docutils literal notranslate"><span class="pre">hasFlow(DataFlow::Node</span> <span class="pre">source,</span> <span class="pre">DataFlow::Node</span> <span class="pre">sink)</span></code>:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>from MyDataFlowConfiguation dataflow, DataFlow::Node source, DataFlow::Node sink
where dataflow.hasFlow(source, sink)
select source, &quot;Dataflow to $@.&quot;, sink, sink.toString()
</pre></div>
</div>
</section>
<section id="using-global-taint-tracking">
<h3>Using global taint tracking<a class="headerlink" href="#using-global-taint-tracking" title="Link to this heading"></a></h3>
<p>Global taint tracking is to global data flow what local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. The global taint tracking library is used by extending the class <code class="docutils literal notranslate"><span class="pre">TaintTracking::Configuration</span></code>:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
class MyTaintTrackingConfiguration extends TaintTracking::Configuration {
MyTaintTrackingConfiguration() { this = &quot;...&quot; }
override predicate isSource(DataFlow::Node source) {
...
}
override predicate isSink(DataFlow::Node sink) {
...
}
}
</pre></div>
</div>
<p>These predicates are defined in the configuration:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">isSource</span></code> - defines where taint may flow from.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">isSink</span></code> - defines where taint may flow to.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">isSanitizer</span></code> - optionally, restricts the taint flow.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">isAdditionalTaintStep</span></code> - optionally, adds additional taint steps.</p></li>
</ul>
<p>Similar to global data flow, the characteristic predicate (<code class="docutils literal notranslate"><span class="pre">MyTaintTrackingConfiguration()</span></code>) defines the unique name of the configuration and the taint analysis is performed using the predicate <code class="docutils literal notranslate"><span class="pre">hasFlow(DataFlow::Node</span> <span class="pre">source,</span> <span class="pre">DataFlow::Node</span> <span class="pre">sink)</span></code>.</p>
</section>
<section id="flow-sources">
<h3>Flow sources<a class="headerlink" href="#flow-sources" title="Link to this heading"></a></h3>
<p>The data flow library contains some predefined flow sources. The class <code class="docutils literal notranslate"><span class="pre">PublicCallableParameterFlowSource</span></code> (defined in module <code class="docutils literal notranslate"><span class="pre">semmle.code.csharp.dataflow.flowsources.PublicCallableParameter</span></code>) represents data flow from public parameters, which is useful for finding security problems in a public API.</p>
<p>The class <code class="docutils literal notranslate"><span class="pre">RemoteFlowSource</span></code> (defined in module <code class="docutils literal notranslate"><span class="pre">semmle.code.csharp.dataflow.flowsources.Remote</span></code>) represents data flow from remote network inputs. This is useful for finding security problems in networked services.</p>
</section>
<section id="example">
<h3>Example<a class="headerlink" href="#example" title="Link to this heading"></a></h3>
<p>This query shows a data flow configuration that uses all public API parameters as data sources:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
import semmle.code.csharp.dataflow.flowsources.PublicCallableParameter
class MyDataFlowConfiguration extends DataFlow::Configuration {
MyDataFlowConfiguration() {
this = &quot;...&quot;
}
override predicate isSource(DataFlow::Node source) {
source instanceof PublicCallableParameterFlowSource
}
...
}
</pre></div>
</div>
</section>
<section id="class-hierarchy">
<h3>Class hierarchy<a class="headerlink" href="#class-hierarchy" title="Link to this heading"></a></h3>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">DataFlow::Configuration</span></code> - base class for custom global data flow analysis.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">DataFlow::Node</span></code> - an element behaving as a data flow node.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">DataFlow::ExprNode</span></code> - an expression behaving as a data flow node.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">DataFlow::ParameterNode</span></code> - a parameter data flow node representing the value of a parameter at function entry.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">PublicCallableParameter</span></code> - a parameter to a public method/callable in a public class.</p></li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">RemoteFlowSource</span></code> - data flow from network/remote input.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">AspNetRemoteFlowSource</span></code> - data flow from remote ASP.NET user input.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">AspNetQueryStringRemoteFlowSource</span></code> - data flow from <code class="docutils literal notranslate"><span class="pre">System.Web.HttpRequest</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">AspNetUserInputRemoveFlowSource</span></code> - data flow from <code class="docutils literal notranslate"><span class="pre">System.Web.IO.WebControls.TextBox</span></code>.</p></li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">WcfRemoteFlowSource</span></code> - data flow from a WCF web service.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">AspNetServiceRemoteFlowSource</span></code> - data flow from an ASP.NET web service.</p></li>
</ul>
</li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">TaintTracking::Configuration</span></code> - base class for custom global taint tracking analysis.</p></li>
</ul>
</section>
<section id="id1">
<h3>Examples<a class="headerlink" href="#id1" title="Link to this heading"></a></h3>
<p>This data flow configuration tracks data flow from environment variables to opening files:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
class EnvironmentToFileConfiguration extends DataFlow::Configuration {
EnvironmentToFileConfiguration() { this = &quot;Environment opening files&quot; }
override predicate isSource(DataFlow::Node source) {
exists(Method m |
m = source.asExpr().(MethodCall).getTarget() and
m.hasQualifiedName(&quot;System.Environment.GetEnvironmentVariable&quot;)
)
}
override predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc |
mc.getTarget().hasQualifiedName(&quot;System.IO.File.Open&quot;) and
sink.asExpr() = mc.getArgument(0)
)
}
}
from Expr environment, Expr fileOpen, EnvironmentToFileConfiguration config
where config.hasFlow(DataFlow::exprNode(environment), DataFlow::exprNode(fileOpen))
select fileOpen, &quot;This &#39;File.Open&#39; uses data from $@.&quot;,
environment, &quot;call to &#39;GetEnvironmentVariable&#39;&quot;
</pre></div>
</div>
</section>
<section id="id2">
<h3>Exercises<a class="headerlink" href="#id2" title="Link to this heading"></a></h3>
<p>Exercise 2: Find all hard-coded strings passed to <code class="docutils literal notranslate"><span class="pre">System.Uri</span></code>, using global data flow. (<a class="reference external" href="#exercise-2">Answer</a>)</p>
<p>Exercise 3: Define a class that represents flow sources from <code class="docutils literal notranslate"><span class="pre">System.Environment.GetEnvironmentVariable</span></code>. (<a class="reference external" href="#exercise-3">Answer</a>)</p>
<p>Exercise 4: Using the answers from 2 and 3, write a query to find all global data flow from <code class="docutils literal notranslate"><span class="pre">System.Environment.GetEnvironmentVariable</span></code> to <code class="docutils literal notranslate"><span class="pre">System.Uri</span></code>. (<a class="reference external" href="#exercise-4">Answer</a>)</p>
</section>
</section>
<section id="extending-library-data-flow">
<h2>Extending library data flow<a class="headerlink" href="#extending-library-data-flow" title="Link to this heading"></a></h2>
<p>Library data flow defines how data flows through libraries where the source code is not available, such as the .NET Framework, third-party libraries or proprietary libraries.</p>
<p>To define new library data flow, extend the class <code class="docutils literal notranslate"><span class="pre">LibraryTypeDataFlow</span></code> from the module <code class="docutils literal notranslate"><span class="pre">semmle.code.csharp.dataflow.LibraryTypeDataFlow</span></code>. Override the predicate <code class="docutils literal notranslate"><span class="pre">callableFlow</span></code> to define how data flows through the methods in the class. <code class="docutils literal notranslate"><span class="pre">callableFlow</span></code> has the signature</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable callable, boolean preservesValue)
</pre></div>
</div>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">callable</span></code> - the <code class="docutils literal notranslate"><span class="pre">Callable</span></code> (such as a method, constructor, property getter or setter) performing the data flow.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">source</span></code> - the data flow input.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">sink</span></code> - the data flow output.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">preservesValue</span></code> - whether the flow step preserves the value, for example if <code class="docutils literal notranslate"><span class="pre">x</span></code> is a string then <code class="docutils literal notranslate"><span class="pre">x.ToString()</span></code> preserves the value where as <code class="docutils literal notranslate"><span class="pre">x.ToLower()</span></code> does not.</p></li>
</ul>
<section id="id3">
<h3>Class hierarchy<a class="headerlink" href="#id3" title="Link to this heading"></a></h3>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">Callable</span></code> - a callable (methods, accessors, constructors etc.)</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">SourceDeclarationCallable</span></code> - an unconstructed callable.</p></li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">CallableFlowSource</span></code> - the input of data flow into the callable.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">CallableFlowSourceQualifier</span></code> - the data flow comes from the object itself.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CallableFlowSourceArg</span></code> - the data flow comes from an argument to the call.</p></li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">CallableFlowSink</span></code> - the output of data flow from the callable.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">CallableFlowSinkQualifier</span></code> - the output is to the object itself.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CallableFlowSinkReturn</span></code> - the output is returned from the call.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CallableFlowSinkArg</span></code> - the output is an argument.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CallableFlowSinkDelegateArg</span></code> - the output flows through a delegate argument (for example, LINQ).</p></li>
</ul>
</li>
</ul>
</section>
<section id="id4">
<h3>Example<a class="headerlink" href="#id4" title="Link to this heading"></a></h3>
<p>This example is adapted from <code class="docutils literal notranslate"><span class="pre">LibraryTypeDataFlow.qll</span></code>. It declares data flow through the class <code class="docutils literal notranslate"><span class="pre">System.Uri</span></code>, including the constructor, the <code class="docutils literal notranslate"><span class="pre">ToString</span></code> method, and the properties <code class="docutils literal notranslate"><span class="pre">Query</span></code>, <code class="docutils literal notranslate"><span class="pre">OriginalString</span></code>, and <code class="docutils literal notranslate"><span class="pre">PathAndQuery</span></code>.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import semmle.code.csharp.dataflow.LibraryTypeDataFlow
import semmle.code.csharp.frameworks.System
class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass {
override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) {
(
constructorFlow(source, c) and
sink instanceof CallableFlowSinkQualifier
or
methodFlow(c) and
source instanceof CallableFlowSourceQualifier and
sink instanceof CallableFlowSinkReturn
or
exists(Property p |
propertyFlow(p) and
source instanceof CallableFlowSourceQualifier and
sink instanceof CallableFlowSinkReturn and
c = p.getGetter()
)
)
and
preservesValue = false
}
private predicate constructorFlow(CallableFlowSourceArg source, Constructor c) {
c = getAMember()
and
c.getParameter(0).getType() instanceof StringType
and
source.getArgumentIndex() = 0
}
private predicate methodFlow(Method m) {
m.getDeclaringType() = getABaseType*()
and
m = getSystemObjectClass().getToStringMethod().getAnOverrider*()
}
private predicate propertyFlow(Property p) {
p = getPathAndQueryProperty()
or
p = getQueryProperty()
or
p = getOriginalStringProperty()
}
}
</pre></div>
</div>
<p>This defines a new class <code class="docutils literal notranslate"><span class="pre">SystemUriFlow</span></code> which extends <code class="docutils literal notranslate"><span class="pre">LibraryTypeDataFlow</span></code> to add another case. It extends <code class="docutils literal notranslate"><span class="pre">SystemUriClass</span></code> (the class representing <code class="docutils literal notranslate"><span class="pre">System.Uri</span></code>, defined in the module <code class="docutils literal notranslate"><span class="pre">semmle.code.csharp.frameworks.System</span></code>) to access methods such as <code class="docutils literal notranslate"><span class="pre">getQueryProperty</span></code>.</p>
<p>The predicate <code class="docutils literal notranslate"><span class="pre">callableFlow</span></code> declares data flow through <code class="docutils literal notranslate"><span class="pre">System.Uri</span></code>. The first case (<code class="docutils literal notranslate"><span class="pre">constructorFlow</span></code>) declares data flow from the first argument of the constructor to the object itself (<code class="docutils literal notranslate"><span class="pre">CallableFlowSinkQualifier</span></code>).</p>
<p>The second case declares data flow from the object (<code class="docutils literal notranslate"><span class="pre">CallableFlowSourceQualifier</span></code>) to the result of calling <code class="docutils literal notranslate"><span class="pre">ToString</span></code> on the object (<code class="docutils literal notranslate"><span class="pre">CallableFlowSinkReturn</span></code>).</p>
<p>The third case declares data flow from the object (<code class="docutils literal notranslate"><span class="pre">CallableFlowSourceQualifier</span></code>) to the return (<code class="docutils literal notranslate"><span class="pre">CallableFlowSinkReturn</span></code>) of the getters for the properties <code class="docutils literal notranslate"><span class="pre">PathAndQuery</span></code>, <code class="docutils literal notranslate"><span class="pre">Query</span></code> and <code class="docutils literal notranslate"><span class="pre">OriginalString</span></code>. Note that the properties (<code class="docutils literal notranslate"><span class="pre">getPathAndQueryProperty</span></code>, <code class="docutils literal notranslate"><span class="pre">getQueryProperty</span></code> and <code class="docutils literal notranslate"><span class="pre">getOriginalStringProperty</span></code>) are inherited from the class <code class="docutils literal notranslate"><span class="pre">SystemUriClass</span></code>.</p>
<p>In all three cases <code class="docutils literal notranslate"><span class="pre">preservesValue</span> <span class="pre">=</span> <span class="pre">false</span></code>, which means that these steps will only be included in taint tracking, not in (normal) data flow.</p>
</section>
<section id="id5">
<h3>Exercises<a class="headerlink" href="#id5" title="Link to this heading"></a></h3>
<p>Exercise 5: In <code class="docutils literal notranslate"><span class="pre">System.Uri</span></code>, what other properties could expose data? How could they be added to <code class="docutils literal notranslate"><span class="pre">SystemUriFlow</span></code>? (<a class="reference external" href="#exercise-5">Answer</a>)</p>
<p>Exercise 6: Implement the data flow for the class <code class="docutils literal notranslate"><span class="pre">System.Exception</span></code>. (<a class="reference external" href="#exercise-6">Answer</a>)</p>
</section>
</section>
<hr class="docutils" />
<section id="answers">
<h2>Answers<a class="headerlink" href="#answers" title="Link to this heading"></a></h2>
<section id="exercise-1">
<h3>Exercise 1<a class="headerlink" href="#exercise-1" title="Link to this heading"></a></h3>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
from Expr src, Call c
where DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(c.getArgument(0)))
and c.getTarget().(Constructor).getDeclaringType().hasQualifiedName(&quot;System.Uri&quot;)
and src.hasValue()
select src, &quot;This string constructs &#39;System.Uri&#39; $@.&quot;, c, &quot;here&quot;
</pre></div>
</div>
</section>
<section id="exercise-2">
<h3>Exercise 2<a class="headerlink" href="#exercise-2" title="Link to this heading"></a></h3>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
class Configuration extends DataFlow::Configuration {
Configuration() { this=&quot;String to System.Uri&quot; }
override predicate isSource(DataFlow::Node src) {
src.asExpr().hasValue()
}
override predicate isSink(DataFlow::Node sink) {
exists(Call c | c.getTarget().(Constructor).getDeclaringType().hasQualifiedName(&quot;System.Uri&quot;)
and sink.asExpr()=c.getArgument(0))
}
}
from DataFlow::Node src, DataFlow::Node sink, Configuration config
where config.hasFlow(src, sink)
select src, &quot;This string constructs a &#39;System.Uri&#39; $@.&quot;, sink, &quot;here&quot;
</pre></div>
</div>
</section>
<section id="exercise-3">
<h3>Exercise 3<a class="headerlink" href="#exercise-3" title="Link to this heading"></a></h3>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>class EnvironmentVariableFlowSource extends DataFlow::ExprNode {
EnvironmentVariableFlowSource() {
this.getExpr().(MethodCall).getTarget().hasQualifiedName(&quot;System.Environment.GetEnvironmentVariable&quot;)
}
}
</pre></div>
</div>
</section>
<section id="exercise-4">
<h3>Exercise 4<a class="headerlink" href="#exercise-4" title="Link to this heading"></a></h3>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import csharp
class EnvironmentVariableFlowSource extends DataFlow::ExprNode {
EnvironmentVariableFlowSource() {
this.getExpr().(MethodCall).getTarget().hasQualifiedName(&quot;System.Environment.GetEnvironmentVariable&quot;)
}
}
class Configuration extends DataFlow::Configuration {
Configuration() { this=&quot;Environment to System.Uri&quot; }
override predicate isSource(DataFlow::Node src) {
src instanceof EnvironmentVariableFlowSource
}
override predicate isSink(DataFlow::Node sink) {
exists(Call c | c.getTarget().(Constructor).getDeclaringType().hasQualifiedName(&quot;System.Uri&quot;)
and sink.asExpr()=c.getArgument(0))
}
}
from DataFlow::Node src, DataFlow::Node sink, Configuration config
where config.hasFlow(src, sink)
select src, &quot;This environment variable constructs a &#39;System.Uri&#39; $@.&quot;, sink, &quot;here&quot;
</pre></div>
</div>
</section>
<section id="exercise-5">
<h3>Exercise 5<a class="headerlink" href="#exercise-5" title="Link to this heading"></a></h3>
<p>All properties can flow data:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>private predicate propertyFlow(Property p) {
p = getAMember()
}
</pre></div>
</div>
</section>
<section id="exercise-6">
<h3>Exercise 6<a class="headerlink" href="#exercise-6" title="Link to this heading"></a></h3>
<p>This can be adapted from the <code class="docutils literal notranslate"><span class="pre">SystemUriFlow</span></code> class:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import semmle.code.csharp.dataflow.LibraryTypeDataFlow
import semmle.code.csharp.frameworks.System
class SystemExceptionFlow extends LibraryTypeDataFlow, SystemExceptionClass {
override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) {
(
constructorFlow(source, c) and
sink instanceof CallableFlowSinkQualifier
or
methodFlow(source, sink, c)
or
exists(Property p |
propertyFlow(p) and
source instanceof CallableFlowSourceQualifier and
sink instanceof CallableFlowSinkReturn and
c = p.getGetter()
)
)
and
preservesValue = false
}
private predicate constructorFlow(CallableFlowSourceArg source, Constructor c) {
c = getAMember()
and
c.getParameter(0).getType() instanceof StringType
and
source.getArgumentIndex() = 0
}
private predicate methodFlow(CallableFlowSourceQualifier source, CallableFlowSinkReturn sink, SourceDeclarationMethod m) {
m.getDeclaringType() = getABaseType*()
and
m = getSystemObjectClass().getToStringMethod().getAnOverrider*()
}
private predicate propertyFlow(Property p) {
p = getAProperty() and p.hasName(&quot;Message&quot;)
}
}
</pre></div>
</div>
</section>
</section>
<section id="further-reading">
<h2>Further reading<a class="headerlink" href="#further-reading" title="Link to this heading"></a></h2>
<ul class="simple">
<li><p><a class="reference internal" href="../codeql-for-visual-studio-code/exploring-data-flow-with-path-queries.html#exploring-data-flow-with-path-queries"><span class="std std-ref">Exploring data flow with path queries</span></a></p></li>
</ul>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/csharp/ql/src">CodeQL queries for C#</a></p></li>
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/csharp/ql/examples">Example queries for C#</a></p></li>
<li><p><a class="reference external" href="https://codeql.github.com/codeql-standard-libraries/csharp/">CodeQL library reference for C#</a></p></li>
</ul>
<ul class="simple">
<li><p><a class="reference internal" href="../ql-language-reference/index.html#ql-language-reference"><span class="std std-ref">QL language reference</span></a></p></li>
<li><p><a class="reference internal" href="../codeql-overview/codeql-tools.html#codeql-tools"><span class="std std-ref">CodeQL tools</span></a></p></li>
</ul>
</section>
</section>
</article>
<!-- GitHub footer, with links to terms and privacy statement -->
<div class="px-3 px-md-6 f6 py-4 d-sm-flex flex-justify-between flex-row-reverse flex-items-center border-top">
<ul class="list-style-none d-flex flex-items-center mb-3 mb-sm-0 lh-condensed-ultra">
<li class="mr-3">
<a href="https://twitter.com/github" title="GitHub on Twitter" style="color: #959da5;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 273.5 222.3" class="d-block" height="18">
<path
d="M273.5 26.3a109.77 109.77 0 0 1-32.2 8.8 56.07 56.07 0 0 0 24.7-31 113.39 113.39 0 0 1-35.7 13.6 56.1 56.1 0 0 0-97 38.4 54 54 0 0 0 1.5 12.8A159.68 159.68 0 0 1 19.1 10.3a56.12 56.12 0 0 0 17.4 74.9 56.06 56.06 0 0 1-25.4-7v.7a56.11 56.11 0 0 0 45 55 55.65 55.65 0 0 1-14.8 2 62.39 62.39 0 0 1-10.6-1 56.24 56.24 0 0 0 52.4 39 112.87 112.87 0 0 1-69.7 24 119 119 0 0 1-13.4-.8 158.83 158.83 0 0 0 86 25.2c103.2 0 159.6-85.5 159.6-159.6 0-2.4-.1-4.9-.2-7.3a114.25 114.25 0 0 0 28.1-29.1"
fill="currentColor"></path>
</svg>
</a>
</li>
<li class="mr-3">
<a href="https://www.facebook.com/GitHub" title="GitHub on Facebook" style="color: #959da5;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.3 15.4" class="d-block" height="18">
<path
d="M14.5 0H.8a.88.88 0 0 0-.8.9v13.6a.88.88 0 0 0 .8.9h7.3v-6h-2V7.1h2V5.4a2.87 2.87 0 0 1 2.5-3.1h.5a10.87 10.87 0 0 1 1.8.1v2.1h-1.3c-1 0-1.1.5-1.1 1.1v1.5h2.3l-.3 2.3h-2v5.9h3.9a.88.88 0 0 0 .9-.8V.8a.86.86 0 0 0-.8-.8z"
fill="currentColor"></path>
</svg>
</a>
</li>
<li class="mr-3">
<a href="https://www.youtube.com/github" title="GitHub on YouTube" style="color: #959da5;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.17 13.6" class="d-block" height="16">
<path
d="M18.77 2.13A2.4 2.4 0 0 0 17.09.42C15.59 0 9.58 0 9.58 0a57.55 57.55 0 0 0-7.5.4A2.49 2.49 0 0 0 .39 2.13 26.27 26.27 0 0 0 0 6.8a26.15 26.15 0 0 0 .39 4.67 2.43 2.43 0 0 0 1.69 1.71c1.52.42 7.5.42 7.5.42a57.69 57.69 0 0 0 7.51-.4 2.4 2.4 0 0 0 1.68-1.71 25.63 25.63 0 0 0 .4-4.67 24 24 0 0 0-.4-4.69zM7.67 9.71V3.89l5 2.91z"
fill="currentColor"></path>
</svg>
</a>
</li>
<li class="mr-3 flex-self-start">
<a href="https://www.linkedin.com/company/github" title="GitHub on Linkedin" style="color: #959da5;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19 18" class="d-block" height="18">
<path
d="M3.94 2A2 2 0 1 1 2 0a2 2 0 0 1 1.94 2zM4 5.48H0V18h4zm6.32 0H6.34V18h3.94v-6.57c0-3.66 4.77-4 4.77 0V18H19v-7.93c0-6.17-7.06-5.94-8.72-2.91z"
fill="currentColor"></path>
</svg>
</a>
</li>
<li>
<a href="https://github.com/github" title="GitHub's organization" style="color: #959da5;">
<svg version="1.1" width="20" height="20" viewBox="0 0 16 16" class="octicon octicon-mark-github"
aria-hidden="true">
<path fill-rule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
</path>
</svg>
</a>
</li>
</ul>
<ul class="list-style-none d-flex text-gray">
<li class="mr-3">&copy;
<script type="text/javascript">document.write(new Date().getFullYear());</script> GitHub, Inc.</li>
<li class="mr-3"><a
href="https://docs.github.com/github/site-policy/github-terms-of-service"
class="link-gray">Terms </a></li>
<li><a href="https://docs.github.com/github/site-policy/github-privacy-statement"
class="link-gray">Privacy </a></li>
</ul>
</div>
</div>
</main>
<script type="text/javascript">
$(document).ready(function () {
$(".toggle > *").hide();
$(".toggle .name").show();
$(".toggle .name").click(function () {
$(this).parent().children().not(".name").toggle(400);
$(this).parent().children(".name").toggleClass("open");
})
});
</script>
</body>
</html>