Secure Programming with Static Analysis
Brian Chess, Ph.D. Chief Scientist Fortify Software [email protected]
May 24, 2007
Software Systems that are Ubiquitous Connected Dependable
Complexity
Unforeseen Consequences
You Are Here
1.
The line between secure/insecure is often subtle.
Many seemingly non-security decisions affect security.
2. 3.
Little errors can hurt a lot. Smart people make dumb mistakes.
As a group, programmers tend to make the same security mistakes over and over.
4.
We need non-experts to get security right.
Success is foreseeing failure.
Henry Petroski
Problems
Buffer Overflow MSDN sample code for function DirSpec:
int main(int argc, char *argv[]) { ... char DirSpec[MAX_PATH + 1]; printf ("Target dir is %s.\n", argv[1]); strncpy (DirSpec, argv[1], strlen(argv[1])+1);
Cross-Site Scripting <c:if test="${param.sayHello} "> Hello ${param.name}! </c:if>
We never intended the code that's in there to actually be production-ready code Ryan Asleson
Cross-site Scripting
Vulnerable Site
Malicious Site
Firewall
Victim Browser
Cross-Site Scripting
Cross-site scripting looks more and more like buffer overflow Buffer Overflow
Allows Arbitrary Code Execution Exploit is hard to write Easy mistake to make in C/C++ Well known problem for decades
Cross-site Scripting
Allows Arbitrary Code Execution Exploit is easy to write Easy mistake to make Well known problem for a decade
Answers
Competitors
Network-devices
Security in a Box
Focusing on the attack over the root cause, Now fixes applications is now the latest craze. Focused on protecting the infrastructure not the software. Some solutions serve as a stop gap, but by no means replace the need to build security in.
Penetration Testing An extra scoop of quality
Badness-ometers
A popular method for establishing awareness offered up as a sustainable solution. Great for demonstrating the problem. Testing without upstream activities to test is pointless and expensive.
Security Light
Simply trying harder does not result in good security. To broaden reach of niche products, static analysis vendors add security to a list of quality issues. Security issues are not just another bug.
Security in the Development Lifecycle
Security in the Development Lifecycle
Plan
Build
Test
Field
Firewalls Intrusion Detection Penetration testing
Security in the Development Lifecycle
Plan
Build
Test
Field
Architectural Risk Assessment Code Review Security Testing
Effective security from non-experts
Not Everyone Gets It
"Since most security for Web applications can be implemented by a system administrator, application developers need not pay attention to the details of securing the application"
BEA WebLogic Documentation
Opportunity
Todays Motivators
1) protect the business from bad guys
2) limit liability, comply with legislation
3) avoid damage to brand and reputation
The Fortify Bet: Tools Across the SDLC
Manage and Measure Fix Security Issues Early in Development
Security Ops Team
Developers Management
Monitor and Protect Deployed Applications
Security Testers
Build Server
Verify and Test Working Applications
Identify, Prioritize and Fix Issues Across Entire Code Base
Security Leads / Auditors
chainsaw
Static Analysis
Static Analysis Is Good For Security
Fast compared to manual review Fast compared to testing Consistent Brings security knowledge with it Makes security review process easier for non-experts
Prehistoric static analysis tools
RATS
Flawfinder ITS4
Prehistoric static analysis tools
(+) Good Help security experts audit code A place to collect knowledge about bad coding practices (-) Bad NOT BUG FINDERS Not helpful without security expertise
RATS
Flawfinder
ITS4
Advanced Static Analysis Tools: Prioritization
int main(int argc, char* argv[]) { char buf1[1024]; char buf2[1024]; char* shortString = "a short string"; strcpy(buf1, shortString); /* eh. */ strcpy(buf2, argv[0]); /* !!! */ ...
No Silver Bullet
Static Analysis Limitations Does not understand architecture Does not understand application semantics Does not understand social context
The Many Faces of Static Analysis
Type checking Style checking Program understanding Program verification / Property checking Bug finding Security review
Type Checking
Taken for granted Imperfect:
short s = 0; int i = s; /* the type checker allows this */ short r = i; /* false positive: this will cause a type checking error at compile time.*/ /* false negative: passes type checking, fails at runtime */ Object[] objs = new String[1]; objs[0] = new Object();
Style Checking
Pickier than type checker, might look at
Whitespace Naming Deprecated functions gcc -Wall does some style checking
typedef enum { red, green, blue } Color; char* getColorString(Color c) { char* ret = NULL; switch (c) { case red: printf("red"); } return ret; }
Tools
Lint, PMD
Program Understanding
Help make sense of a large codebase Tools:
Fujaba Klockwork CAST Systems
Program Verification / Property Checking
*Prove* that a program has particular properties Partial specification -> property checking Often focuses on temporal safety properties Example: allocated memory must always be freed
inBuf = (char*) malloc(bufSz); if (inBuf == NULL) return -1; outBuf = (char*) malloc(bufSz); if (outBuf == NULL) return -1; /* memory leak */
Soundness Aspires to Sound WRT the specification: reports a bug if one exists Tools: Praxis, PolySpace, GrammaTech
Bug Finding
More sophisticated than a style checker Less ambitious than program verification Search code for bug idioms Find high-confidence, low noise results (low false positives) Soundness Example: double checked locking
if (fitz == null) { synchronized (this) { if (fitz == null) { fitz = new Fitzer(); } } }
Aspires to Sound WRT counterexample: never reports a bug that isnt a bug
Tools:
FindBugs, Coverity, Klocwork, Prefast
Security Review
Focus on finding exploitable code Find high-risk code constructs for review (low false negatives) Hint: summarize, dont simulate Tools Ancient: RATS, ITS4, FlawFinder New: Fortify Software and Ounce Labs
Scope vs. Performance
Analysis Techniques: Taint Propagation
Trace potentially tainted data through the program Report locations where an attacker could take advantage of a vulnerable function or construct
buff = getInputFromNetwork(); copyBuffer( newBuff , buff ); exec( newBuff );
(command injection)
Real-world cases usually cross method boundaries
A Peek Inside a Static Analysis Tool
Analyzer
src
Front End
System Model
Analyzer
Results Viewer
Analyzer
Modeling Rules
Security Properties
Parsing
Language support
One language/compiler is straightforward Lots of combinations is harder
Could analyze compiled code
Everybody has the binary No need to guess how the compiler works No need for rules
but
Decompilation can be difficult Loss of context hurts. A lot. Remediation requires mapping back to source anyway
Analysis / Rules: Structural
Identify bugs in the program's structure Example: calls to gets() Structural rule: FunctionCall: function is [name == "gets"]
Analysis / Rules: Structural
Identify bugs in the program's structure Example: memory leaks caused by realloc() buf = realloc(buf, 256); Structural rule: FunctionCall c1: ( c1.function is [name == "realloc"] and c1 in [AssignmentStatement: rhs is c1 and lhs == c1.arguments[0] ] )
Analysis / Rules: Dataflow Source Rule
Following interesting values through the program Example: Command injection vulnerability buff = getInputFromNetwork(); copyBuffer( newBuff, exec( newBuff ); Source rule: Function: getInputFromNetwork() Postcondition: return value is tainted buff );
Analysis / Rules: Dataflow Pass-Through Rule
Following interesting values through the program Example: Command injection vulnerability buff = getInputFromNetwork(); copyBuffer( newBuff, exec( newBuff ); Pass-through rule: Function: copyBuffer() Postcondition: if the second argument is tainted, then the first argument becomes tainted buff );
Analysis / Rules: Dataflow Sink Rule
Following interesting values through the program Example: Command injection vulnerability buff = getInputFromNetwork(); copyBuffer( newBuff, exec( newBuff ); Sink rule: Function: exec() Precondition: the first argument must not be tainted buff );
Analysis / Rules: Control Flow
Look for dangerous sequences Example: Double-free vulnerability
while ((node = *ref) != NULL) { *ref = node->next; free(node); if (!unchain(ref)) { break; } } if (node != 0) { free(node); return UNCHAIN_FAIL; }
start initial state
free(x)
(other operations)
freed
(other operations) free(x)
error
Analysis / Rules: Control Flow
Look for dangerous sequences Example: Double-free vulnerability
while ((node = *ref) != NULL) { *ref = node->next; free(node); if (!unchain(ref)) { break; } } if (node != 0) { free(node); return UNCHAIN_FAIL; }
start initial state
free(x)
(other operations)
freed
(other operations) free(x)
error
Analysis / Rules: Control Flow
Look for dangerous sequences Example: Double-free vulnerability
while ((node = *ref) != NULL) { *ref = node->next; free(node); if (!unchain(ref)) { break; } } if (node != 0) { free(node); return UNCHAIN_FAIL; }
start initial state
free(x)
(other operations)
freed
(other operations) free(x)
error
Interface
Must convince programmer that theres a bug in the code Different interfaces for different scenarios: Security auditor parachutes in to 2M line program Programmer reviews own code Programmers share code review responsibilities Interface is just as important as analysis Dont show same bad result twice
Common Problems
False positives Incomplete/inaccurate model Conservative analysis False negatives Incomplete/inaccurate model Missing rules Forgiving analysis
Untapped Potential
Customization Unique to your application or organization Design for testability Write code knowing that it will be checked
Adopting a Static Analysis Tool
1) Some culture change required
More than just another tool Often carries the banner for software security program Pitfall: the tool doesnt solve the problem by itself
2) Define the playing field
Choose specific objectives Build a gate
3) Do training up front
Software security training more important than tool training Tool training is helpful too
Adopting a Static Analysis Tool
4) Start small
Do a pilot rollout to a friendly dev group Build on your success
5) Go for the throat
Tools detect lots of kinds of issues. Turn most of it off. Focus on easy-to-understand, highly relevant problems.
6) Appoint a champion
Make sure there is a point person on the dev team Choose a developer who knows a little about everything
Adopting a Static Analysis Tool
7) Measure the outcome
Keep track of tool findings. Keep track of outcome (issues fixed).
8) Make it your own
Investigate customization Map tool against internal security standards. Best case scenario: The tools reinforce company coding guidelines Company coding guidelines are written with automated checking in mind
9) The first time around is the worst
Budget 2x typical cycle cost. Typical numbers: 10% of time for security, 20% for the first time
Conventions
Design
Algorithms
Data Structures
Protocols
<Your Code>
Libraries
Language
Platform
Conventions
Design
Algorithms
Data Structures
Protocols
<Your Code>
Libraries
Language
Platform
The Buck Stops With Your Code
Security problems everywhere you look
Languages, libraries, frameworks, platforms, etc
Right answer
Better languages, libraries, frameworks, platforms, etc
Realistic answer
Build secure programs out of insecure pieces
Conventions Design Algorithms
Data Structures
Protocols <Your Code>
Libraries
Language
Platform
Summary
Static analysis makes code review more efficient. Critical components
Algorithm Rules Interface
Static analysis brings implementation security to programmers.
Secure Programming with Static Analysis
Brian Chess, Ph.D. Chief Scientist Fortify Software
[email protected]