Skip to content

Latest commit

 

History

History
84 lines (49 loc) · 2.41 KB

File metadata and controls

84 lines (49 loc) · 2.41 KB

Exercise: snprintf overflow

CodeQL for C/C++

.. rst-class:: setup

Setup

For this example you need to set up CodeQL for Visual Studio Code and download the CodeQL database for rsyslog from GitHub.

snprintf

.. rst-class:: build

  • printf: Returns number of characters printed.

    printf("Hello %s!", name)
  • sprintf: Returns number of characters written to buf.

    sprintf(buf, "Hello %s!", name)
  • snprintf: Returns number of characters it would have written to buf had n been sufficiently large, not the number of characters actually written.

    snprintf(buf, n, "Hello %s!", name)
  • In pre-C99 versions of glibc snprintf would return -1 if n was too small!

RCE in rsyslog

Finding the RCE yourself

  1. Write a query to find calls to snprintf

    Hint: Use class FunctionCall

  2. Restrict to calls whose result is used

    Hint: Use class ExprInVoidContext

  3. Restrict to calls where the format string contains “%s”

    Hint: Use predicates Expr.getValue and string.regexpMatch

  4. Restrict to calls where the result flows back to the size argument

    Hint: Import library semmle.code.cpp.dataflow.TaintTracking and use predicate TaintTracking::localTaint

Model answer

.. literalinclude:: ../query-examples/cpp/snprintf-1.ql
   :language: ql

.. rst-class:: build

Note

The regular expression for matching the format string uses the “(?s)” directive to ensure that “.” also matches any newline characters embedded in the string.