OWASP Guide to Building Secure Web Applications and Web Services, Chapter 13: Interpreter Injection

Web applications are vulnerable to a barrage of injection attacks, such as SQL injection and XSS. This chapter from OWASP explains how to secure your Web services against injection exploits.

This article is provided by special arrangement with the Open Web Application Security Project (OWASP). This article is covered by the Creative Commons Share-Alike Attribution 2.5 license. You can find the latest version of this article and more free and open application security tools and documentation at http://www.owasp.org.


Interpreter Injection

Objective
To ensure that applications are secure from well-known parameter manipulation attacks against common interpreters.

Platforms Affected
All

Relevant COBIT Topics
DS11 – Manage Data – All sections should be reviewed
DS11.9 – Data processing integrity
DS11.20 – Continued integrity of stored data

User Agent Injection
User agent injection is a significant problem for web applications. We cannot control the user's desktop (nor would we want to), but it is part of the trust equation.

  • The browser may be compromised with spyware or Trojans
  • The browser has several in-built renderers, including: HTML, XHTML, XML, Flash (about 90% of all browsers), Javascript (nearly 99%), XUL (Firefox and Mozilla), XAML (IE 7 and later) and so on.

Render engines and plug-ins can be abused by:

  • As phishing attempts - pure HTML can be used to fake up a convincing site
  • As trust violations - XUL and XAML are used to write the user interface - if they can be abused, nothing on the browser is trustworthy, including the URL, padlock and certificate details
  • As malware injection paths - all software has bugs, and spyware is adept at abusing these bugs to install or run malicious software on the user's machine
  • As information gatherers - stealing the user's cookies and details allows the attacker to resume the user's session elsewhere

Vectors of user agent injection

  • Cross-site scripting using DHTML / Javascript
  • Flash / Shockwave
  • Mocha (old Netscape)
  • ActiveX (IE only)
  • Plugins (such as Quicktime, Acrobat, or Windows Media Player)
  • BHOs (often used by spyware and Trojans) – the user may not be aware of these babies
  • HTML bugs (all browsers)
  • XUL (Firefox) Chrome
  • XAML (IE 7) Chrome – untested at the time of writing

Immediate Reflection
This is the most typical form of user agent injection as it is trivial to find and execute.

The victim is encouraged / forced to a vulnerable page, such as a link to cute kittens, a redirect page to "activate" an account, or a vulnerable form which contains an improperly sanitized field. Once the user is on the vulnerable destination, the embedded reflection attack launches the attacker's payload. There are limits to the size of embedded reflection attacks – most GET requests need to be less than 2 or 4 KB in size. However, this has proved ample in the past.

Nearly all phishing attempts would be considered immediate reflection attacks.

Stored
In this model, the injection occurs at a previous time and users are affected at a later date. The usual type of attack are blog comments, forum, and any relatively public site which can be obviated in some fashion.

DOM-based XSS Injection
DOM Based XSS Injection (detailed in the Klein whitepaper in the Further References section) allows an attacker to use the Data Object Model (DOM) to introduce hostile code into vulnerable client-side Javascript embedded in many pages. For more information, please refer to DOM-based XSS Injections paper in the Further Reading section.

Protecting against DOM based attacks
From Klein's paper:

  • Avoid client side document rewriting, redirection, or other sensitive actions, using client side data. Most of these effects can be achieved by using dynamic pages (server side).
  • Analyzing and hardening the client side (Javascript) code. Reference to DOM objects that may be influenced by the user (attacker) should be inspected, including (but not limited to):
  • document.URL
  • document.URLUnencoded
  • document.location (and many of its properties)
  • document.referrer
  • window.location (and many of its properties)
    Note that a document object property or a window object property may be referenced syntactically in many ways - explicitly (e.g. window.location), implicitly (e.g. location), or via obtaining a handle to a window and using it (e.g. handle_to_some_window.location).

Special attention should be given to scenarios wherein the DOM is modified, either explicitly or potentially, either via raw access to the HTML or via access to the DOM itself, e.g. (by no means an exhaustive list, there are probably various browser extensions):
Write raw HTML, e.g.:

  • document.write(…)
  • document.writeln(…)
  • document.body.innerHtml=…
  • Directly modifying the DOM (including DHTML events), e.g.:
  • document.forms[0].action=… (and various other collections)
  • document.attachEvent(…)
  • document.create…(…)
  • document.execCommand(…)
  • document.body. … (accessing the DOM through the body object)
  • window.attachEvent(…)

Replacing the document URL, e.g.:

  • document.location=… (and assigning to location's href, host and hostname)
  • document.location.hostname=…
  • document.location.replace(…)
  • document.location.assign(…)
  • document.URL=…
  • window.navigate(…)

Opening/modifying a window, e.g.:

  • document.open(…)
  • window.open(…)
  • window.location.href=… (and assigning to location's href, host and hostname)

Directly executing script, e.g.:

  • eval(…)
  • window.execScript(…)
  • window.setInterval(…)
  • window.setTimeout(…)

How to protect yourself against reflected and stored XSS
Protecting against Reflected Attacks
Input validation should be used to remove suspicious characters, preferably by strong validation strategies; it is always better to ensure that data does not have illegal characters to start with.

In ASP.NET, you should add this line to your web.config:

<pages validateRequest="true" />

in the <system> </system> area.

Protecting against stored attacks

ASP.NET: Change web.config – validateRequest to be true and use

HTTPUtility.HTMLEncode() for body variables

PHP: Use htmlentities(), htmlspecialchars(), for HTML output, and urlencode() for GET arguments

JSP: Output validation is actually very simple for those using Java Server Pages - just use Struts, such as using <bean:write ... > and friends:

Good:

<html:submit styleClass="button" value="<bean:message key="button.submitText"/> "/>

Bad:

out.println('<input type="submit" class="button" value="<%=buttonSubmitText%>" />');

The old JSP techniques such as <%= ... %> and out.print* do not provide any protection from XSS attacks. They should not be used, and any code including them should be rejected.

With a small caveat, you can use <%= ... %> as an argument to Struts tags:

<html:submit styleClass="button" value="<%=button.submitText%>"/ > "/>

But it is still better to use the tag for this purpose. Do not use System.out.* for output, even for output to the console - console messages should be logged via the logging mechanism.

HTTP Response Splitting
This attack, described in a 2004 paper by Klein (see HTTP Response Splitting Whitepaper in the Further Reading section), uses a weakness in the HTTP protocol definition to inject hostile data into the user's browser. Klein describes the following classes of attacks:

  • Cross-Site Scripting (XSS)
  • Web Cache Poisoning (defacement)
  • Cross User attacks (single user, single page, temporary defacement)
  • Hijacking pages
  • Browser cache poisoning

How to determine if you are vulnerable
In HTTP, the headers and body are separated by a double carriage return line feed sequence. If the attacker can insert data into a header, such as the location header (used in redirects) or in the cookie, and if the application does not protect against CRLF injection, it is quite likely that the application will be vulnerable to HTTP Response Splitting. The attack injects two responses (thus the name), where the first response is the attacker's payload, and the second response containing the rest of the user's actual output, is usually ignored by the web server.

How to protect yourself
Investigate all uses of HTTP headers, such as

  • setting cookies
  • using location (or redirect() functions)
  • setting mime-types, content-type, file size, etc
  • or setting custom headers

If these contain unvalidated user input, the application is vulnerable when used with application frameworks that cannot detect this issue.

If the application has to use user-supplied input in HTTP headers, it should check for double "n" or "rn" values in the input data and eliminate it.

Many application servers and frameworks have basic protection against HTTP response splitting, but it is not adequate to task, and you should not allow unvalidated user input in HTTP headers.

SQL Injection
SQL Injection can occur with every form of database access. However, some forms of SQL injection are harder to obviate than others:

  • Parameterized stored procedures, particularly those with strongly typed parameters
  • = Prepared statements
  • = ORM (e.g., Hibernate)
  • Dynamic queries

It is best to start at the top and work to the lowest form of SQL access to prevent injection issues.

Although old-fashioned dynamic SQL injection is still a favorite amongst PHP programs, it should be noted that the state of the art has advanced significantly:

  • It is possible to perform blind (and complete) injection attacks (see the NGS papers in the references section of this chapter) using timing based attacks
  • It is possible to obviate certain forms of stored procedures, particularly when the stored procedure is just a wrapper

The application should:

  • All SQL statements should ensure that where a user is affecting data, that the data is selected or updated based upon the user's record

  • In code which calls whichever persistence layer, escape data as per that persistence layer's requirements to avoid SQL injections

  • Have at least one automated test should try to perform a SQL injection.

This will ensure the code has an extra layer of defense against SQL injections, and ensure that if this control fails, that the likelihood of the injection working is known.

ORM Injection
It is commonly thought that ORM layers, like Hibernate are immune to SQL injection. This is not the case as Hibernate includes a subset of SQL called HQL, and allows "native" SQL queries. Often the ORM layer only minimally manipulates the inbound query before handing it off to the database for processing.

If using Hibernate, do not use the depreciated session.find() method without using one of the query binding overloads. Using session.find() with direct user input allows the user input to be passed directly to the underlying SQL engine and will result in SQL injections on all supported RDBMS.

Payment payment = (Payment) session.find("from com.example.Payment as payment where payment.id = " + paymentIds.get(i));

The above Hibernate HQL will allow SQL injection from paymentIds, which are obtained from the user. A safer way to express this is:

int pId = paymentIds.get(i);
TsPayment payment = (TsPayment) session.find("from com.example.Payment as payment where payment.id = ?", pId, StringType);

It is vital that input is properly escaped before use on a SQL database. Luckily, the current Oracle JDBC driver escapes input for prepared statements and parameterized stored procedures. However, if the driver changes, any code that assumes that input is safe will be at risk.

The application should:

  • Ensure that all native queries are properly escaped or do not contain user input
  • Ensure that all ORM calls which translate into dynamic queries are re-written to be bound parameters
  • In code which calls whichever persistence layer, escape data as per that persistence layer's requirements to avoid SQL injections
  • Have at least one automated test should try to perform a SQL injection.
  • This will ensure the code has an extra layer of defense against SQL injections, and ensure that if this control fails, that the likelihood of the injection working is known.

LDAP Injection
LDAP injections are relatively rare at the time of writing, but they are devastating if not protected against. LDAP injections are thankfully relatively easy to prevent: use positive validation to eliminate all but valid username and other dynamic inputs.

For example, if the following query is used:

String principal = "cn=" + getParameter("username") + ", ou=Users, o=example";
String password = getParameter("password");

env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, principal);
env.put(Context.SECURITY_CREDENTIALS, password);

// Create the initial context
DirContext ctx = new InitialDirContext(env);

the LDAP server will be at risk from LDAP injection. It is vital that LDAP special characters are removed prior to any LDAP queries taking place:

// if the username contains LDAP specials, stop now
if ( containsLDAPspecials(getParameter("username")) ) {
 throw new javax.naming.AuthenticationException();
}

String principal = "cn=" + getParameter("username") + ", ou=Users, o=example";
String password = getParameter("password");

env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, principal);
env.put(Context.SECURITY_CREDENTIALS, password);

// Create the initial context
DirContext ctx = new InitialDirContext(env);

XML Injection
Many systems now use XML for data transport and transformation. It is vital that XML injection is not possible.

Attack paths - blind XPath Injection
Amit Klein details a variation of the blind SQL injection technique in the paper in the references section below. The technique allows attackers to perform complete XPath based attacks, as the technique does not require prior knowledge of the XPath schema.

As XPath is used for everything from searching for nodes within an XML document right through to user authentication, searches and so on, this technique can be devastating if the system is vulnerable.

The technique Klein describes is also a useful extension for other blind injection-capable interpreters, such as many SQL dialects.

How to determine if you are vulnerable

  • If you allow unvalidated input from untrusted sources, such as the user; AND
  • If you use XML functions, such as constructing XML transactions, use XPath queries, or use XSLT template expansion with the tainted data, you are most likely vulnerable.

How to protect yourself
This requires the following characters to be removed (ie prohibited) or properly escaped:

  • < > / ' = " to prevent straight parameter injection
  • XPath queries should not contain any meta characters (such as ' = * ? // or similar)
  • XSLT expansions should not contain any user input, or if they do, that you comprehensively test the existence of the file, and ensure that the files are within the bounds set by the Java 2 Security Policy

Code Injection
ASP.NET does not contain any functions to include injected code, but can do it through the use of CodeProvider classes along with reflection. See the "ASP.NET Eval" reference.

Any PHP code which uses eval() is at risk from code injection.

Java generally does not contain the ability to evaluate dynamic JSPs.

However, there are two exceptions to this:

  • Dynamic JSP inclusion (<jsp:include ... >)
  • Using a third party JSP eval taglibs.
  • Portals and other community-based software often require the evaluation of dynamic code for templates and skinning. If the portal software requires dynamic includes and dynamic code execution, there is a risk of Java or JSP code injection.

To combat this, the primary defenses are to

  • Always prefer static include (<% include ... %> )
  • Not allow the inclusion of files outside of the server by using Java 2 Security policies
  • Establish firewall rules to prevent outbound Internet connectivity
  • Ensure that code does not interpret user data without prior validation.

In a theoretical example, the user may choose to use "Cats" as their primary theme. In this theoretical example, the code dynamically includes a file called "Cats.theme.jsp" using simple concatenation. However, if the user types in something else, they may be able to get Java code interpreted on the server. At that stage, the application server is no longer 0wned by the user. Generally, dynamic inclusion and dynamic code evaluation should be frowned upon.

Further reading

There are several challenges to trusting input and sending output from the user: As data is often obtained from unclean sources, output validation is required.

Dig deeper on Building security into the SDLC (Software development life cycle)

Pro+

Features

Enjoy the benefits of Pro+ membership, learn more and join.

0 comments

Oldest 

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

-ADS BY GOOGLE

SearchSOA

TheServerSide

SearchCloudApplications

SearchAWS

SearchBusinessAnalytics

SearchFinancialApplications

SearchHealthIT

Close