mirror of
https://github.com/hohn/codeql-info.git
synced 2025-12-16 20:53:04 +01:00
603 lines
39 KiB
HTML
603 lines
39 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++ (new) — 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="Analyzing data flow in C and C++" href="analyzing-data-flow-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"><a class="reference internal" href="analyzing-data-flow-in-cpp.html">Analyzing data flow in C and C++</a></li>
|
|
<li class="toctree-l3 current"><a class="current reference internal" href="#">Analyzing data flow in C and C++ (new)</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>
|
|
<li class="toctree-l3"><a class="reference internal" href="advanced-dataflow-scenarios-cpp.html">Advanced dataflow scenarios for C/C++</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 and Kotlin</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-javascript.html">CodeQL for JavaScript and TypeScript</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>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-swift.html">CodeQL for Swift</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">
|
|
|
|
<blockquote class="pull-quote" id="analyzing-data-flow-in-cpp-new">
|
|
<div><p>Note</p>
|
|
<p>The data flow library described here is available from CodeQL 2.12.5 onwards. With the release of CodeQL 2.13.0 the library uses the new modular API for data flow. For information on the previous version of the library, see <a class="reference internal" href="analyzing-data-flow-in-cpp.html#analyzing-data-flow-in-cpp"><span class="std std-ref">Analyzing data flow in C and C++</span></a> and for information about the new modular API and how to migrate any existing queries to the updated data flow library, see <a class="reference external" href="https://gh.io/codeql-new-dataflow-api">New dataflow API for CodeQL query writing</a>.</p>
|
|
</div></blockquote>
|
|
<section id="analyzing-data-flow-in-c-and-c-new">
|
|
<h1>Analyzing data flow in C and C++ (new)<a class="headerlink" href="#analyzing-data-flow-in-c-and-c-new" 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>, <code class="docutils literal notranslate"><span class="pre">IndirectExprNode</span></code>) and parameter nodes (<code class="docutils literal notranslate"><span class="pre">ParameterNode</span></code>, <code class="docutils literal notranslate"><span class="pre">IndirectParameterNode</span></code>). The indirect nodes represent expressions or parameters after a fixed number of pointer dereferences.</p>
|
|
<p>It is possible to map between data flow nodes and expressions or parameters using the member predicates <code class="docutils literal notranslate"><span class="pre">asExpr</span></code>, <code class="docutils literal notranslate"><span class="pre">asIndirectExpr</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 expression corresponding to a node that is obtained after dereferencing
|
|
* the expression `index` times, if any.
|
|
*/
|
|
Expr asIndirectExpr(int index) { ... }
|
|
|
|
/**
|
|
* Gets the parameter corresponding to this node, if any.
|
|
*/
|
|
Parameter asParameter() { ... }
|
|
|
|
/**
|
|
* Gets the parameter corresponding to a node that is obtained after dereferencing
|
|
* the parameter `index` times.
|
|
*/
|
|
Parameter asParameter(int index) { ... }
|
|
|
|
...
|
|
}
|
|
</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, where <code class="docutils literal notranslate"><span class="pre">nodeFrom</span></code> and <code class="docutils literal notranslate"><span class="pre">nodeTo</span></code> are of type <code class="docutils literal notranslate"><span class="pre">DataFlow::Node</span></code>:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>nodeFrom.asParameter() = source and
|
|
nodeTo.asExpr() = sink and
|
|
DataFlow::localFlow(nodeFrom, nodeTo)
|
|
</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, where <code class="docutils literal notranslate"><span class="pre">nodeFrom</span></code> and <code class="docutils literal notranslate"><span class="pre">nodeTo</span></code> are of type <code class="docutils literal notranslate"><span class="pre">DataFlow::Node</span></code>:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>nodeFrom.asParameter() = source and
|
|
nodeTo.asExpr() = sink and
|
|
TaintTracking::localTaint(nodeFrom, nodeTo)
|
|
</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.hasGlobalName("fopen") and
|
|
fc.getTarget() = fopen
|
|
select fc.getArgument(0)
|
|
</pre></div>
|
|
</div>
|
|
<p>However, this will only give the expression in the argument, not the values which could be passed to it. Instead we can use local data flow to find all expressions that flow into the argument, where we use <code class="docutils literal notranslate"><span class="pre">asIndirectExpr(1)</span></code>. This is because we are interested in the value of the string passed to <cite>fopen</cite>, not the pointer pointing to it:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import cpp
|
|
import semmle.code.cpp.dataflow.new.DataFlow
|
|
|
|
from Function fopen, FunctionCall fc, Expr src, DataFlow::Node source, DataFlow::Node sink
|
|
where
|
|
fopen.hasGlobalName("fopen") and
|
|
fc.getTarget() = fopen and
|
|
source.asIndirectExpr(1) = src and
|
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
|
DataFlow::localFlow(source, sink)
|
|
select src
|
|
</pre></div>
|
|
</div>
|
|
<p>Then we can vary the source and, for example, use the parameter of a function. The following query finds where a parameter is used when opening a file:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import cpp
|
|
import semmle.code.cpp.dataflow.new.DataFlow
|
|
|
|
from Function fopen, FunctionCall fc, Parameter p, DataFlow::Node source, DataFlow::Node sink
|
|
where
|
|
fopen.hasGlobalName("fopen") and
|
|
fc.getTarget() = fopen and
|
|
source.asParameter(1) = p and
|
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
|
DataFlow::localFlow(source, sink)
|
|
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.new.DataFlow
|
|
import semmle.code.cpp.commons.Printf
|
|
|
|
from FormattingFunction format, FunctionCall call, Expr formatString, DataFlow::Node sink
|
|
where
|
|
call.getTarget() = format and
|
|
call.getArgument(format.getFormatParameterIndex()) = formatString and
|
|
sink.asIndirectExpr(1) = formatString and
|
|
not exists(DataFlow::Node source |
|
|
DataFlow::localFlow(source, sink) and
|
|
source.asIndirectExpr(1) instanceof StringLiteral
|
|
)
|
|
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 implementing the signature <code class="docutils literal notranslate"><span class="pre">DataFlow::ConfigSig</span></code> and applying the module <code class="docutils literal notranslate"><span class="pre">DataFlow::Global<ConfigSig></span></code> as follows:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import semmle.code.cpp.dataflow.new.DataFlow
|
|
|
|
module MyFlowConfiguration implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node source) {
|
|
...
|
|
}
|
|
|
|
predicate isSink(DataFlow::Node sink) {
|
|
...
|
|
}
|
|
}
|
|
|
|
module MyFlow = DataFlow::Global<MyFlowConfiguration>;
|
|
</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">isAdditionalFlowStep</span></code>—optional, adds additional flow steps</p></li>
|
|
</ul>
|
|
<p>The data flow analysis is performed using the predicate <code class="docutils literal notranslate"><span class="pre">flow(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 DataFlow::Node source, DataFlow::Node sink
|
|
where MyFlow::flow(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 applying the module <code class="docutils literal notranslate"><span class="pre">TaintTracking::Global<ConfigSig></span></code> to your configuration instead of <code class="docutils literal notranslate"><span class="pre">DataFlow::Global<ConfigSig></span></code> as follows:</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import semmle.code.cpp.dataflow.new.TaintTracking
|
|
|
|
module MyFlowConfiguration implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node source) {
|
|
...
|
|
}
|
|
|
|
predicate isSink(DataFlow::Node sink) {
|
|
...
|
|
}
|
|
}
|
|
|
|
module MyFlow = TaintTracking::Global<MyFlowConfiguration>;
|
|
</pre></div>
|
|
</div>
|
|
<p>The resulting module has an identical signature to the one obtained from <code class="docutils literal notranslate"><span class="pre">DataFlow::Global<ConfigSig></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 cpp
|
|
import semmle.code.cpp.dataflow.new.DataFlow
|
|
|
|
module EnvironmentToFileConfiguration implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node source) {
|
|
exists(Function getenv |
|
|
source.asIndirectExpr(1).(FunctionCall).getTarget() = getenv and
|
|
getenv.hasGlobalName("getenv")
|
|
)
|
|
}
|
|
|
|
predicate isSink(DataFlow::Node sink) {
|
|
exists(FunctionCall fc |
|
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
|
fc.getTarget().hasGlobalName("fopen")
|
|
)
|
|
}
|
|
}
|
|
|
|
module EnvironmentToFileFlow = DataFlow::Global<EnvironmentToFileConfiguration>;
|
|
|
|
from
|
|
Expr getenv, Expr fopen, DataFlow::Node source, DataFlow::Node sink
|
|
where
|
|
source.asIndirectExpr(1) = getenv and
|
|
sink.asIndirectExpr(1) = fopen and
|
|
EnvironmentToFileFlow::flow(source, sink)
|
|
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">isBarrier</span></code> to prevent taint from propagating through them. It also uses <code class="docutils literal notranslate"><span class="pre">isAdditionalFlowStep</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.new.TaintTracking
|
|
|
|
module NetworkToBufferSizeConfiguration implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node node) {
|
|
node.asExpr().(FunctionCall).getTarget().hasGlobalName("ntohl")
|
|
}
|
|
|
|
predicate isSink(DataFlow::Node node) {
|
|
exists(ArrayExpr ae | node.asExpr() = ae.getArrayOffset())
|
|
}
|
|
|
|
predicate isAdditionalFlowStep(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)
|
|
)
|
|
}
|
|
|
|
predicate isBarrier(DataFlow::Node node) {
|
|
exists(GuardCondition gc, Variable v |
|
|
gc.getAChild*() = v.getAnAccess() and
|
|
node.asExpr() = v.getAnAccess() and
|
|
gc.controls(node.asExpr().getBasicBlock(), _) and
|
|
not exists(Loop loop | loop.getControllingExpr() = gc)
|
|
)
|
|
}
|
|
}
|
|
|
|
module NetworkToBufferSizeFlow = TaintTracking::Global<NetworkToBufferSizeConfiguration>;
|
|
|
|
from DataFlow::Node ntohl, DataFlow::Node offset
|
|
where NetworkToBufferSizeFlow::flow(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 cpp
|
|
import semmle.code.cpp.dataflow.new.DataFlow
|
|
|
|
from StringLiteral sl, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
|
|
where
|
|
fc.getTarget().hasName("gethostbyname") and
|
|
source.asIndirectExpr(1) = sl and
|
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
|
DataFlow::localFlow(source, sink)
|
|
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 cpp
|
|
import semmle.code.cpp.dataflow.new.DataFlow
|
|
|
|
module LiteralToGethostbynameConfiguration implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node source) {
|
|
source.asIndirectExpr(1) instanceof StringLiteral
|
|
}
|
|
|
|
predicate isSink(DataFlow::Node sink) {
|
|
exists(FunctionCall fc |
|
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
|
fc.getTarget().hasName("gethostbyname")
|
|
)
|
|
}
|
|
}
|
|
|
|
module LiteralToGethostbynameFlow = DataFlow::Global<LiteralToGethostbynameConfiguration>;
|
|
|
|
from
|
|
StringLiteral sl, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
|
|
where
|
|
source.asIndirectExpr(1) = sl and
|
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
|
LiteralToGethostbynameFlow::flow(source, sink)
|
|
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
|
|
import semmle.code.cpp.dataflow.new.DataFlow
|
|
|
|
class GetenvSource extends DataFlow::Node {
|
|
GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("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 cpp
|
|
import semmle.code.cpp.dataflow.new.DataFlow
|
|
|
|
class GetenvSource extends DataFlow::Node {
|
|
GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") }
|
|
}
|
|
|
|
module GetenvToGethostbynameConfiguration implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
|
|
|
|
predicate isSink(DataFlow::Node sink) {
|
|
exists(FunctionCall fc |
|
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
|
fc.getTarget().hasName("gethostbyname")
|
|
)
|
|
}
|
|
}
|
|
|
|
module GetenvToGethostbynameFlow = DataFlow::Global<GetenvToGethostbynameConfiguration>;
|
|
|
|
from
|
|
Expr getenv, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
|
|
where
|
|
source.asIndirectExpr(1) = getenv and
|
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
|
GetenvToGethostbynameFlow::flow(source, sink)
|
|
select getenv, 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> |