mirror of
https://github.com/hohn/codeql-info.git
synced 2025-12-16 20:53:04 +01:00
577 lines
38 KiB
HTML
577 lines
38 KiB
HTML
<!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 and C++ — 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="Refining a query to account for edge cases" href="refining-a-query-to-account-for-edge-cases.html" />
|
|
<link rel="prev" title="Conversions and classes in C and C++" href="conversions-and-classes-in-cpp.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 current"><a class="reference internal" href="codeql-for-cpp.html">CodeQL for C and C++</a><ul class="current">
|
|
<li class="toctree-l3"><a class="reference internal" href="basic-query-for-cpp-code.html">Basic query for C and C++ code</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="codeql-library-for-cpp.html">CodeQL library for C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="functions-in-cpp.html">Functions in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="expressions-types-and-statements-in-cpp.html">Expressions, types, and statements in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="conversions-and-classes-in-cpp.html">Conversions and classes in C and C++</a></li>
|
|
<li class="toctree-l3 current"><a class="current reference internal" href="#">Analyzing data flow in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="refining-a-query-to-account-for-edge-cases.html">Refining a query to account for edge cases</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="detecting-a-potential-buffer-overflow.html">Detecting a potential buffer overflow</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="using-the-guards-library-in-cpp.html">Using the guards library in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="using-range-analsis-in-cpp.html">Using range analysis for C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="hash-consing-and-value-numbering.html">Hash consing and value numbering</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-csharp.html">CodeQL for C#</a></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> »</li>
|
|
<li class="nav-item nav-item-1"><a href="index.html"
|
|
>CodeQL language guides</a> »</li>
|
|
<li class="nav-item nav-item-2"><a href="codeql-for-cpp.html"
|
|
accesskey="U">CodeQL for C and C++</a> »</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<article class="p-4 col-lg-10 col-md-10 col-sm-12">
|
|
|
|
<section id="analyzing-data-flow-in-c-and-c">
|
|
<span id="analyzing-data-flow-in-cpp"></span><h1>Analyzing data flow in C and C++<a class="headerlink" href="#analyzing-data-flow-in-c-and-c" title="Link to this heading">¶</a></h1>
|
|
<p>You can use data flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase.</p>
|
|
<section id="about-data-flow">
|
|
<h2>About data flow<a class="headerlink" href="#about-data-flow" title="Link to this heading">¶</a></h2>
|
|
<p>Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. 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 function. Local data flow is usually 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>). It is possible to 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>. The predicate can be applied recursively (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 through the predefined recursive predicate <code class="docutils literal notranslate"><span class="pre">localFlow</span></code>, which is equivalent to <code class="docutils literal notranslate"><span class="pre">localFlowStep*</span></code>.</p>
|
|
<p>For example, finding 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 can be achieved as follows:</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-cpp notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tainted_user_input</span><span class="p">();</span>
|
|
<span class="n">some_big_struct</span><span class="w"> </span><span class="o">*</span><span class="n">array</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">malloc</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">some_big_struct</span><span class="p">));</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>In this case, the argument to <code class="docutils literal notranslate"><span class="pre">malloc</span></code> is 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>. The predicate can be applied recursively (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 through the predefined recursive predicate <code class="docutils literal notranslate"><span class="pre">localTaint</span></code>, which is equivalent to <code class="docutils literal notranslate"><span class="pre">localTaintStep*</span></code>.</p>
|
|
<p>For example, finding 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 can be achieved as follows:</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>The following query finds the filename passed to <code class="docutils literal notranslate"><span class="pre">fopen</span></code>.</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import cpp
|
|
|
|
from Function fopen, FunctionCall fc
|
|
where fopen.hasQualifiedName("fopen")
|
|
and fc.getTarget() = fopen
|
|
select fc.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 cpp
|
|
import semmle.code.cpp.dataflow.DataFlow
|
|
|
|
from Function fopen, FunctionCall fc, Expr src
|
|
where fopen.hasQualifiedName("fopen")
|
|
and fc.getTarget() = fopen
|
|
and DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(fc.getArgument(0)))
|
|
select src
|
|
</pre></div>
|
|
</div>
|
|
<p>Then we can vary the source, for example an access to a public parameter. The following query finds where a public parameter is used to open a file:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import cpp
|
|
import semmle.code.cpp.dataflow.DataFlow
|
|
|
|
from Function fopen, FunctionCall fc, Parameter p
|
|
where fopen.hasQualifiedName("fopen")
|
|
and fc.getTarget() = fopen
|
|
and DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(fc.getArgument(0)))
|
|
select p
|
|
</pre></div>
|
|
</div>
|
|
<p>The following example finds calls to formatting functions where the format string is not hard-coded.</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import semmle.code.cpp.dataflow.DataFlow
|
|
import semmle.code.cpp.commons.Printf
|
|
|
|
from FormattingFunction format, FunctionCall call, Expr formatString
|
|
where call.getTarget() = format
|
|
and call.getArgument(format.getFormatParameterIndex()) = formatString
|
|
and not exists(DataFlow::Node source, DataFlow::Node sink |
|
|
DataFlow::localFlow(source, sink) and
|
|
source.asExpr() instanceof StringLiteral and
|
|
sink.asExpr() = formatString
|
|
)
|
|
select call, "Argument to " + format.getQualifiedName() + " isn't hard-coded."
|
|
</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">host_ent</span></code> via <code class="docutils literal notranslate"><span class="pre">gethostbyname</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> as follows:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import semmle.code.cpp.dataflow.DataFlow
|
|
|
|
class MyDataFlowConfiguration extends DataFlow::Configuration {
|
|
MyDataFlowConfiguration() { this = "MyDataFlowConfiguration" }
|
|
|
|
override predicate isSource(DataFlow::Node source) {
|
|
...
|
|
}
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
...
|
|
}
|
|
}
|
|
</pre></div>
|
|
</div>
|
|
<p>The following 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>—optional, restricts the data flow</p></li>
|
|
<li><p><code class="docutils literal notranslate"><span class="pre">isBarrierGuard</span></code>—optional, restricts the data flow</p></li>
|
|
<li><p><code class="docutils literal notranslate"><span class="pre">isAdditionalFlowStep</span></code>—optional, 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">"MyDataFlowConfiguration"</span></code> should be replaced by the name of your class.</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 MyDataFlowConfiguration dataflow, DataFlow::Node source, DataFlow::Node sink
|
|
where dataflow.hasFlow(source, sink)
|
|
select source, "Data flow to $@.", 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 as 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> as follows:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import semmle.code.cpp.dataflow.TaintTracking
|
|
|
|
class MyTaintTrackingConfiguration extends TaintTracking::Configuration {
|
|
MyTaintTrackingConfiguration() { this = "MyTaintTrackingConfiguration" }
|
|
|
|
override predicate isSource(DataFlow::Node source) {
|
|
...
|
|
}
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
...
|
|
}
|
|
}
|
|
</pre></div>
|
|
</div>
|
|
<p>The following 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>—optional, restricts the taint flow</p></li>
|
|
<li><p><code class="docutils literal notranslate"><span class="pre">isSanitizerGuard</span></code>—optional, restricts the taint flow</p></li>
|
|
<li><p><code class="docutils literal notranslate"><span class="pre">isAdditionalTaintStep</span></code>—optional, 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, so <code class="docutils literal notranslate"><span class="pre">"MyTaintTrackingConfiguration"</span></code> should be replaced by the name of your class.</p>
|
|
<p>The taint tracking 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="id1">
|
|
<h3>Examples<a class="headerlink" href="#id1" title="Link to this heading">¶</a></h3>
|
|
<p>The following data flow configuration tracks data flow from environment variables to opening files in a Unix-like environment:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import semmle.code.cpp.dataflow.DataFlow
|
|
|
|
class EnvironmentToFileConfiguration extends DataFlow::Configuration {
|
|
EnvironmentToFileConfiguration() { this = "EnvironmentToFileConfiguration" }
|
|
|
|
override predicate isSource(DataFlow::Node source) {
|
|
exists (Function getenv |
|
|
source.asExpr().(FunctionCall).getTarget() = getenv and
|
|
getenv.hasQualifiedName("getenv")
|
|
)
|
|
}
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
exists (FunctionCall fc |
|
|
sink.asExpr() = fc.getArgument(0) and
|
|
fc.getTarget().hasQualifiedName("fopen")
|
|
)
|
|
}
|
|
}
|
|
|
|
from Expr getenv, Expr fopen, EnvironmentToFileConfiguration config
|
|
where config.hasFlow(DataFlow::exprNode(getenv), DataFlow::exprNode(fopen))
|
|
select fopen, "This 'fopen' uses data from $@.",
|
|
getenv, "call to 'getenv'"
|
|
</pre></div>
|
|
</div>
|
|
<p>The following taint-tracking configuration tracks data from a call to <code class="docutils literal notranslate"><span class="pre">ntohl</span></code> to an array index operation. It uses the <code class="docutils literal notranslate"><span class="pre">Guards</span></code> library to recognize expressions that have been bounds-checked, and defines <code class="docutils literal notranslate"><span class="pre">isSanitizer</span></code> to prevent taint from propagating through them. It also uses <code class="docutils literal notranslate"><span class="pre">isAdditionalTaintStep</span></code> to add flow from loop bounds to loop indexes.</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import cpp
|
|
import semmle.code.cpp.controlflow.Guards
|
|
import semmle.code.cpp.dataflow.TaintTracking
|
|
|
|
class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration {
|
|
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
|
|
|
|
override predicate isSource(DataFlow::Node node) {
|
|
node.asExpr().(FunctionCall).getTarget().hasGlobalName("ntohl")
|
|
}
|
|
|
|
override predicate isSink(DataFlow::Node node) {
|
|
exists(ArrayExpr ae | node.asExpr() = ae.getArrayOffset())
|
|
}
|
|
|
|
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
|
exists(Loop loop, LoopCounter lc |
|
|
loop = lc.getALoop() and
|
|
loop.getControllingExpr().(RelationalOperation).getGreaterOperand() = pred.asExpr() |
|
|
succ.asExpr() = lc.getVariableAccessInLoop(loop)
|
|
)
|
|
}
|
|
|
|
override predicate isSanitizer(DataFlow::Node node) {
|
|
exists(GuardCondition gc, Variable v |
|
|
gc.getAChild*() = v.getAnAccess() and
|
|
node.asExpr() = v.getAnAccess() and
|
|
gc.controls(node.asExpr().getBasicBlock(), _)
|
|
)
|
|
}
|
|
}
|
|
|
|
from DataFlow::Node ntohl, DataFlow::Node offset, NetworkToBufferSizeConfiguration conf
|
|
where conf.hasFlow(ntohl, offset)
|
|
select offset, "This array offset may be influenced by $@.", ntohl,
|
|
"converted data from the network"
|
|
</pre></div>
|
|
</div>
|
|
</section>
|
|
<section id="id2">
|
|
<h3>Exercises<a class="headerlink" href="#id2" title="Link to this heading">¶</a></h3>
|
|
<p>Exercise 2: Write a query that finds all hard-coded strings used to create a <code class="docutils literal notranslate"><span class="pre">host_ent</span></code> via <code class="docutils literal notranslate"><span class="pre">gethostbyname</span></code>, using global data flow. (<a class="reference external" href="#exercise-2">Answer</a>)</p>
|
|
<p>Exercise 3: Write a class that represents flow sources from <code class="docutils literal notranslate"><span class="pre">getenv</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 which finds all global data flows from <code class="docutils literal notranslate"><span class="pre">getenv</span></code> to <code class="docutils literal notranslate"><span class="pre">gethostbyname</span></code>. (<a class="reference external" href="#exercise-4">Answer</a>)</p>
|
|
</section>
|
|
</section>
|
|
<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 semmle.code.cpp.dataflow.DataFlow
|
|
|
|
from StringLiteral sl, FunctionCall fc
|
|
where fc.getTarget().hasName("gethostbyname")
|
|
and DataFlow::localFlow(DataFlow::exprNode(sl), DataFlow::exprNode(fc.getArgument(0)))
|
|
select sl, fc
|
|
</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 semmle.code.cpp.dataflow.DataFlow
|
|
|
|
class LiteralToGethostbynameConfiguration extends DataFlow::Configuration {
|
|
LiteralToGethostbynameConfiguration() {
|
|
this = "LiteralToGethostbynameConfiguration"
|
|
}
|
|
|
|
override predicate isSource(DataFlow::Node source) {
|
|
source.asExpr() instanceof StringLiteral
|
|
}
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
exists (FunctionCall fc |
|
|
sink.asExpr() = fc.getArgument(0) and
|
|
fc.getTarget().hasName("gethostbyname"))
|
|
}
|
|
}
|
|
|
|
from StringLiteral sl, FunctionCall fc, LiteralToGethostbynameConfiguration cfg
|
|
where cfg.hasFlow(DataFlow::exprNode(sl), DataFlow::exprNode(fc.getArgument(0)))
|
|
select sl, fc
|
|
</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>import cpp
|
|
|
|
class GetenvSource extends FunctionCall {
|
|
GetenvSource() {
|
|
this.getTarget().hasQualifiedName("getenv")
|
|
}
|
|
}
|
|
</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 semmle.code.cpp.dataflow.DataFlow
|
|
|
|
class GetenvSource extends DataFlow::Node {
|
|
GetenvSource() {
|
|
this.asExpr().(FunctionCall).getTarget().hasQualifiedName("getenv")
|
|
}
|
|
}
|
|
|
|
class GetenvToGethostbynameConfiguration extends DataFlow::Configuration {
|
|
GetenvToGethostbynameConfiguration() {
|
|
this = "GetenvToGethostbynameConfiguration"
|
|
}
|
|
|
|
override predicate isSource(DataFlow::Node source) {
|
|
source instanceof GetenvSource
|
|
}
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
exists (FunctionCall fc |
|
|
sink.asExpr() = fc.getArgument(0) and
|
|
fc.getTarget().hasName("gethostbyname"))
|
|
}
|
|
}
|
|
|
|
from DataFlow::Node getenv, FunctionCall fc, GetenvToGethostbynameConfiguration cfg
|
|
where cfg.hasFlow(getenv, DataFlow::exprNode(fc.getArgument(0)))
|
|
select getenv.asExpr(), fc
|
|
</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/cpp/ql/src">CodeQL queries for C and C++</a></p></li>
|
|
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/cpp/ql/examples">Example queries for C and C++</a></p></li>
|
|
<li><p><a class="reference external" href="https://codeql.github.com/codeql-standard-libraries/cpp/">CodeQL library reference for C and 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">©
|
|
<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> |