Source Code Audit Training

Day 1

Jörn Schneeweisz

© 2018

Your Trainer(s)

  • Jörn Schneeweisz
    • a.k.a. joernchen
    • Security consultant at Recurity Labs since 2007
    • Ruby on Rails “fetish”
    • Strong preference towards White-Box testing
  • Stefan Seefeldt
    • Security consultant at Recurity Labs for ~ half a year
    • M.S. in Computer Science
    • Master’s thesis on advanced exploitation techniques
    • Unfortunately isn’t here for this training

Before we start

  • Introduction Round! =)
  • Build Teams (2-3 persons)
  • You can ask questions any time 👋

Motivation

From the Training description:

The more you are able to see, the more bugs may appear under the hood.

Reading (and understanding) source code is a time-consuming task. The effort is rewarded in multiple ways.

Motivation

But I don’t know how to code in $LANGUAGE!

Me neither ;-).

Overview - Day 1

  • The Basics
    • Toolchain & set-up
    • Vulnerable patterns and idioms
    • Language independent issues
    • Language/Framework specific hints

Toolchain

Toolchain

Not much is needed to read code, less source.php will do the job. But there are quite some things which help a lot to understand much quicker what’s going on.

Pretty simple, right!

int
main(int argc, char *argv[])
{
                        /* Important!!    *
  if (argc > 1)          * Please note:   *
    for (;;)             * This code is   *
      puts(argv[1]);     * NOT optimized  *
  else                   * in any way.    */
    for (;;)
      puts("y");
}

Wait a minute!

Syntax Highlighting

A very simple, yet quite effective measure to understand code faster.

Editor/IDE

I won’t start a war here.
I won’t start a war here.

grep et al.

Being able to search within a codebase is essential for an audit.

Besides grep there are more specialized tools:

Just to name a few.

grep et al.

Even tough simple text base search might suffice in a lot of cases some IDE-like features are really nice to have:

  • Cross referencing
  • Control Flow Graphs
  • Highlighting features

SCM tools

Static analyzers

There are a lot of static code analyzers out there. They might help a lot to get to some bugs faster. They won’t be covered here for obvious reasons.

Patterns and Idioms

Intro

  • Read it, over and over again.

  • Ask your peers if unsure
  • Think aloud (use with care)
  • Üben, üben, üben! (Practice, practice, practice!)

Intro

Common Pitfalls:

  • Validations
  • Logic
  • Assumptions about the environment
  • Assumptions about the interfaces
  • Assumptions about called library methods

Intro

Your job is to think about things the developer didn’t have time to think about.

Code Comments

Being able to read the code comments is actually a huge benefit. Even if you’re able to perfectly decompile e.g. a .jar file you won’t get the comments from the original source code.

Code Quality

Starter

Have a look here:

src/first/StringStuff.java

Starter

What’s wrong with this code?

Starter

Let’s dissect

Starter

Note the new StringBuffer()

Starter

Starter - “Exploit”

is just fine.

An empty file will result in an endless loop:

Injections

Quite a lot of issue are based on some kind of injection. So for instance:

  • XSS
  • SQL Injections
  • Directory Traversals
  • Command Injections
  • … you name it

Injections

Injections can be seen as a form of in-band signaling. An attacker is able to alter some semantics within the underlying operation. This is possible, as some attacker controlled input is injected in a way which allows those semantical changes.

A very basic example:

Remote root any1?

Just have a look here

GitHub, the gift that keeps on giving.
GitHub, the gift that keeps on giving.

Injections

The general injection pattern:

Some user controlled variable is ending up (being injected) in an operation which subsequently will do something beyond its intended purpose.

Most prominent and easy to spot root cause is string concatenation.

Simple SQL Injection

<?php
$id = $_GET['p_id'];
$query  = "SELECT name FROM products WHERE id=" . $id . ";" ;
$result = pg_query($conn, $query);
?>

Go

Java (JDBC)

C#

PHP

Python

Ruby

Guess how it looks :)

Rails ORM specific hints

What is injected here?

Arguments!

-O [<pager>], –open-files-in-pager [<pager>] Open the matching files in the pager (not the output of grep). If the pager happens to be “less” or “vi”, and the user specified only one pattern, the first file is positioned at the first match automatically.

Argument Injection Example

Argument Injection Example

PHP’s mail()

Argument Injection Example

When PHP is configured to invoke a local MTA $additional_parameters will be sanitized by escapeshellcmd().

➡️ Arguments to the MTA can be still injected.

Further reading

Hands on Injections

Recap / Generalization

Let’s think about the Injections from a high-level perspective.

Recap / Generalization

  • IPO - a rather universal engineering pattern:
    • Input ➡️ Processing ➡️ Output

User input

  • Have a look at this .go file
    • Any thoughts about the code?
  • The example is shamelessly stolen from here

ZIP / Archive Files

  • Lesser known fact about ZIP (also other archive formats) files:
    • The filename entry is just a string
    • It can contain the $PATH_SEPARATOR (‘/’ on Unix, ‘\’ on Windows)
    • Tool: e.g. evilarc

ZIP / Archive Files

Turns out, this got quite some hype

ZIP / Archive Files

  • Another fun thing to put into a .zip:
    • A symbolic link

User Input

source

Logic issues

Even simple boolean logic is hard, trust me 😂!

“Leftovers”

Gitrob

There’s stuff to be found in code repositories which isn’t code, but still that stuff might introduce security issues.

Language / Framework specific hints

Generally speaking

Every language has some specific pitfalls/ways to shoot yourself in the foot.

PHP: Type Juggling

Example taken from here

Further reading: Greg’s Presentation

PHP: Type Juggling

uniqid() :Gets a prefixed unique identifier based on the current time in microseconds.

+ operator is for Numbers:

php > echo("admin" + "1337wtf");
1337

PHP: Type Juggling

RTFM here and here

Ruby

Ruby

The usual RegEx Anchors ^ and $ are multiline by default.

Which means:

/^[a-zA-Z]$/ matches perfectly on the following input:

hallo
!@#$WTF**

Indirections (Ruby example)

send(string [, args…]) → obj

method_missing(symbol [, *args] ) → result

More on that later during this training.

Indirections (Java example)

Reflect.java a very basic example:

Timing Attacks

“Remote Timing Attacks are Practical” - are they?

Timing Attacks

  • Especially when validating MACs, passwords, or other strings which implement some kind of access protection timing attacks might be an issue

Timing Attacks

Basic pattern/assumption:

  • Canonical string comparison (e.g. ==, .equals(),…) is not time constant
    • “AAAAAAB” == “AAAAAAA” is slower than “ABAAAAA” == “AAAAAAA”

Timing Attacks mitigation

  • Constant time comparison is usually implemented like:

Day 1 - Recap

Day 1 - Recap

What’s your main take away for today?
What’s your main take away for today?