Security

From Cloudrexx Development Wiki
Jump to: navigation, search

Introduction

Due to its nature, the internet is per se an insecure environment. Web applications are exposed to a wide range of possible security attacks. Therefore, when developing web applications there are many security considerations that have to be taken into account to prevent any (known) security flaws.

Contrexx provides a set of functions to deal with common security flaws like Cross-site scripting, SQL-Injection and Cross-site request forgery.

Important: This article is not meant as a replacement for the study of web application security, but shall show how common security flaws can be prevented when developing in Contrexx! See http://en.wikipedia.org/wiki/Web_application_security

Contrexx Input / Output Handling

Contrexx Input / Output Handling


Reading data (Input)

When reading data from a request ($_GET/$_POST/$_REQUEST), the data must be converted into its raw form before it can be further used in the program logic. This can be achieved by using the function contrexx_input2raw():

// convert input to its raw representation
$foo = contrexx_input2raw($_GET['foo']);

Cross-site scripting (XSS)

See http://en.wikipedia.org/wiki/Cross-site_scripting for detailed information about XSS.

To prevent cross-site scripting flaws in the application, all user generated content must be escaped into its HTML-representation.

// escape user generated content before sending it to the browser
echo contrexx_raw2xhtml($foo);

SQL-Injection

See SQL Injection @ OWASP for detailed information about SQL-Injection.

To prevent SQL-Injections all data passed to the database must be escaped. For legacy SQL-queries it is best to use the Bind Variables feature of the database abstraction layer ADOdb to ensure all data passed to the database is properly escaped. E.g.:

$db = $this->cx->getDb()->getAdoDb();
$db->Execute(
    'INSERT INTO `' . DBPREFIX . 'test` (`foo`) VALUES (?)',
    $data
);
Deprecated:

Alternatively, if Bind Variables is not an option (which it theoretically never is) and data is directly inserted into the SQL-statement, then the raw data must be escaped using the function contrexx_raw2db():

$db = $this->cx->getDb()->getAdoDb();
$db->Execute(
    "INSERT INTO `" . DBPREFIX . "test` (`foo`) VALUES ('" . contrexx_raw2db($data) . "')"
);


Note: When working with Doctrine models the input sanitation (escaping) is taken care of by the Doctrine ORM. No manual escaping has to be done is such case.

Cross-site request forgery (CSRF)

CSRF Protection Message

See http://en.wikipedia.org/wiki/Cross-site_request_forgery for detailed information about CSRF.

Every request to the backend is protected with a CSRF-Token. Meaning that every request to the backend fails if no or an invalid CSRF-Token had been supplied. Requests blocked by the CSRF protection system result in the error message shown in the right box.

Contrexx automatically adds a CSRF-token to the following HTML-tags (see url_rewriter.tags in config/configuration.php and \Cx\Core\Csrf\Controller\Csrf::setFrontendMode() in lib/CSRF.php):

HTML-Tag Attribute * Frontend Backend
form x x
fieldset x x
a href x
area href x x
frame src x x
iframe src x x
input src x x

* only HTML-tags using the specified attribute will be enhanced with a CSRF-token


So basically, you won't have to bother about making a HTML-form or anchor-tag working with the CSRF protection system.

Though, when working with dynamic URLs (i.e. inside the scope of JavaScript) you will have to manually supply a CSRF-token to the HTTP-request (URL). See next subsection on how to do this.


GET versus POST

The current implementation of the Contrexx CSRF Protection System does not distinguish between GET- and POST-HTTP-Requests. That means that not only all POST-HTTP-Requests are verified of having supplied a valid CSRF-token, but also all GET-HTTP-Requests. This is a huge usability flaw, because it often causes non-action requests (regular browsing) to be reported as false-positives by the CSRF protection system.

When implementing/handling a HTTP-Request, you shall follow the following guidelines:

  • GET: All read-only operations are implemented using a GET-HTTP-Request
  • POST: All modifications (add/update/delete) are implemented using a POST-HTTP-Request

By applying these two simple rules, the Contrexx CSRF Protection System could be reduced to HTTP-POST-Requests, because we would no longer have to expect receiving any harmful requests over a HTTP-GET-Request. This would eliminate the huge usability flaw of false-positives as we have explained above.

Enhance JavaScript requests

Regular links created using Javascripts are not automatically enhanced by a CSRF-token and must therefore be enhanced manually.

Note: This shall not be confused with AJAX-requests (XMLHttpRequest) where the usage of CSRF-tokens is not required.

There are two ways to get this job done:

Using Contrexx JavaScript Framework (cxjs)

You can use the Contrexx_Javascript_Framework by activating cxjs in PHP:

// activate cxjs (only needed frontend)
\JS::activate('cx');

Then you can access a CSRF-token through cx.variables.get('csrf', 'contrexx'):

// add CSRF-token to URL
window.location.href =  'index.php?cmd=access&act=delete&csrf=' + cx.variables.get('csrf', 'contrexx');

Using Template System

You can use the template system by putting the CSRF-token globally into the placeholder {CSRF_PARAM} (you would usually place this call in the constructor of your Contrexx module)

// add global placeholder {CSRF_PARAM} to template-object $objTemplate
\Cx\Core\Csrf\Controller\Csrf::add_placeholder($objTemplate);

Add CSRF-token to your JavaScript code:

<script type="text/javascript">
# CSRF enabled location redirect
window.location.href =  'index.php?cmd=access&act=delete&{CSRF_PARAM}';
</script>

Enhance HTTP-Redirects

To enhance a HTTP Location redirection with a CSRF-token you can use the method CSRF::redirect():

// CSRF enabled HTTP-Redirect response
\Cx\Core\Csrf\Controller\Csrf::redirect("/cadmin/index.php?cmd=access");