ZF-12467: Invalid controller name specified into request

Description

If user makes a mistake on accidentally enters incorrect controller, it is set into request as-is in Zend_Controller_Router_Rewrite::_setRequestParams(). However, in Zend_Controller_Dispatcher_Abstract::_formatName() there is a preg_replace('/[^a-z0-9 ]/', '') when forming the controller name.

Now, in my code I cannot rely that controller name has been properly filtered, nor what the class name ended up to be!

I'm currently studying the implications of rejecting illegal controller names or alternatively, silently accepting the filtering result.

Comments

I ended up inheriting my own Controller_Router_Rewrite. The only thing I'm doing there is:

 
    /**
     * Set module, controller and action to request
     * Confirm that they are sane
     */
    protected function _setRequestParams($request, $params)
    {
        parent::_setRequestParams($request, $params);

        if (!preg_match('/^[a-z0-9 ]+$/', strtolower($request->getModuleName()))) {
            require_once 'Zend/Controller/Router/Exception.php';
            throw new Zend_Controller_Router_Exception('Badly formatted module: ' . $request->getModuleName(), 412);
        }
        if (!preg_match('/^[a-z0-9 ]+$/', strtolower($request->getControllerName()))) {
            require_once 'Zend/Controller/Router/Exception.php';
            throw new Zend_Controller_Router_Exception('Badly formatted controller: ' . $request->getControllerName(), 412);
        }
        if (!preg_match('/^[a-z0-9 ]+$/', strtolower($request->getActionName()))) {
            require_once 'Zend/Controller/Router/Exception.php';
            throw new Zend_Controller_Router_Exception('Badly formatted action: ' . $request->getActionName(), 412);
        }
    }

This won't be changed in the core of ZF as extending the class as noted in the comments is a good workaround for anyone who needs this functionality .

Let's think this for a second. I'll present a really stupid example, but bear with me.

Assume that somebody using Windows would define a controller in filename PrintglobalspasswordController.php like this:

global $password;
$password = "reallysecret123";

class PrintglobalspasswordController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $cntr = $this->getRequest()->getControllerName();
        $PrintglobalspasswordController = "not this";
        print eval($cntr);
    }
}

I'm the first one to state, that if anyone would write such a code, he would be a total dumbass. Also I'd say that the code would not work. But I've seen really wonderful things happen (and written).

You would see some sort of runtime error when accessing: http://myserver.com/fi/printglobalspassword

But guess what happens when user accesses it like this: http://myserver.com/fi/print $GLOBALS["password"];

Yep. You guessed it!

My scenario is really far fetched and very stupid, but the way I run my business, I choose to sanitize user input. Period. Looks like at Zend you really don't care.

That's sad. I really thought that you are professionals there.

I can't see how this theoretical attack could ever work as if you go to http://myserver.com/fi/print $GLOBALS["password"]; then you get an exception of:

Invalid controller specified (print%20$GLOBALS%5B%22password%22%5D;)

which means that any code in the PrintglobalspasswordController class wouldn't run.

What I'm saying is that I don't think that there's actually a possibly security issue here due to the way the router and dispatcher work. If you have a working proof of concept, please email zf-security@zend.com.

That error is actually:

```

Sir, you're correct. But only if you did not touch routing. Out-of-the-box the only router is a Zend_Controller_Router_Route_Module which seems to do urlencoding for it's parameters.

In my case app, I don't have the luxury of using solely module-routes. There are a number of Zend_Controller_Router_Route routes which don't sanitize or encode input strings. Which is pretty much my point.