jump to navigation

MySecurity Component August 23, 2006

Posted by rossoft in CakePHP.
trackback

Some tricks for extra security in cake.

If you call http://example.com/users/render/delete (you’ve an UsersController) you will get rendered the delete.thtml view.
Try it at home with any controller.
The render() method from Controller gets called. I’m not sure if something dangerous can be done, but some other functions can be called like redirect. For forbidding all the methods from Controller base class, use this component.

<?php
/**
 * MySecurity.php
 * Some security things for Cake
 *
 * Features:
 * – The public functions from controller & object now can’t be called from url
 * –
 *
 * @author RosSoft
 * @version 0.1
 * @license MIT
 *
 * @package components
 */

class MySecurityComponent extends Object
{
    var $components=array(‘Security’);

    /**
     * Extra forbidden actions
     *
     * @var array $forbidden_actions
     */
    var $forbidden_actions=array();

    function startup(&$controller)
    {
        $this->forbidden_actions=am($this->forbidden_actions, get_class_methods(‘Controller’));

        $this->Security->startup($controller);
        if (in_array($controller->action,$this->forbidden_actions))
        {
            $this->Security->blackHoleCallback=null;
            $this->Security->blackHole($this);
        }
    }
}
?>

Advertisements

Comments»

1. Nao - August 25, 2006

Hi Miguel,

Just a suggestion to prevent custom method in appController or in FixController (for FlexyFix).

function startup(&$controller)
{
$this->forbidden_actions = am($this->forbidden_actions, get_class_methods(get_parent_class($controller)));

2. nao - August 25, 2006

function startup(&$controller)
{
$this->forbidden_actions = array_unique(am($this->forbidden_actions, get_class_methods(get_parent_class($controller))));
if(!empty($controller->alowedActions)){
$this->alowActions($controller->alowedActions);
}
if(!empty($controller->forbiddenActions)){
$this->forbiddenActions($controller->forbiddenActions);
}
…….
}

function alowActions($alowedActions)
{
$this->forbidden_actions = array_diff($this->forbidden_actions, $alowedActions);
}

function forbiddenAction($forbiddenAction)
{
$this->forbidden_actions = array_unique(am($this->forbidden_actions, $forbiddenAction));
}

(not tested)

3. Jitka - October 2, 2006

I think Your code is supposed to be in CakePHP core.

I can imagine websites with usage of admin routes and some simple session-based authorization in beforeFilter(). Then explore implementation of Controller::setAction() – what will happen when someone non-authorized opens
http://your_server/users/setAction/admin_index/
or even
http://your_server/users/setAction/admin_delete/2/

???

Again:
I think Your code is supposed to be in CakePHP core.

Have a nice day!

4. max - October 8, 2006

I guess views can’t perform any model-desructive actions, because this is controller by, well, controller. This probably is the reason that plain $data is exported to the view, not the corresponding Model children. So rendering /admin_delete won’t cause much trouble, but what’s more F#cked up is that using this ‘exploit’ one can render any file in the webroot dir. The only thing that saves CakePhp from full-scale priviledged documents theft is that one can’t use “/” in the document name and thus can’t browse neither config/ nor /etc/passwd or whatever. But! Maybe it is possible with replacing “/” with its UTF correspondant – I’m not sure that all webservers handle this correctly, because there were some relevant issues not so long ago – and CakePhp simple preg_split will then pass all the path to the $action. Another similar possibly bad method is “redirect”, because if it is possible to pass UTF ‘/’, then it will be possible to use your CakePHP dispatcher as anonymous proxy.

Vote for putting this check into Dispatcher, but for now I use following in my AppController::beforeFilter().


function _checkCanInvokeAction()
{
// for f$cking cakeError - or else it recursively creates-starts AppController
if (empty($this->params['action'])) return;

// there are NO actions in the Controller, period!
// thus any overriden method in children classes (like redirect in AppController or such)
// can't be called from outside no matter that

$classMethods = get_class_methods($this); echo ss_as_string($classMethods); exit;
$classMethodsBase = get_class_methods("Controller");

if (!in_array(strtolower($this->params['action']), $classMethods))
{
Debug::log(__FILE__,__LINE__, "SECURITY: ".$_SERVER["REMOTE_ADDR"]." tried to access non-existant action '".$this->params['action']."'");
return $this->cakeError('missingAction', array(
array('className' => Inflector::camelize($this->params['controller']."Controller"),
'action' => $this->params['action'],
'webroot' => $this->webroot,
'url' => $this->here,
'base' => $this->base)));
}

if (in_array(strtolower($this->params['action']), $classMethodsBase))
{
Debug::log(__FILE__,__LINE__, "SECURITY: ".$_SERVER["REMOTE_ADDR"]." tried to access private action '".$this->params['action']."'");
return $this->cakeError('privateAction', array(
array('className' => Inflector::camelize($this->params['controller']."Controller"),
'action' => $this->params['action'],
'webroot' => $this->webroot,
'url' => $this->here,
'base' => $this->base)));
}
}

5. max - October 8, 2006

2 nao:
$this->forbidden_actions = array_unique(am($this->forbidden_actions, get_class_methods(get_parent_class($controller))));

This is not very scalable solution. I prefer to get base list of forbidden methods directly from ‘Controller’ class, because for better code reuse one can have more then one level of hierarchy, e.g. class MyController extends GenericTableController extends AppController. All other non-action method must start with ‘_’ and that’s enough.

Without similar security code, badguy can use following nice hack.
http://your_server/cake/anycontroller/render/.htaccess – renders .htaccess from cake’s /app dir, which can have valuable info.

6. rossoft - October 8, 2006

@max: thanks for your posts.

I think that rendering arbitrary views are dangerours: some views can contain sensitive information hard-coded in the .thtml file that only must be shown to certain users.

7. Bret Kuhns - January 21, 2008

Just in case anyone finds this post from google (like I did), I wanted to make note that this flaw seems to have been fixed in newer builds of cakePHP. I tested /controller/render/viewName on an active cakePHP app of mine and the missing action error was called.

8. webroot - June 18, 2009

webroot…

Howdy , your most important Grandparenting 101: Chat Rooms, Chat Definitions | Be a Web Safe Kid was quite engaging when I saw it on Thursday searching for webroot….


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: