KEMBAR78
CNIT 127: Ch 18: Source Code Auditing | PDF
CNIT 127: Exploit Development



Ch 18: Source Code Auditing
Updated 4-10-17
Why Audit Source Code?
• Best way to discover vulnerabilities
• Can be done with just source code and
grep
• Specialized tools make it much easier
Cscope
• A source code browsing tool
• Useful for large code trees,
such as the whole Linux
kernel
• Many useful search
functions
• Cbrowser: GUI front-end
• Links Ch 18a, 18b
Ctags
• Indexes source code
• Creates a tag file with
locations for language
tags in files scanned
• Works in many
languages, including C
and C++
– Link Ch 18c
Text Editor
• Vim and Emacs have features that make
writing and searching though large
amounts of code easy
• Bracket-matching: find matching ([{
Automated Source Code
Analysis Tools
Splint
• Badly out-of date (last revised in 2007)
• Output a little hard to understand
– Links Ch 18d, 18e
• Many available, specialized by language
• Link Ch 18f
• Easy to use
• Finds about half the obvious
vulnerabilities we've exploited
Heap Overflow
Finds Some Vulnerabilities
• But not the overflow!
Format String Vulnerability
• It doesn't find
it at all!
Flawfinder
• Much better
• In Kali
• apt-get update
• apt-get install flawfinder
Methodology
Top-Down (Specific) Approach
• Search for specific lines of vulnerable
code, such as format string errors
• Auditor doesn't have to understand
application in depth
• Misses vulnerabilities that span more than
one part of the code
Bottom-Up Approach
• Auditor reads large portion of code
• Starting at main()
• Time-consuming but can reveal subtle
bugs
Selective Approach
• Most auditors use this approach
• Locate code that can be reached with
attacker-defined input
• Focus energy on that code
• Learn the purpose of that code thoroughly
Vulnerability Classes
Generic Logic Errors
• Requires good understanding of an
application
– And internal structures and classes
• Example: wildcard certificates
– Pascal-based CA will sell a certificate for *
0.evil.com
– C-based browser will see it as *, a wildcard
• Link Ch 18g
(Almost) Extinct Bug Classes
• Unbounded memory copy functions
– strcpy(), sprintf(), strcat(), gets(), …
• Hunted nearly to extinction
Root Cause (from Microsoft)
Bypassing ASLR & DEP
Format Strings
• Easy to find with a code audit
– Although cppcheck failed
• Often found in logging code
• Vulnerable only if attacker controls the
format string
Generic Incorrect Bounds-Checking
• Coder attempts to check limits, but does
it incorrectly
• Example: Snort RCP Processor (2003)
– Processes a series of RPC fragments
– Checks each fragment to make sure it's not
larger than the buffer
– But it should check the total size of all
combined fragments
Snort RCP Processor (2003)
Loop Constructs
• Coders often use intricate loops, and loops
within loops
• Complex interactions can lead to insecurities
• Led to a buffer overflow in Sendmail
• Link Ch 18h
Demonstration Exploit
• Link Ch 18i
Off-by-One Vulnerabilities
• Often caused by improper null-
termination of strings
• Frequently found in loops or introduced
by common string functions
• Can lead to arbitrary code execution
Example from Apache
• When both if statements are true
– Space allocated is one byte too small
– memcpy will write one null out of bounds
OpenBSD ftp Daemon
• If last character is a quote, it can be
written past the bounds of the input
buffer
strncat()
• Strncat always null-terminates its output
string
• Will write a null byte out of bounds unless
the third argument is equal to the
remaining space in the buffer minus one
byte
Non-Null Termination Issues
• If a string is not terminated with a null
– Memory after the string is interpreted as part
of the string
– May increase length of string
– String writes may corrupt memory outside the
string buffer
– Can lead to arbitrary code execution
strncpy()
• If there's not enough space in the
destination buffer
– strncpy() won't null-terminate the string it
writes
strncpy() Example
– First strncpy won't null-terminate not_term_buf
– Second strcpy is unsafe, even though both
buffers are the same size
– Fix it by adding this line of code after the first
strcpy
Skipping Past Null-Termination
• String-processing loops that process more
than one character at a time
– Or where assumptions about string length are
made
• Can make it possible to write past end of
a buffer
– Possible arbitrary code execution
Example from Apache
• This line is intended to skip past :// in a
URL
– cp += 3
But Not All Schemes End in ://
• If the URI is ldap:a
– The null byte is skipped
Signed Comparison Vulnerabilities
• Coder attempts to check input length
• But uses a signed integer variable
• Or two different integer types or sizes
– C sometimes converts them both to signed
integers before comparing them
• Following example from Apache
– Led to code execution on Windows and BSD
Unix
Example from Apache
• bufsize is a signed integer
– Remaining space in the buffer
• r->remaining is signed
– Chunk size from the request
• len_to_read should be the smaller of the two
– Negative chunk size tricks the code into performing a
large memcpy later, because it's cast to
unsigned
Integer Conversions
• Link Ch 18l
• A hashed password can begin with 0e and
contain only digits (very rare)
– Like 0e12353589661821035685
• PHP reads that as scientific notation
– 0^123…
– Always zero (link Ch 18j)
Double Free Vulnerabilities
• Freeing the same memory chunk twice
• Can lead to memory corruption and arbitrary
code execution
• Most common when heap buffers are stored
in pointers with global scope
• Good practice: when a global pointer is
freed, set it to Null to prevent it being re-
used
• Prevents dangling pointers
Out-of-Scope Memory Usage
Vulnerabilities
• Use of a memory region
before or after it is valid
• Also called "Dangling
Pointer"
– Image from Wikipedia
• Link Ch 18k)
Uninitialized Variable Usage
• Static memory in the .data or .bss
sections of an executable are initialized
to null on program startup
• But memory on the stack or heap is not
• Uninitializes variables will contain data
from previous function calls
• Argument data, saved registers, or local
variables from previous function calls
Uninitialized Variable Usage
• Rare, because they can lead to immediate
program crashes
• So they get fixed
• Look for them in code that is rarely used
• Such as handlers for uncommon errors
• Compilers attempt to prevent these errors
Example
• If data is null
– test is never assigned any value
– But test is still freed
Exploitation
• The "uninitialized" data in test is not
random
• It comes from previous variables and
function calls
• It may be controlled by the attacker
• So the free() leads to a controllable
memory write
– Arbitrary code execution
Use After Free Vulnerabilities
• Heap buffers are temporary
– Released with free()
• But a program may use a pointer after
free()
– If more than one variable points to the same
object
• Allows an attacker to write to RAM
– Possible arbitrary code execution
Multithreaded Issues and 

Re-Entrant Safe Code
• A global variable is used by more than one
thread, without proper locking
– A variable might be changed unexpectedly by
another thread
• Such issues won't appear until the server
is under heavy load
– May remain as intermittent software bugs
that are never verified

CNIT 127: Ch 18: Source Code Auditing

  • 1.
    CNIT 127: ExploitDevelopment
 
 Ch 18: Source Code Auditing Updated 4-10-17
  • 2.
    Why Audit SourceCode? • Best way to discover vulnerabilities • Can be done with just source code and grep • Specialized tools make it much easier
  • 3.
    Cscope • A sourcecode browsing tool • Useful for large code trees, such as the whole Linux kernel • Many useful search functions • Cbrowser: GUI front-end • Links Ch 18a, 18b
  • 4.
    Ctags • Indexes sourcecode • Creates a tag file with locations for language tags in files scanned • Works in many languages, including C and C++ – Link Ch 18c
  • 5.
    Text Editor • Vimand Emacs have features that make writing and searching though large amounts of code easy • Bracket-matching: find matching ([{
  • 6.
  • 7.
    Splint • Badly out-ofdate (last revised in 2007) • Output a little hard to understand – Links Ch 18d, 18e
  • 8.
    • Many available,specialized by language • Link Ch 18f
  • 9.
    • Easy touse • Finds about half the obvious vulnerabilities we've exploited
  • 10.
  • 11.
    Finds Some Vulnerabilities •But not the overflow!
  • 12.
    Format String Vulnerability •It doesn't find it at all!
  • 13.
    Flawfinder • Much better •In Kali • apt-get update • apt-get install flawfinder
  • 14.
  • 15.
    Top-Down (Specific) Approach •Search for specific lines of vulnerable code, such as format string errors • Auditor doesn't have to understand application in depth • Misses vulnerabilities that span more than one part of the code
  • 16.
    Bottom-Up Approach • Auditorreads large portion of code • Starting at main() • Time-consuming but can reveal subtle bugs
  • 17.
    Selective Approach • Mostauditors use this approach • Locate code that can be reached with attacker-defined input • Focus energy on that code • Learn the purpose of that code thoroughly
  • 18.
  • 19.
    Generic Logic Errors •Requires good understanding of an application – And internal structures and classes • Example: wildcard certificates – Pascal-based CA will sell a certificate for * 0.evil.com – C-based browser will see it as *, a wildcard • Link Ch 18g
  • 20.
    (Almost) Extinct BugClasses • Unbounded memory copy functions – strcpy(), sprintf(), strcat(), gets(), … • Hunted nearly to extinction
  • 21.
    Root Cause (fromMicrosoft)
  • 22.
  • 23.
    Format Strings • Easyto find with a code audit – Although cppcheck failed • Often found in logging code • Vulnerable only if attacker controls the format string
  • 24.
    Generic Incorrect Bounds-Checking •Coder attempts to check limits, but does it incorrectly • Example: Snort RCP Processor (2003) – Processes a series of RPC fragments – Checks each fragment to make sure it's not larger than the buffer – But it should check the total size of all combined fragments
  • 25.
  • 26.
    Loop Constructs • Codersoften use intricate loops, and loops within loops • Complex interactions can lead to insecurities • Led to a buffer overflow in Sendmail • Link Ch 18h
  • 27.
  • 28.
    Off-by-One Vulnerabilities • Oftencaused by improper null- termination of strings • Frequently found in loops or introduced by common string functions • Can lead to arbitrary code execution
  • 29.
    Example from Apache •When both if statements are true – Space allocated is one byte too small – memcpy will write one null out of bounds
  • 30.
    OpenBSD ftp Daemon •If last character is a quote, it can be written past the bounds of the input buffer
  • 31.
    strncat() • Strncat alwaysnull-terminates its output string • Will write a null byte out of bounds unless the third argument is equal to the remaining space in the buffer minus one byte
  • 32.
    Non-Null Termination Issues •If a string is not terminated with a null – Memory after the string is interpreted as part of the string – May increase length of string – String writes may corrupt memory outside the string buffer – Can lead to arbitrary code execution
  • 33.
    strncpy() • If there'snot enough space in the destination buffer – strncpy() won't null-terminate the string it writes
  • 34.
    strncpy() Example – Firststrncpy won't null-terminate not_term_buf – Second strcpy is unsafe, even though both buffers are the same size – Fix it by adding this line of code after the first strcpy
  • 35.
    Skipping Past Null-Termination •String-processing loops that process more than one character at a time – Or where assumptions about string length are made • Can make it possible to write past end of a buffer – Possible arbitrary code execution
  • 36.
    Example from Apache •This line is intended to skip past :// in a URL – cp += 3
  • 37.
    But Not AllSchemes End in :// • If the URI is ldap:a – The null byte is skipped
  • 38.
    Signed Comparison Vulnerabilities •Coder attempts to check input length • But uses a signed integer variable • Or two different integer types or sizes – C sometimes converts them both to signed integers before comparing them • Following example from Apache – Led to code execution on Windows and BSD Unix
  • 39.
    Example from Apache •bufsize is a signed integer – Remaining space in the buffer • r->remaining is signed – Chunk size from the request • len_to_read should be the smaller of the two – Negative chunk size tricks the code into performing a large memcpy later, because it's cast to unsigned
  • 40.
  • 41.
  • 42.
    • A hashedpassword can begin with 0e and contain only digits (very rare) – Like 0e12353589661821035685 • PHP reads that as scientific notation – 0^123… – Always zero (link Ch 18j)
  • 43.
    Double Free Vulnerabilities •Freeing the same memory chunk twice • Can lead to memory corruption and arbitrary code execution • Most common when heap buffers are stored in pointers with global scope • Good practice: when a global pointer is freed, set it to Null to prevent it being re- used • Prevents dangling pointers
  • 44.
    Out-of-Scope Memory Usage Vulnerabilities •Use of a memory region before or after it is valid • Also called "Dangling Pointer" – Image from Wikipedia • Link Ch 18k)
  • 45.
    Uninitialized Variable Usage •Static memory in the .data or .bss sections of an executable are initialized to null on program startup • But memory on the stack or heap is not • Uninitializes variables will contain data from previous function calls • Argument data, saved registers, or local variables from previous function calls
  • 46.
    Uninitialized Variable Usage •Rare, because they can lead to immediate program crashes • So they get fixed • Look for them in code that is rarely used • Such as handlers for uncommon errors • Compilers attempt to prevent these errors
  • 47.
    Example • If datais null – test is never assigned any value – But test is still freed
  • 48.
    Exploitation • The "uninitialized"data in test is not random • It comes from previous variables and function calls • It may be controlled by the attacker • So the free() leads to a controllable memory write – Arbitrary code execution
  • 49.
    Use After FreeVulnerabilities • Heap buffers are temporary – Released with free() • But a program may use a pointer after free() – If more than one variable points to the same object • Allows an attacker to write to RAM – Possible arbitrary code execution
  • 50.
    Multithreaded Issues and
 Re-Entrant Safe Code • A global variable is used by more than one thread, without proper locking – A variable might be changed unexpectedly by another thread • Such issues won't appear until the server is under heavy load – May remain as intermittent software bugs that are never verified