Security model

Wednesday, June 9th, 2010|Brainstorming, Version 4|by Romans

Some discussions prompted me to focus on security goals of ATK4. This post is about how we are approaching security and human-factor as well as flexibility in dealing with external systems.

External systems

This approach was influenced by some ideas behind ESAPI and Security Ninja from Realex Payments.

The general idea is that your application interacts with different external systems. Potentially all of those systems are faulty and cannot be trusted. One system may be used to hack another external system.

Developers cannot be trusted as well, there is a human factor that some data will not be validated or escaped and therefore cannot be relied upon.

Final concept is “being secure by default”, which should allow developers do 80% of functionality in an very easy way, with minimum implications. We shouldn’t make security into an obstacle.

Below are the list of our current external systems:

  • HTML and Templates (curated by SMlite)
  • SQL (RDBMS) (curated by DBlite)
  • Mail-outs (curated by SMlite)
  • JavaScript and jQuery (curated by jUI)
  • POST (curated by Form)
  • GET data (not curated)
  • Local filesystem (not curated)
  • Executables (curated by ProcessIO)
  • Other APIs (PayPal, Payments, etc curated by individual controllers)
  • Potential
    • Cloud storages (SimpleDB, S3)

Curated vs Not Curated

ATK may decide not to intervene with the external components, so it’s up to the user to do the validation. This is what happens,

$id=(int)$_GET['id']

However not always check will be in place. Potentially we might have $id a value which we do not expect to be there, such as very—very long or crafted/corrupted UTF-8 string.

We see each external system equally dangerous. So adding _GET validation is not solving problem with SQL injection.

Security vs Sanity

Some systems take a great lengths to formally define all interaction by either severely restricting functionality (narrow down powerful SQL engine into GDB-like backend) or introducing insane definitions for each interaction type. I have seen projects where all the SQL queries would be listed in a single file and rest of the system could only specify parameters for those.

  1. Projects needs quick draft version.
  2. Developer decides not to use complicated security filters and add them later, when more time/budget is available.
  3. Due to human factor security features are not going to be enabled later.

Bearing in mind that “Write Less do more” is a very important goal for ATK, we need to find a good defaults which are both secure, simple and usable in 80% cases.

Agile Toolkit 4 Strategy

We aim to “lure” developers into using our Curating classes by offering some benefits. For example with Forms – we offer to automatically collect data from POST data based on the fields defined. When user accesses $form->get(‘field’), then it’s already properly validated.

With SQL we offer a dynamic-query syntax (some may call it query builder. It is, but not for much longer). It’s just as quick to write as a regular statements, but it is integrated throughout the system and ignoring this layer completely is impossible.

Finally with JavaScript we introduce a framework which greatly helps with effects and function integration. It takes care of object ID’s, includes and events and in addition it acts as a great security filter.

We still have no filter for $_GET, because there is no way to provide any benefit to developer. $id=$_GET['id'] is the easiest you can write, and even if we create filter, it might not become a standard for developers. Regardless, we are going to introduce one. We simply are thinking of a way how to not get into the way of developer.

Objects

Abstraction of javascript events, SQL requests and HTML templates is a great way to provide power through an object-oriented interface. For instance when you write the following:

$title=" ');alert(123);void(' ";

// $title='<script>alert(321)</script>';

$this->js('click')->univ()->dialogURL($title,$url);

argument to the function is properly converted and escaped to make sure it causes no harm to the JavaScript layers. Developer didn’t intend to call alert function here and there should be no way how to do it through the injection.

There are still ways to get around it $this->js(‘click’,'alert(123)’); – but as long as developer is cautious not to use this without necessity application consistency is safe.

http://atk4.wordpress.com/2010/04/26/how-js-layer-works-in-atk/

The same thing approach is taken in new DSQL implementation. Previously it was possible to sneak pieces of SQL into statements such as :

$dq->set(‘name=md5(name)’); , which could potentially end up as $dq->set(‘name=’.$enc_func.’(name)’); From here – all attacker needs to do is to get SQL into $enc_func.

New approach introduces a different approach:

$dq->set(‘name’,$dq->expr(‘md5′,$dq->getField(‘name’)));

It is not that much longer to write, but as you automate it:

$dq->set($field1,$dq->expr($enc_func,$dq->getField($field2)));

even if hacker can inject SQL in all 3 variables, they will not make it through into the select and will be sanitized or will cause exception. Also regardless of what you have in $field2 (string), you can’t force it to look into a new table or use sub-select. There are however constructions developers can use to implement any of those – if that is what is intended.

Template output

We have nothing against developers using HTML here and there in the PHP code. A most trivial example is taking HTML out from the database/CMS and putting it into the template on the frontend. However in some cases $this->add(‘Text’)->set(‘<h1>hello world</h1>’) is used.

Developers wish to have a quick way to drop some markup into the templates. However it becomes dangerous if something like this occur:

$this->add(‘Text’)->set(‘<h1>Hello, ‘.$name.’</h1>’);

We do want to let developers play with the markup, but we want to do it in a curated way. Recently added object “HTMLElement” is step in the right direction. You can do the following:

$this->add(‘View_HTMLElement’)->useElement(‘h1′)->addClass(‘my-header’)->set(‘Hello’);

and this would do what it seems it will. However all the arguments should be validated not to accidentally inject anything bad into the code.

(this part of the system still needs some work to match security standards, and it will be done before 4.0 release)

Third-party APIs

As we get more and more third-party APIs to deal with, we also aim to set the good standards and patterns they can use to fully curate Input and Output from their modules. What happens if you use PayPal backend and paypal returns unexpected output? Could it potentially result in SQL injection? But what if output is passed to a command-line?

What is checked

You can see which version was first to support the check. 2.0 was released around 2003. 3.0 was out since 2006. 3.6 was in use in 2009 and 3.8 is in use since 2010.

  • HTML and Templates (curated by SMlite)
    • [4.0] check to make sure set() can only set text. use setHtml() if you need to pass markup (but not <script>)
    • [2.0] make sure user can’t inject tags into template
    • [2.0] make sure template file (which comes from filesystem or database) cannot execute functions on it’s own
  • SQL (RDBMS) (curated by DBlite)
    • [3.0] properly escape arguments to set() and where(), having();
    • [3.9] validate field names and lock fields to tables in set(), where(), join(), having(), etc.
    • [3.0] validate limit()
    • [3.9] introduce expression support and curation.
    • [3.9] support sub-select curation.
  • Mail-outs (curated by SMlite)
    • [3.2] same rules as with templates
    • [4.0] separate text from html and javascript.
  • JavaScript and jQuery (curated by jUI)
    • [3.7] event handling
    • [3.7] execution chains
  • POST (curated by Form)
    • [2.0] form data processing
    • [4.0] manual direct access to POST data
  • GET data (not curated)
    • [4.0] manual direct access to _GET
    • [3.0] usage in conjunction with other objects such as Form::addConditionFromGET()
  • Local filesystem (not curated)
    • [3.8] path and URL abstraction, include paths
    • [3.8] packages
  • Executables (curated by ProcessIO)
    • [3.5] process execution and IO controll
  • Other APIs (PayPal, Payments, etc curated by individual controllers)
  • Potential
    • [4.0+] Cloud storages (SimpleDB, S3)