Broadcast on Broadcast off
The Documentation for Project Zero has moved. Please update your bookmarks to: http://www.projectzero.org/documentation/
Advanced Wiki Search
Table of
Contents...
Hide

Project Zero Developer’s Guide?

Concepts and components
Basic concepts overview
Event processing
Writing Java handlers
Writing Groovy handlers
Firing events
Global Context
Global Context reference
Application directory layout?
Virtualized directories
Assemble
PHP
Features and configuration
Configuration
Debugging?
Dependencies?
Packaging?
Application classpath
Logging and tracing
RESTful resources?
RESTful documentation?
File serving
Response rendering
Validators and validation
HTTP error handling
Calling a remote resource
Using the Connection API
Sending an email using EmailConnection
Configuring destinations
Configuring protocols
Configuring connection handlers
Creating a connection handler
Creating a custom protocol transport
Simple logging connection handlers
Protocol reference
Client programming with Dojo
Runtime options
Deployment modifications
HTTP configuration
SSL configuration
Proxy configuration
Extending the CLI
Security considerations
Authentication
OpenID authentication
Extending security
Security tokens
CSRF prevention support
Extending token support
Leveraging TAI
User service
File based user service
LDAP user service
Extending user service
Security Utilities
Leveraging XOREncoder
Extensions
Atom support
RSS support
JSON support
XMLEncoder
REST to SOAP extension
URIUtils
Developer Web tools?
Database setup tools
Configuring data access
Common query patterns
Advanced query patterns
Update patterns
Local database transactions
Extending data access
Configuration vendor differences
PHP data access
Resource model
Configuring ZRM
Resource model declaration
Programmatic model API
HTTP REST API
A ZRM mini tutorial
Active content filtering support
Default filters
Custom filters
Runtime management
Management commands
Zero socket opener
Other extension modules
Amazon E-commerce service
Flickr service
WeatherZero forecast service
Wikipedia service
Reference
Zero command line interface
JavaDoc - Public API
JavaDoc - Public SPI
JavaDoc - All Classes

 

Cross site request forgery

Cross-site request forgery (CSRF/XSRF) attacks are powerful and straight-forward attacks that can totally subvert the security of Web applications. These attacks can target both the integrity (causing changes on the server without users approval) and the confidentiality (leaking private data) of Web applications. The following sections of this article describe cross-site request forgery and how to prevent it.

How it works

Unlike Cross-Site Scripting (XSS) attacks, CSRF/XSRF attacks do not require an application bug that allows an attacker to inject active code into the Web-application. Instead, CSRF attacks work as soon the user opens a rogue Web application in parallel to the target application (for example, in a separate browser tab) or subsequent to a visit to the target Web application if that application does not clean up user credentials when the user navigates away. The rogue application can misuse the user's privileges to cause server-side actions on the user's behalf and, to a lesser extent, also retrieve confidential data, for example, from JSON requests using a special form of CSRF called JavaScript Hijacking attacks.

The attack works for all applications relying exclusively on traditional Web-authentication mechanism such as session cookies or HTTP basic authentication when no special precautions are taken. Hence, these attacks are very powerful and OWASP lists them in the Top 10 Web application vulnerabilities. For more information see this Wikipedia article.

While there a number of best practices out in the field, many:

  • Are wrong, for example using POST instead of GET does not protect against CSRF
  • Are very incomplete and limiting, for example not using arrays in JSON responses
  • Require quite a bit of effort by an application developer
To ease the development of secure application without burdening the application overtly, Project Zero provides corresponding countermeasures built into the framework.

Enabling CSRF protection

To enable protection, you must perform the following steps:

  1. Instrument your HTML and JavaScript files to include, in the server request, a CSRF-authenticator that assures the framework the request comes from your client-side code and not from a rogue application running in the client's browser.
  2. Modify the zero.config configuration file to enable CSRF-protection and to specify which resources require CSRF protection and which pages are safe entry points into the application.

Code instrumentation

CSRF protection relies on proof that a request for a protected server-side resource or action originates from an authenticated user's browser and from your own code. This code is loosely defined as the union of HTML, JavaScript code and CSS. That is, CSRF protection requires a form of code-credentials. Hence, each of your code pieces referencing protected server resources has to be instrumented to provide such proofs to the server with each request.

Depending on the particular application requirement, there are two, not necessarily mutually exclusive, modes of operation:

Transparent Protection
For applications in which all access to protected resources is either through static links in HTML pages or through XHR in Dojo, CSRF-protection is completely transparent.

Programmatic Protection
Applications that access protected resources through other means and cannot tolerate the performance overhead, due to the code-rewriting of the transparent mode, or require maximal security can enable CSRF-protection by instrumenting their code programmatically.

Transparent protection

The most convenient way to instrument applications is to rely on the transparent rewriting of HTML files on the server-side and client-site instrumentation of AJAX code.

Server-side HTML

To transparently embed CSRF protection code into an HTML page requires the use of the ACF library in Zero. After including the ACF library and resolving the ACF dependency for your application, add the following rule to your zero.config file:

@include "${/config/dependencies/zero.acf}/config/acf.config"

This rule has the following mandatory parameters:

uri
A URI pattern of the files that have to be rewritten. The URI patterns are the same regular expression patterns that are supported as part of the condition operators in Project Zero. See the conditions operations information of the Configuration article. You should also consult the general best practices for configuring security rules information in the Security considerations article as these also apply.

filterRuleFile
The rules governing which element referencing server-side resources are enhanced with CSRF protection. There are two default rules:
${/config/dependencies/zero.acf}/config/acf-csrf-config.xml
Rewrites all references to server-resources.
${/config/dependencies/zero.acf}/config/acf-csrf-safe-config.xml
Rewrites only references to server-resources that cannot cause leakage through HTTP referer fields.

For example, to rewrite the pages of /app use the following rule:

@include "acf.config" {
   "conditions": "/request/path =~ /app/(.*)?",
   "filterRuleFile" : "${/config/dependencies/zero.acf}/config/acf-csrf-config.xml"
}

For more information on leakage through HTTP referer fields, see the Best practices section.)

HELP Notes:

  • Rewriting only rewrites the HTML part of the file. For embedded JavaScript code, see the Client-side JavaScript information for instrumenting client-side code. Similarly,this does not cover external CSS files. While they are integrity-sensitive (CSS can contain active code and hence they are best retrieved over SSL), they rarely are confidentiality-sensitive and hence would reference only public objects not requiring any rewriting. If not, they would have to be manually instrumented using the manual server-side instrumentation steps described in the Server side section.

  • HTML <BASE> elements are only supported if they point to the same server, otherwise they are removed. If they were not removed, this would cause a security exposure.

  • If you are also using Active content filtering on the same resources, you need to manually merge the CSRF-protection configuration ${/config/dependencies/zero.acf}/config/acf-csrf-config.xml with the ACF rules into a private configuration file. See the Configuring ACF section of the Active content filtering article for more information.

  • To limit the scope of rewriting to only parts of your file (for example, to better contain the exposure of CSRF credentials) and not the whole file, use a custom rule file. Based on acf-csrf-config.xml or acf-csrf-safe-config.xml, create a new rule file in your config directory and add or remove items from the list of rewritten tags or attributes. You can also define a more restrictive <TARGET> element. To do this, see the Configuring ACF section of the Active content filtering article for more information.

  • Similar to ACF filtering, CSRF-rewriting can be applied to the body of authentication-induced redirects if the access to the rewritten resource causes authentication. However, this should be harmless.

Client-side JavaScript

For client-side JavaScript that uses the XHR methods provided by Dojo (versions 0.9 and 1.0), the HTML page should include the following scripts after loading dojo.js:

  • /zero/js/csrfBasic.js and
  • /zero/js/csrfDojo.js, .
All XHR methods are automatically instrumented for CSRF protection. If you enable server-side transparent protection mode, then the re-writer automatically and transparently detects when you load dojo and include the two script files.

HELP Note

  • Do not use <BASE> elements on pages including CSRF-instrumented JavaScript code. If you have to use them you must ensure that the corresponding href attribute points to the local server. Otherwise, your security is compromised.

  • The preceding wrapper does not handle dynamically created HTML elements (for example <script>, <img>, <iframe> or <form>). If they point to protected resources, you must manually instrument the code as described in the following information.

  • If you are using an AJAX framework other than dojo, you might achieve a similar transparent handling by applying the zeroClient.CSRFXhrWrapper.wrapXhr() function from the script /zero/js/csrfDojo.js similar to its use in zeroClient.CSRFXhrWrapper.wrapDojo().

Programmatic protection

The methods described in the previous section should suffice for typical programs and are fail-safe to use. However, the rewriting might not meet your performance goals if you create dynamic HTML elements pointing to protected resources or have CSS pointing to protected resources. In this case, use the programmatic methods described in this section.

The following methods are as fail-safe as possible. They determine automatically whether, for a given URI, a CSRF authenticator can be sent. That is, even if you accidentally pass a URL to a remote site (which at best could not make use of the authenticator and at worst might misuse it) the functions will not include the authenticator for such requests.

The following best practices can maximize your security:

  • JavaScript embedding is preferred over server-side embedding as this minimizes the exposure of the code credential.
  • There are three different ways to encode CSRF authenticators:
    1. HTTP Header
    2. Parameter in form
    3. URI query string
    Use them in this order of preference. If possible, attach the authenticator as an HTTP header and use URI query string encoding only as last resort as this can cause leaking the secret (in referer fields or in log-files) in proxy servers.

Server-side

The programmatic API on the server-side consists of the following functions:

Java
The API is provided by the class zero.core.security.CSRFProtector in the following methods:
public static boolean doIncludeProtection(java.net.URI uri)
public static java.lang.String getProtectionFormField(java.lang.String path)
public static java.lang.String getProtectionFormField(java.net.URI uri)
public static java.lang.String getProtectedUri(java.lang.String path)
public static java.net.URI getProtectedUri(java.net.URI uri)

See the JavaDoc for more information.

Groovy
The functions have the same semantics as the String versions of Java methods getProtectionFormField and getProtectedUri, respectively:
getCSRFProtectedUri (String uri)
getCSRFProtectionFormField (String uri)

PHP
The following code sample shows the PHP version:
csrf_protected_form_field (String uri)
csrf_protected_uri (String uri)

See the Using Project Zero Cross Site Request Forgery (CSRF) APIs programmatically section of the Additional PHP functions article for more information.

For example, to protect a form using Groovy, you might issue the following code:

<% formUri =  getRelativeUri("/resources/owners"+ '/' + request.subject['remoteUser'] + "/todos")  %>
<form method="POST" action="<%= formUri %>" >
<%= getCSRFProtectionFormField(formUri) %>
... further fields
<input type="submit" name=".submit" value="Post Form" />
</form>

Client-side JavaScript

For client-side JavaScript that does not exclusively use the XHR methods provided by Dojo, the APIs in /zero/js/csrfBasic.js can be used. The following functions can be called on the object zeroClient.CSRFBasic:

addCSRFTokenToHeader(/*String*/ url, /*XHR*/ xhr)
addCSRFTokenToForm(/*Form*/ form)
addCSRFTokenToURL(/*String*/ url)
removeCSRFTokenFromForm(/*Form*/ form)

The following low-level methods are available if you want to lookup and attach the CSRF token manually:

getCSRFParamName(/*String*/ param)
getCSRFHeaderName(/*String*/ header)
getCSRFTokenValue(/*String*/ token)

To issue a protected XHR call, you might write JavaScript code as shown in the following example:

function getTodosXHR() {
        var url = ownerURL + '/' + owner + '/todos';
        var req = new XMLHttpRequest();
        req.open('POST', url, false);
        zeroClient.CSRFBasic.addCSRFTokenToHeader(url, req);
        req.send();
}

Configuration

To enable CSRF protection, add /config/security/token/enableCsrfProtection=true to your zero.config file

As authentication from a user perspective rarely implies authorizing immediate destructive operations, implicit authentication on a CSRF-protected resource does not trigger the requested resource but returns a safe fallback page. This prevents CSRF-style attack on the integrity of user data (for example, in an email application a user could otherwise be tricked to delete all his email just by authenticating). The fallback can be specified assigning the property /config/security/token/csrfGlobalPostLoginFallback in your zero.config file with your desired fallback page.

If you enable CSRF protection, all your protected resources automatically require CSRF credentials on access. If you have to allow some protected resources to be accesses by code that because it can either not be instrumented to issue CSRF credentials for each request or because it is part of the login process where the user does not yet have CSRF credentials, you can mark resources with csrfProtect=false in the corresponding [@include ${zero.core}/config/security/rule.config] rule.

Note: Do this only for resources that do not cause server-side change and only for HTML files. For example, doing this on JSON resources can allow JavaScript Hijacking attacks.

Typically, you would apply this only to the HTML pages forming the entry point into the secure part of your application, containing only the application logic but not the confidential resources themselves.

Putting everything together, you might have a zero.config file, as shown in the following example, for securing the simpletodo application from the tutorial:

/config/security/token/enableCsrfProtection=true

# enable transparent rewriting on /todo.gt
@include "acf.config" {
   "uri":"/todo.gt",
   "filterRuleFile" : "${/config/dependencies/zero.acf}/config/acf-csrf-config.xml"
}

# Transparent authentication triggered by access to csrf-protected resources will generally fall back on below 
/config/security/token/csrfGlobalPostLoginFallback = "/todo.gt"

# ports
/config/http/port=8880
/config/https/port=8883

# SSL setup
/config/https/keyStore="config/myKeyStore.p12"
/config/https/keyStorePassword="passw0rd"
/config/https/keyStoreType="PKCS12"

# Authentication Method
myAuthType="Form"
@include "security/form.config"{
   "formLoginPage" : "/login/index.html"
}

# allow logouts
/config/handlers += [{
   "events" : "POST",
   "handler" : "zero.core.security.LogoutHandler.class",
   "conditions" : "/request/path =~ /logout"
}]

# todo.gt is the entry-page: We need an authenticated user but this page can be
# without CSRF-protection as it does not cause any server changes by
# itself and, being html, cannot be read by hijacked by code from a foreign domain
# Obviously, being sensitive, we require SSL.
@include "security/rule.config"{
   "conditions": "/request/path =~ todo.gt",
   "authType" : ${myAuthType}, 
   "groups" : ["ALL_AUTHENTICATED_USERS"],
   "csrfProtect" : false,
   "requireSSL" : true
}

# Security of resources is crucial: they have to be CSRF-protected
@include "security/rule.config"{
   "conditions": "/request/path =~/resources/.*",
   "authType" : ${myAuthType},
   "groups" : ["ALL_AUTHENTICATED_USERS"],
   "csrfProtect" : true,
   "requireSSL" : true
}

# Scripts such as dojo and CSS can be public but have to to be
# integrity-protected as they are active content, hence the SSL
# requirement 
@include "security/rule.config"{
   "conditions": "/request/path =~ .*.(js|css)",
   "requireSSL" : true
}

# Images of theme and from dojo are neither secret nor thaat
# integrity-sensitive. Hence allow public access
@include "security/rule.config"{
   "conditions": "/request/path =~ ((/zero/theme/|/dojo/|/dijit/).*.(jpg|png|gif)|/favicon.ico)",
   "requireSSL" : false
}

# Finally a secure catchall for the rest to be on the safe side ...
@include "security/rule.config"{
   "conditions": "/request/path =~ .*",
   "authType" : ${myAuthType},
   "groups" : ["ALL_AUTHENTICATED_USERS"],
   "csrfProtect" : true
}

## derby embedded
/config/db/simpletodo = {
  "class" : "org.apache.derby.jdbc.EmbeddedDataSource",
  "databaseName" : "./db/todos.db", 
   "connectionAttributes" :"create=true"
 }

Best practices

The following list of best practices can maximize the security of your application:

  • Minimize the use of resources with csrfProtect=false and use this only for HTML pages that have entry pages securing parts of the application.

  • Minimize the HTML pages that contain confidential information or trigger server-side state changes and hence must be (CSRF-) protected. HTML pages should contain only the application code and retrieve confidential data and cause critical server-side state-change only using XHR. This reduces the need for URI query string encoded CSRF-authenticators that easily leak on HTML pages, for example through HTTP Referer fields.

  • If possible, load CSRF-protected HTML pages using client-side instrumentation based on the header encoding. Server-side instrumentation would have to rely on URI query string encoded CSRF-authenticators and induce a high risk to leak the code credentials, for example through HTTP Referer fields.

  • Use the URI-encoding only on resources that you know do not contain references to (untrusted) foreign domains as this will cause the leakage of the CSRF credential. For example, apply the server-side re-writer with the acf-csrf-config.xml rule only on a page that does not contain <A>, <IFRAME>, <FRAME> or <FRAMESET> elements pointing to a resource on your server which in turn references a foreign resources, for example a <IMG&gt;.

Limitations

  • The CSRF protection is currently limited to a single site. It does not support clustering nor does it protect requests among a realm of different servers, for example, unified behind a reverse proxy.

r24 - 06 Feb 2008 - 16:58:27 - paynel
Syndicate this site RSS ATOM
Copyright 2007 © IBM Corporation | Privacy | Terms of Use | About this site