secure coding in c/c++
TRANSCRIPT
McAfee Confidential—Internal Use Only
Secure Coding in C/C++
A technical perspective
September 25, 2013
Dan-Claudiu Dragoș
Software Development Engineer
What will we cover today:
• Software vulnerabilities: who and why?
• String and buffer overflows
• Pointer vulnerabilities
• Dynamic memory management
• Format strings (printf)
• Integer values
• Concurrency
• File I/O
McAfee Confidential—Internal Use Only
Software vulnerabilities: who and why?
3
• Script kiddies or illiterate cybercriminals do not find vulnerabilities:
• … they simply use them for profit or fame
• Vulnerabilities are found by security experts
• They may be working for McAfee or for the government of Elbonia
• … this is not a non profit activity!
• These experts can set up environments similar to yours
• They have a deep understanding of the system architecture
• They have access to the same tools as you do
» … including debuggers!
» … or even to the source code!
• They practice the attacks in controlled environments before going live.
McAfee Confidential—Internal Use Only
Software vulnerabilities: what to do?
4
• There is no magic recipe!
• The approach should be proactive, not reactive
» … it’s like pipe work when fixing leaks
• There are some good development practices
» … do’s and don’ts
• There is also some external help:
• Modern compilers may reorder parameters on stack or apply
optimizations
• Modern operating systems may use memory randomization
• Modern CPUs have “execute disable” flags
McAfee Confidential—Internal Use Only
Software vulnerabilities: Buffers
5
• Unbounded buffer operations are the recipe for disaster
– Never use:
• API functions that populate buffers without taking sizes
• C-String operations without allowing for buffer size!
• Array iterations without checking for bounds
• Unsafe functions marked as such in the documentation
– Do not rely on your own canary values, let the compiler do its job!
– During development:
• Build the source code with a debug library with strict bounds checking
• Use static analysis software (Coverity)
• Run the software through a dynamic analyser (Purify)
McAfee Confidential—Internal Use Only
Software vulnerabilities: Buffers
6
• Design patterns to keep in mind:
• Allocating memory for the use of (external) API functions is unsafe!
» On Linux the ELF dynamic linking table can be exploited
» Windows approach on using DLLs is safe
GNU libc (unsafe) GNU libc (safer) C++ STL (safest)
Caller allocates Calee allocates Callee allocates
Callee initializes
Caller uses
Caller frees Caller frees Callee frees
McAfee Confidential—Internal Use Only
Software vulnerabilities: Pointers
7
• Function pointers are dangerous!
– An attacker may modify the memory and use such pointer as a trampoline
to their own shell code
• C++ polymorphic approach is much safer
• Always initialize and set the pointers to NULL after use
– NULL pointers may point to valid memory on some architectures
• Linux platforms: running the program through valgrind may help
identify potential issues
– the attacker may very likely do this in search of vulnerabilities!
McAfee Confidential—Internal Use Only
Software vulnerabilities: Memory
8
• Never use buffer sizes based only on user input
» …argv[] elements can be empty strings!
» …including argv[0]
• Do not use malloc(0), the behaviour is undefined
• Always check the result of memory allocation (and handle the error)
• Always use the proper call pairs:
• new – delete
• malloc – free
• new[] – delete[]
• placement new – explicit destructor call
McAfee Confidential—Internal Use Only
Software vulnerabilities: Format strings
9
• Variadic functions such as printf are dangerous
• the C standard does not provide a reliable way to determine the call
argument count
• these functions must rely on the caller to provide the proper format, the
right number of arguments and the proper argument types
• If the format string contains unparsed user input, this is an exploit
invitation:
» the attacker can trigger reading arbitrary data from the stack
» the %n format specifier causes data to be written!
» specially crafted format strings can cause data to be written to
arbitrary memory locations!
• Localization code is a prime target for these attacks
McAfee Confidential—Internal Use Only
Software vulnerabilities: Integers
10
xkcd clipart released under Creative Commons license
McAfee Confidential—Internal Use Only
Software vulnerabilities: Integers
11
• C language defines multiple integer types and default conversions
• Integer values are prone to overflow
• Don’t:
• design your code with a certain architecture in mind
• forget that the safe storage of the multiplication result requires twice
the size of the largest argument
• mix signed and unsigned types
• forget about LSB/MSB or the negative numbers
• Do:
• check for bounds on any integer value received from the user
• test the code thoroughly on all relevant architectures
McAfee Confidential—Internal Use Only
Software vulnerabilities: Concurrency
12
• The concurrency issues do not usually result in privilege escalation
» …they are mostly used for denial of service
• An attacker may only want to get your system to an undefined state
» …but this is also a job for the QA!
• Always be on the look for:
• scalability issues
• race conditions
• deadlocks
• starvation and live locks
McAfee Confidential—Internal Use Only
Software vulnerabilities: File I/O
13
• Referring files by names is unsafe by design
• on Linux the race window between stat() and open() cannot be
(cleanly) avoided
• an attacker may replace the file in this race window
• The prime target for these attacks are the setuid() programs
• Mitigation strategies:
• use canonical names / paths, do not trust the user input
• perform all the operations with the lowest required privileges / drop
super user privileges when they are no longer required
• check that the file operation is not performed on a symlinked file
• the admin must ensure that no hard links are possible between user
files and system files
McAfee Confidential—Internal Use Only
Software vulnerabilities:
14
• Questions?