Injection Attacks on Node.js Automatically Preventing...
Transcript of Injection Attacks on Node.js Automatically Preventing...
1
Michael PradelTU Darmstadt
Understanding andAutomatically PreventingInjection Attacks on Node.js
Joint work with Cristian Staicu (TU Darmstadt)and Ben Livshits (Microsoft Research, Redmond)
2
Why JavaScript?
Relevant and challenging
Rank of top languages on GitHub over time(Source: GitHub.com)
3
Why JavaScript?
1096 pages 153 pages
Relevant and challenging
4
Motivation: JavaScript (In)Security
JavaScript: Popular beyond the browser
Client-sideweb app
Browser
Operatingsystem
4
Motivation: JavaScript (In)Security
JavaScript: Popular beyond the browser
Client-sideweb app
Server-side ordesktop app
Mobileapp
Dalvik VMNode.jsBrowser
Operatingsystem
Operatingsystem
Operatingsystem
4
Motivation: JavaScript (In)Security
JavaScript: Popular beyond the browserSandbox Sandbox
Client-sideweb app
Server-side ordesktop app
Mobileapp
Dalvik VMNode.jsBrowser
Operatingsystem
Operatingsystem
Operatingsystem
4
Motivation: JavaScript (In)Security
JavaScript: Popular beyond the browserSandbox SandboxNo sandbox!
Client-sideweb app
Server-side ordesktop app
Mobileapp
Dalvik VMNode.jsBrowser
Operatingsystem
Operatingsystem
Operatingsystem
5
Culture of Naive Reuse
Node.js code: Builds on 3rd-party code
� Over 300.000 modules
� No specified trust relationshipsbetween modules
� Many indirect dependences
5
Culture of Naive Reuse
Node.js code: Builds on 3rd-party code
� Over 300.000 modules
� No specified trust relationshipsbetween modules
� Many indirect dependences
Risk of vulnerable and malicious code
6
Real Example: Growl Module
var msg = /* receive
from network */
growl(msg);
6
Real Example: Growl Module
var msg = /* receive
from network */
growl(msg);
Growl module:� Platform-specific command to show notifications� Pass message to command without any checks
7
Running Examplefunction backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
var kind = (ext === "jpg") ? "pics" : "other";
console.log(eval("messages.backup_" + kind));
}
7
Running Examplefunction backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
var kind = (ext === "jpg") ? "pics" : "other";
console.log(eval("messages.backup_" + kind));
}
Constructshell command
Execute it
7
Running Examplefunction backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
var kind = (ext === "jpg") ? "pics" : "other";
console.log(eval("messages.backup_" + kind));
} Construct JavaScript codeand execute it
7
Running Examplefunction backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
var kind = (ext === "jpg") ? "pics" : "other";
console.log(eval("messages.backup_" + kind));
}
Injection APIs:Interpret stringas code
7
Running Examplefunction backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
var kind = (ext === "jpg") ? "pics" : "other";
console.log(eval("messages.backup_" + kind));
} Injection attack:backupFile("-h && rm -rf * && echo ", "")
8
Our Contributions
1. Study of injection vulnerabilities� First large-scale study of Node.js security
� 236K modules, 816M lines of JavaScript
2. Repair of vulnerabilities� Static analysis and runtime enforcement
� Automatic and easy to deploy
� Small overhead and high accuracy
8
Our Contributions
1. Study of injection vulnerabilities� First large-scale study of Node.js security
� 236K modules, 816M lines of JavaScript
2. Repair of vulnerabilities� Static analysis and runtime enforcement
� Automatic and easy to deploy
� Small overhead and high accuracy
9
Study: Prevalence
Are injection vulnerabilities widespread?
9
Study: Prevalence
Are injection vulnerabilities widespread?
9
Study: Prevalence
Are injection vulnerabilities widespread?
Direct uses
9
Study: Prevalence
Are injection vulnerabilities widespread?
Indirectuses viaothermodules
9
Study: Prevalence
Are injection vulnerabilities widespread?
Manual inspection of 150 call sites
� Attacker-controlled data may reach API: 58%
� Defense mechanisms� None: 90%� Regular expression: 9%
10
Study: Developer Reactions
Do developers fix vulnerabilities?
� Reported 20 previously unknownvulnerabilities
� After several months, only 3 fixed
10
Study: Developer Reactions
Do developers fix vulnerabilities?
� Reported 20 previously unknownvulnerabilities
� After several months, only 3 fixed
10
Study: Developer Reactions
Do developers fix vulnerabilities?
� Reported 20 previously unknownvulnerabilities
� After several months, only 3 fixed
Need mitigation technique thatrequires very little developer attention
11
Our Contributions
1. Study of injection vulnerabilities� First large-scale study of Node.js security
� 236K modules, 816M lines of JavaScript
2. Repair of vulnerabilities� Static analysis and runtime enforcement
� Automatic and easy to deploy
� Small overhead and high accuracy
11
Our Contributions
1. Study of injection vulnerabilities� First large-scale study of Node.js security
� 236K modules, 816M lines of JavaScript
2. Repair of vulnerabilities� Static analysis and runtime enforcement
� Automatic and easy to deploy
� Small overhead and high accuracy
12
Preventing Injections
Vulnerable code
Code withruntime checks
Saferuntimebehavior
Stringtemplates
Staticallysafe code
Runtimeinputs
Static analysis
Dynamic enforcement
Synthesize policy
13
Static Analysis: Template Trees
1. Backward data flow analysis� Overapproximate strings passed to injection API� Represent possible values as a tree
13
Static Analysis: Template Trees
1. Backward data flow analysis� Overapproximate strings passed to injection API� Represent possible values as a tree
function backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
}
13
Static Analysis: Template Trees
1. Backward data flow analysis� Overapproximate strings passed to injection API� Represent possible values as a tree
$cmd
join
” ”
function backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
}
13
Static Analysis: Template Trees
1. Backward data flow analysis� Overapproximate strings passed to injection API� Represent possible values as a tree
function backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
}
$cmd
push
join
” ”
”˜/.localBackup/”
13
Static Analysis: Template Trees
1. Backward data flow analysis� Overapproximate strings passed to injection API� Represent possible values as a tree
function backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
}$name ”.” $ext
$cmd
push
push
join
” ”
”˜/.localBackup/”
+
13
Static Analysis: Template Trees
1. Backward data flow analysis� Overapproximate strings passed to injection API� Represent possible values as a tree
function backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
}$cmd ”cp” $name ”.” $ext
push
push
push
join
” ”
”˜/.localBackup/”
+
13
Static Analysis: Template Trees
1. Backward data flow analysis� Overapproximate strings passed to injection API� Represent possible values as a tree
function backupFile(name, ext) {
var cmd = [];
cmd.push("cp");
cmd.push(name + "." + ext);
cmd.push("̃ /.localBackup/");
exec(cmd.join(" "));
}emptyarray
”cp” $name ”.” $ext
push
push
push
join
” ”
”˜/.localBackup/”
+
14
Static Analysis: Templates
2. Evaluate template trees into templates� Statically model operations (bottom-up)� Unknown parts to be filled at runtime
14
Static Analysis: Templates
2. Evaluate template trees into templates� Statically model operations (bottom-up)� Unknown parts to be filled at runtime
”cp $name.$ext ˜/.localBackup/”
emptyarray
”cp” $name ”.” $ext
push
push
push
join
” ”
”˜/.localBackup/”
+
15
Synthesizing a Policy
Create runtime policy from templates� Enforce structure via partial AST� For unknown parts, allow only benign AST nodes
15
Synthesizing a Policy
Create runtime policy from templates� Enforce structure via partial AST� For unknown parts, allow only benign AST nodes
”cp $name.$ext ˜/.localBackup/”
Bashgrammar
Command
Literal Arguments
Literal Literalcp
??? ˜/.localBackup/
16
Runtime Enforcement
Enforce policy on strings passed toinjection APIsPolicy:
Command
Literal Arguments
Literal Literalcp
??? ˜/.localBackup/
16
Runtime Enforcement
Enforce policy on strings passed toinjection APIsPolicy: Runtime string:
”cp f.txt ˜/.localBackup/”
Command
Literal Arguments
Literal Literalcp
f.txt ˜/.localBackup/
Command
Literal Arguments
Literal Literalcp
??? ˜/.localBackup/
16
Runtime Enforcement
Enforce policy on strings passed toinjection APIsPolicy: Runtime string:
”cp f.txt ˜/.localBackup/”
Command
Literal Arguments
Literal Literalcp
f.txt ˜/.localBackup/
AcceptedCommand
Literal Arguments
Literal Literalcp
??? ˜/.localBackup/
16
Runtime Enforcement
Enforce policy on strings passed toinjection APIsPolicy: Runtime string:
”cp -h && rm -rf * &&echo ˜/.localBackup/”
CompoundCmd
Command Command
Literal
Command
... ...
...
...
Command
Literal Arguments
Literal Literalcp
??? ˜/.localBackup/
16
Runtime Enforcement
Enforce policy on strings passed toinjection APIs
Rejected
Policy: Runtime string:”cp -h && rm -rf * &&
echo ˜/.localBackup/”CompoundCmd
Command Command
Literal
Command
... ...
...
...
Command
Literal Arguments
Literal Literalcp
??? ˜/.localBackup/
17
Evaluation: Static Analysis
Setup:� 51K call sites of injection APIs
Statically safe:36.7%
To be checked at runtime: 63.3%
Most call sites:� At least 10 known characters� Only 1 hole
Precision:
Performance:� 4.4 seconds per module
18
Evaluation: Runtime Enforcement
Setup� 24 modules� 56 benign and 65 malicious inputs
Results:� Zero false negatives (i.e., no missed injections)� Five false positives (i.e., overly conservative)� Overhead (avg.): 0.74 milliseconds per call
19
Conclusion
Understand injection vulnerabilities� First large-scale empirical study of Node.js
(in)security
Detect and prevent injections� Static inference of expected string values� AST-based runtime policy
→ Automated repair of vulnerabilities
More details: Technical report on my web site