Professional Documents
Culture Documents
Shellcon 2019 Rolling Your Own - 2
Shellcon 2019 Rolling Your Own - 2
Shellcon 2019 Rolling Your Own - 2
https://tldrsec.com
By the end of this talk you will...
● Understand at a high level how static analysis tools work
● See several practical, hands-on examples using open source tools
● Have an intuition for what use cases are easy and which are hard
● Know when commercial SAST tools may be useful for your company
About Us
● Daniel DeFreez
○ PhD student at UC Davis (program analysis and automated reasoning group)
○ LLVM and Linux Enthusiast
● Clint Gibler
○ Technical Director and Research Director at NCC Group
○ PhD from UC Davis
○ Loves building tools to find bugs
NCC Group - Books
Head of
CEO
NCC Group - Alumni Red Team
Co-founder
Security Engineer
Agenda
● Background
○ Static analysis vs dynamic analysis
○ Motivating example - finding NodeJS command injection
○ Fundamentals - parsing, abstract syntax trees (ASTs)
● Hands-on Examples
○ Interactively exploring Rails code bases
○ Finding command injection in NodeJS apps
● Challenges and Limitations
○ When static analysis is hard
● Going Forward, Other Resources
○ Other use cases of AST matching
○ Should I buy a SAST tool?
○ Open source tools
Background
Static vs. Dynamic Analysis Overview
● Static analysis - reason about code based on looking at it
● Dynamic analysis - run code and observe how it behaves
● ShellCon 2019 - Automated Bug Finding in Practice -> Slides | Video
Grep / Linters
Motivating Example: Find command injection
● NodeJS child_process.exec()
“Spawns a shell then executes the command within that shell... The command
string passed to the exec function is processed directly by the shell and special
characters need to be dealt with accordingly.”
Aww yeah
Motivating Example: Find command injection
Attempt 1:
// exec(arg) in a comment
console.log("exec(foo) in a string") !=
// arg to exec is a combination of
// variable and hard-coded string
exec(arg + " constant")
exec("constant" + arg)
Search language ● Clever regexes can get closer,
Background
● Controller - class that defines methods that respond to HTTP reqs (“route”)
● before_action - “call this method before running this route”
#3 - Routes: --rails-summarize-controllers
#3 - Routes: --rails-summarize-controllers
} methods
} methods
#3 - Routes: --rails-summarize-controllers
before_action
} before_action
#3 - Routes: --rails-summarize-controllers
Not subclassing the right controller -> security checks may not be applied
#4 --rails-controllers-by-superclass
:verify_password
Profiles || affected = update, destroy | ignored = edit, show, delete
:verify_with_otp
Api::V1::Owners || affected = create, destroy | ignored = show, gems,
verify_gem_ownership
Api::V1::Rubygems || affected = create | ignored = index, show,
reverse_dependencies
Api::V1::Deletions || affected = create | ignored =
#5 --rails-controllers-by-before-action
:redirect_to_signin
Dashboards || affected = show | ignored =
EmailConfirmations || affected = | ignored = update, new
Profiles || affected = edit, update, delete, destroy | ignored = show
Notifiers || affected = show, update | ignored =
MultifactorAuths || affected = new, create, update | ignored =
Api::V1::ApiKeys || affected = reset | ignored = show
:verify_password
Profiles || affected = update, destroy | ignored = edit, show, delete
:verify_with_otp
}
Api::V1::Owners || affected = create, destroy | ignored = show, gems,
verify_gem_ownership
Api::V1::Rubygems || affected = create | ignored = index, show,
reverse_dependencies
Api::V1::Deletions || affected = create | ignored =
GitHub Case Study
JavaScript Command Injection
NodeJS shell command injection
# Source files in
GitHub dataset
2.2 billion
# JavaScript files 284 million (13%)
child_process
& exec 322,000 (1%) % is of previous
working set
+ req 12,236 (3.8%)
Extract Function Calls Named exec() - jq
"callFunction": {
"sourceRange": [ 750, 754 ],
"name": "exec",
cat ast.json
"sourceSpan": {
| jq '..
"start": [29, 11],
| .callFunction?
"end": [29, 15 ]
| select(.name == "exec")'
},
"term": "Identifier"
}
jq Limitations
● Works best for a pipeline that gets narrower and narrower
● Cumbersome to match part of the tree then go back up
Quick Terminology - Taint
● Taint source - where untrusted, attacker-controlled data comes in
○ URL parameters, cookies, data from a third-party service, ...
● Taint sink - function call that’s dangerous if attacker controlled data reaches
○ Unparameterized SQL query, shell exec()
“Two-step” taint analysis
● A quick way to reduce false positives is to limit path length
● “One step” would be directly using taint source at sink
Step 1 Step 2
Taint Source
● Extremely rough approximation: any variable named “req”
○ Clearly this could be improved
● ...few results ��
AST Subtree Approximation
Rule #1
Our analysis in a nutshell
Three rules:
Rule #1
Rule #2
Our analysis in a nutshell
Three rules:
Rule #1
Rule #2 Rule #3
Some real command injection examples
Some real command injection examples
Some real command injection examples
Most companies...
Types Matter - JS Exec, not so simple
● Just knowing exec() is a function call isn’t enough
● Here, we’re running a regex, not executing a command in a shell
Going Forward, Other Resources
Example Code Patterns You Can Find with ASTs
● Find all methods that <return a value> or <take a parameter> of this type
● Find all classes that inherit <this interface> or subclass <this class>
● Find all unauthenticated routes
○ Find all methods that define routes
○ Filter out methods that check the user’s session / apply the right middleware
Killer applications:
● Find when our secure wrapper library isn’t used (ensure safe defaults)
● Find company-specific business logic bugs. E.g. “It’s a bug when:”
○ A method calls foo() before bar()
○ A method calls foo() and not bar()
○ The arguments to foo() are (not) a constant value (e.g. nonces in crypto APIs, creds, …)
Static Analysis Difficulty Cheat Sheet Abstract Interpretation /
formal methods
Probably
use an
Implementation difficulty
Tl;dr - if >= 1 of these apply, potentially not the best immediate use of your time
and money.
● You use modern frameworks and don’t have significant legacy code
● You ship code rapidly (embraced Agile/DevOps)
● Your code is not written in C/C++
● You haven’t already invested significant effort in building secure by default libs
● You don’t have one or more AppSec engineers who can dedicate months to
onboarding/tuning the SAST tool
Should I buy a SAST tool?
(Borrowed: AppSec EU 2018 - “How Lead Companies are Scaling Their Security”)
Some considerations:
● Do you have large, legacy code bases that haven’t be thoroughly vetted?
● Is much of your code in Java or other statically typed languages?
○ Dynamic languages are harder for static analysis (Python / Ruby / JavaScript)
● How mature is your security program?
● Does your org heavily use custom frameworks with non-standard control
flow?
● Are you willing to invest months of security engineer time in the rollout?
Calculate ROI
● How much security engineer time is required to comb through results vs. how
many bugs of what severity do we find?
● Initial upfront time investment? Low recurring time cost?
● Might find many good bugs on initial integration but fewer over the years
Should I buy a SAST tool?
Security engineering / secure wrapper libraries may have higher ROI
● AppSec Cali 2019 - Lessons Learned from the DevSecOps Trenches
○ Panel of senior security leaders from: Netflix, Dropbox, Datadog, Snap, DocuSign
● DevSecCon Seattle 2019 - Ban Footguns: How to standardize how
developers use dangerous aspects of your framework
● BsidesSF 2019 - DevSecOps State of the Union
○ Several examples of security engineering solving classes of vulnerabilities
Open Source Static Analysis Tools
● C/C++ - Clang Static Analyzer, Phasar, Cppcheck
● C#/.NET - Puma Scan, Security Code Scan
● Golang - gosec, glasgo
● Java - SpotBugs, Frameworks: Soot, WALA
● JavaScript/Typescript - NodeJsScan, eslint, tslint
● Python - bandit, dlint, pyre-check (data-flow analysis to find web app bugs)
● Ruby - Brakeman
● Slides: https://bit.ly/2019ShellCon_StaticAnalysis
● Code: https://github.com/nccgroup/lightweight_static_analysis
● Uplevel your security knowledge: https://tldrsec.com