Rootkits for JavaScript Environments Intro

manipulate the JavaScript environment to interpose undetectable attacker code between a site's scripts and the native JavaScript objects;

very narrow target: bookmarklet-based password managers

bookmarklet: bookmarked JavaScript code. Click the , execute the code

example: :'hello, world' The Players & the Game

= attacker bookmarklet = victim

1. user navigates to evil.com, is prompted to log in 2. user clicks bookmarklet 3. bookmarklet asks page "who are you? " to determine what username and pass to use 4. evil.com answers "bank.com please, thank you " 5. ☠,$,☹ What Makes this Attack Possible

Additionally: page always loads first, bookmarklet second; some pass managers store all the data on the client side, in the bookmarklet itself. I know. Attack Techniques

Shadowing

Emulation

Prototype Poisoning

Reflection

Global Variable Hijacking

Caller Shadowing

replace native JavaScript objects with global objects with the same name Example (works in IE and ):

Rootkit Code Bookmarklet Code

var window = { if (window.location.host == "bank. location: { host: "bank.com" } com") }; doLogin(password); Emulation

to thwart attacks of the kind on the previous slide, bookmarklet authors could attempt to test the validity of the "window" object

rootkit authors simply emulate the expected behavior:

window.__defineGetter__("location", function () { return "://bank.com/login#"; Rootkit Code });

window.__defineSetter__("location", function (v) { });

Bookmarklet Code window.location = "#" Prototype Poisoning

alter behavior of native objects like strings, functions and regular expressions

Rootkit Code Bookmarklet Code

RegExp.prototype.exec = (/ˆhttps?:/i).exec(url) function () { return true; } Global variable hijacking

rootkit author may subvert integrity of global variables by declaring getters and setters for the vars in the window object bookmarklet author may: never use any variables (yeah right) wrap the entire bookmarklet code in an anonymous function. It's cool and it works, but leads to problem on the next slide...

Rootkit Code Bookmarklet Code

window.__defineGetter__( "x", function () { ... }); var x = "#" window.__defineSetter__( "x", function (v) { ... }); Caller

say bookmarklet author wraps entire bookmarklet in an anonymous function, to protect against global var hijacking: (function () { ... if (obj == "bank.com") ... })();

not good enough: == implicitly calls the valueOf method. Attacker owns that function. The moment control gets transferred to valueOf, attacker: 1. obtains pointer to anonymous function by checking call stack 2. calls the anonymous function's toString() method 3. ☠,$,☹ because some bookmarklets store all passwords in the code. Locally. I know. Case studies

team evaluated 6 commercial password managers. all vulnerable. some used encryption; didn't matter. 4 revealed all secrets with 1 click. remaining 2 were exploited by attacking their cross-site scripting filter. VeriSign (yes, that one)

product: "One-Click Sign-In Bookmark" what it took (shadowing): var location = { hostname: "www.facebook.com", href: "http://www.facebook.com/" }; a variant on the above extracted all passwords at once authors' recommended fix implemented soon after reported MashedLife what it took (prototype poisoning): String.prototype.toLowerCase = function() { return "bank.com"; }; authors' recommended fix implemented in under a month

Passpack

what it took (prototype poisoning): String.prototype.toString = function() { return "https://delicious.com"; }; Passpack also validates Referer header, but if none is present, it lets the request through. So it actually doesn't validate the Referer header. authors' recommended fix implemented and deployed in 20 minutes 1Password

stores all user data locally, encrypted, in a global var named 'database.' what it took (global variable setters): window.__defineSetter__("database", function (v) { ... }); attacker overrides the event handler for the user's master password input and decrypts all passwords at once; vendor acknowledged vulnerability but declined to fix it. Clipperz

bookmarklet serializes contents of the login form and presents it to user user pastes serialized content into Clipperz later on, Clipperz submits form as if it came from user when user wants to sign in CSRF anyone? because Clipperz relies on CSRF to make this work, it attempts to sanitize the form to prevent XSS however, it sanitizes locally, in JavaScript (in the bookmarklet) what it took (prototype poisoning): Array.prototype.join = function() { ... return evilString; } fixed within 4 days of reporting MyVidoop

very similar to Clipperz, except it submits the serialized form itself -- user does not have to paste it during registration process same weakness: sanitizes form locally fixed within 1 day of reporting Defenses

1. Don't store passwords locally; instead, store a secure cookie for pwdmgr.com containing a master secret 2. When a pass is needed, query server by inserting a