65.9K
CodeProject is changing. Read more.
Home

Git Bisection Utility Wrapper Script for Memory Corruption Bugs

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0 vote)

Jul 16, 2020

CPOL

2 min read

viewsIcon

3623

downloadIcon

15

A single-script git bisection utility wrapper for memory corruption bugs

Background

Git already has an embedded facility to trace back the root commit that introduced a given bug, namely git bisect, but its usage is seemingly not widespread. Why is it that? I suspect it's because git bisect still resorts to quite a lot of manual efforts, such as deciding whether a given commit is good (bug-free) or bad (bug-affected).

However, come to think of it, does every kind of bug actually need manual efforts to decide the presence of a certain bug? When we trace back the root commit of a certain bug, we simply investigate whether a given PoC input exhibits the same crash at the same program location. This procedure is quite mechanical, so it's not supposed to require human efforts.

On this account, I wrote a short bash script that automates the git bisect operation, given a suspected commit range and a PoC input/command. The script simply decides whether a certain commit is bug-affected by identifying the bug type and the crashing function in the ASAN report, spitting out the first bad commit hash as a result if it exists between the suspected commit range.

Requirements

  • ASAN-enabled compiler
  • (Obviously) git-managed project
  • Known bad/good commit hashes
  • PoC input
  • PoC command

Using the Code

  1. Place a BISECT file in the project directory, formatted as follows:
    <known_bad_commit> <known_good_commit> <poc_input_path> -- <poc_command>
    • <known_bad_commit>: Known bad commit hash (tag name applicable as tags/<name>)
    • <known_good_commit>: Known good commit hash
    • <poc_input_path>: Path to PoC input
    • <poc_command>: PoC command, with `@@` as a placeholder for the PoC input
  2. Place `bisector` in the project directory and execute it:
    $ ./bisector
  3. When finished, find the first bad commit in the FIRSTBAD file. See {good,bad}.bis for the ASAN dumps from the last good and first bad commit, respectively.

Example: CVE-2016-3658

  1. Prepare libtiff itself and the PoC input.
    $ git clone https://gitlab.com/libtiff/libtiff.git libtiff
    $ cd libtiff
    $ curl http://bugzilla.maptools.org/attachment.cgi?id=601 > POC

    The PoC input is provided by http://bugzilla.maptools.org/show_bug.cgi?id=2500.

  2. Place a BISECT file.
    d7db70c9 tags/Release-v4-0-0 POC -- ./tools/tiffset @@

    d7db70c9 is the last commit before 07/01/2015, and we expect CVE-2016-3658 has been created after 4.0.0.

  3. Place the bisector script and run it.
    $ ./bisector
    [*] Initializing...
     +  Commit range: 'd7db70c9'(bad) to 'f7b79dc7'(good)
     +  PoC input: POC
     +  PoC command: ./tools/tiffset @@
    [*] Generating most recent ASAN dump...
    [*] Testing commit 'd7db70c9'...
     +  Bug type: heap-buffer-overflow
     +  Crash function: TIFFWriteDirectoryTagSampleformatArray
    [*] Verifying good commit...
    [*] Testing commit 'f7b79dc7'... Good
    [*] Bisecting...
    [*] Testing commit 'd1be5cb7'... (234 remaining) Bad
    [*] Testing commit '871d1067'... (117 remaining) Bad
    [*] Testing commit '1358a916'... (58 remaining) Bad
    [*] Testing commit 'f502a159'... (29 remaining) Good
    [*] Testing commit '920688aa'... (15 remaining) Bad
    [*] Testing commit 'e54e9545'... (7 remaining) Good
    [*] Testing commit 'c0733844'... (4 remaining) Bad
    [*] Testing commit 'af47ad26'... (2 remaining) Good
    [*] Verifying...
    [*] Testing commit 'c0733844'... Bad
    [*] Testing commit 'af47ad26'... Good
     +  First bad commit: c0733844461ceb1b05f41968c1d962480f0db5f6 (see FIRSTBAD)
     +  {Last-good, First-bad} ASAN log: {good, bad}.bis
     +  All done!
  4. Check FIRSTBAD to see the first bad commit.
    c0733844461ceb1b05f41968c1d962480f0db5f6

Disclaimer

  • Currently supports configure only
  • Supported bug types include:
    • ASAN-detectable memory corruptions
    • Divide-by-zero (SIGFPE)
    • Null dereference (SIGSEGV)
    • Assertion failure
  • This script tests a bug by identifying the bug type and the crashing function in the ASAN dump; it does not recognize whether the bug manifests in another commit with a different bug type or at a different function.
  • Random contributions would be very much appreciated.

History

  • 16th July, 2020: Initial post