« Previous - Version 13/16 (diff) - Next » - Current version
Sebastian Kurfuerst, 2012-03-22 10:03


Extbase / FLOW3 Security Cookbook

While the Extbase and FLOW3 frameworks take a lot of burden off the developer's
shoulders when it comes to security, the developer needs to be aware at which
points the Extbase / FLOW3 security measures are automatically working, and when
he needs to care about security himself.

This document is meant as a guideline for secure extension programming based on
Extbase, and for programming secure FLOW3 packages.

Hint: Extbase and FLOW3 are very similar in some areas like the MVC stack, that's why most of this guide applies to FLOW3 as well.

In A Nutshell

If you are in a hurry, read at least these basic guidelines:

  • You need to validate the parameters of $query->setOrderings() yourself.
  • If an object has some properties which shall be only modified by a specific
    user group, you need to secure access yourself, possibly by writing a custom TypeConverter.
    Do not assume that only the properties specified inside a Fluid form are updated.
  • When writing your own ViewHelpers, you need to take care of properly escaping input values.

Basic Security Principles

The most basic principle for programming secure extensions is to never trust the
user input
. All input values which are received from the user can be potentially
dangerous. This includes GET/POST variables, but also cookies or HTTP headers.

SQL Injection

Hint: This section only applies to Extbase.

Extbase Query Building: Secure

If you build queries inside your repository using the Query Object Model, like below,
you are protected by SQL injections automatically, as Extbase escapes the untrusted values
properly:

1 $query->matching(
2   $query->equals('foo.bar', $untrustedValue)
3 );

Query->setOrderings()

However, this does not apply to the $query->setOrderings() method, so the following code
is potentially insecure:

1 $query->setOrderings(array(
2   $untrustedValue => ...ASCENDING
3 ));

You need to validate the parameters of $query->setOrderings() yourself.

Note: We cannot easily fix this in Extbase, as some people run complex ordering queries, involving aggregate functions such as MAX or MIN inside an order query. Furthermore, Extbase does not know the definitive list of all possible columns of a database table.

Query->statement()

If you use $query->statement() to write a custom SQL query, you should use the prepared statement
feature, as the value can then be properly escaped:

1 $query->statement('SELECT * FROM ... WHERE foo=?', array($untrustedValue));

Mass Assignment in Property Mapping

Hint: This section applies to Extbase when features.rewrittenPropertyMapper is enabled and FLOW3.

Extbase and FLOW3 makes working with objects really easy. One integral part of this is that it automatically
converts simple types into objects
inside the MVC layer. An example shall demonstrate this. Imagine the
following action of a controller:

1 public function updateAction(Tx_Blog_Domain_Model_Blog $blog) {
2   // now, do something with the $blog object
3 }

Now, Extbase automatically transforms the incoming data into an object. The details of this process
are described in the FLOW3 Manual, and also apply to Extbase

In a nutshell, all properties of the top level object can be modified by default, and permissions
are always processed on a whole-object level. For our update action from above this means that the
following input is all processed:

1 blog=17             # Simple case, blog with UID 17 is fetched, no updates occur
2 blog[__identity]=17 # same as above
3 blog[__identity]=17&blog[name]=Foo # Blog with ID 17 is fetched, and the *name* property is updated on it.

Now, if the blog has a property (f.e. $superPowers) which shall be only modified by a specific user group, you need to
take care of this yourself, probably by writing a custom TypeConverter

Now, imagine the blog has an owner which is of type FrontendUser. It is possible to change the owner by sending the following data:

1 blog[__identity]=17&blog[owner]=81

However, it is, by default not possible to update nested objects, i.e. the following intrusion attempt will result in an exception:

1 blog[__identity]=17&blog[owner][isAdmin]=1 # we're trying to set the ADMIN flag on the owning user, but we fail

The important bit to remember: Property Mapping is done on an object level.

Hint: In FLOW3, you can use the Security Framework to make partial updates of objects possible.

Preventing Cross-Site Scripting

Hint: This section applies to Extbase and FLOW3.

When outputting user data,