1
Michael Pradel TU Darmstadt
Understanding and Automatically Preventing Injection Attacks on Node.js
Joint work with Cristian Staicu (TU Darmstadt) and Ben Livshits (Microsoft Research, Redmond)
Understanding and Automatically Preventing Injection Attacks on - - PowerPoint PPT Presentation
Understanding and Automatically Preventing Injection Attacks on Node.js Michael Pradel TU Darmstadt Joint work with Cristian Staicu (TU Darmstadt) and Ben Livshits (Microsoft Research, Redmond) 1 Why JavaScript? Relevant and challenging
1
Joint work with Cristian Staicu (TU Darmstadt) and Ben Livshits (Microsoft Research, Redmond)
2
(Source: GitHub.com)
3
4
4
4
4
5
Over 300.000 modules No specified trust relationships
Many indirect dependences
5
Over 300.000 modules No specified trust relationships
Many indirect dependences
6
var msg = /* receive from network */ growl(msg);
6
var msg = /* receive from network */ growl(msg);
Platform-specific command to show notifications Pass message to command without any checks
7
function 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
function 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
function 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
function 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
function 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:
8
First large-scale study of Node.js security 236K modules, 816M lines of JavaScript
Static analysis and runtime enforcement Automatic and easy to deploy Small overhead and high accuracy
8
First large-scale study of Node.js security 236K modules, 816M lines of JavaScript
Static analysis and runtime enforcement Automatic and easy to deploy Small overhead and high accuracy
9
9
9
9
9
Attacker-controlled data may reach API: 58% Defense mechanisms None: 90% Regular expression: 9%
10
Reported 20 previously unknown
After several months, only 3 fixed
10
Reported 20 previously unknown
After several months, only 3 fixed
10
Reported 20 previously unknown
After several months, only 3 fixed
11
First large-scale study of Node.js security 236K modules, 816M lines of JavaScript
Static analysis and runtime enforcement Automatic and easy to deploy Small overhead and high accuracy
11
First large-scale study of Node.js security 236K modules, 816M lines of JavaScript
Static analysis and runtime enforcement Automatic and easy to deploy Small overhead and high accuracy
12
13
Overapproximate strings passed to injection API Represent possible values as a tree
13
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
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
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
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
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
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(" ")); }
empty array ”cp” $name ”.” $ext push push push join ” ” ”˜/.localBackup/” +
14
Statically model operations (bottom-up) Unknown parts to be filled at runtime
14
Statically model operations (bottom-up) Unknown parts to be filled at runtime
empty array ”cp” $name ”.” $ext push push push join ” ” ”˜/.localBackup/” +
15
Enforce structure via partial AST For unknown parts, allow only benign AST nodes
15
Enforce structure via partial AST For unknown parts, allow only benign AST nodes
Command Literal Arguments Literal Literal cp ??? ˜/.localBackup/
16
Command Literal Arguments Literal Literal cp ??? ˜/.localBackup/
16
Command Literal Arguments Literal Literal cp f.txt ˜/.localBackup/ Command Literal Arguments Literal Literal cp ??? ˜/.localBackup/
16
Command Literal Arguments Literal Literal cp f.txt ˜/.localBackup/
Command Literal Arguments Literal Literal cp ??? ˜/.localBackup/
16
CompoundCmd Command Command Literal Command ... ... ... ... Command Literal Arguments Literal Literal cp ??? ˜/.localBackup/
16
CompoundCmd Command Command Literal Command ... ... ... ... Command Literal Arguments Literal Literal cp ??? ˜/.localBackup/
17
51K call sites of injection APIs
At least 10 known characters Only 1 hole
4.4 seconds per module
18
24 modules 56 benign and 65 malicious inputs
Zero false negatives (i.e., no missed injections) Five false positives (i.e., overly conservative) Overhead (avg.): 0.74 milliseconds per call
19
First large-scale empirical study of Node.js
Static inference of expected string values AST-based runtime policy