views:

526

answers:

7

Hi,

I have an application which makes decisions based on part of URL:

    if ( isset($this->params['url']['url']) ) {
    $url = $this->params['url']['url'];
    $url = explode('/',$url);
    $id = $this->Provider->getProviderID($url[0]);

    $this->providerName = $url[0]; //set the provider name

    return $id;

    }

This happens to be in a cake app so $this->params['url'] contains an element of URL. I then use the element of the URL so decide which data to use in the rest of my app. My question is...

whats the best way to secure this input so that people can't pass in anything nasty?

thanks,

A: 

Please define "anything nasty". Anything a Regex won't get?

Karsten
+1  A: 

What are valid provider names? Test if the URL parameter is one, otherwise reject it.

Hopefully you're aware that there is absolutely no way to prevent the user from submitting absolutely anything, including provider names they're not supposed to use.

Michael Borgwardt
+1  A: 

I'd re-iterate Karsten's comment: define "anything nasty"

What are you expecting the parameter to be? If you're expecting it to be a URL, use a regex to validate URLs. If you're expecting an integer, cast it to an integer. Same goes for a float, boolean, etc.

These PHP functions might be helpful though: www.php.net/strip_tags www.php.net/ctype_alpha

Keith Palmer
+1  A: 

the parameter will be a providername - alphanumeric string. i think the answer is basically to to use ctype_alpha() in combination with a check that the providername is a valid one, based on other application logic.

thanks for the replies

codecowboy
Don't forget to do a mysql_real_escape_string also.
Click Upvote
Or use PDO objects for newer versions
Joe Philllips
A: 

Also, if you have a known set of allowable URLs, a good idea is to whitelist those allowed URLs. You could even do that dynamically by having a DB table that contains the allowed URLs -- pull that from the database, make a comparison to the URL parameter passed. Alternatively, you could whitelist patterns (say you have allowed domains that can be passed, but the rest of the url changes... You can whitelist the domain and/ or use regexps to determine validity).

At the very least, make sure you use strip_tags, or the built-in mysql escape sequences (if using PHP5, parameterizing your SQL queries solves these problems).

Travis Leleu
+1  A: 

Other comments here are correct, in AppController's beforeFilter validate the provider against the providers in your db.

However, if all URLs should be prefixed with a provider string, you are going about extracting it from the URL the wrong way by looking in $this->params['url'].

This kind of problem is exactly what the router class, and it's ability to pass params to an action is for. Check out the manual page in the cookbook http://book.cakephp.org/view/46/Routes-Configuration. You might try something like:

Router::connect('/:provider/:controller/:action');

You'll also see in the manual the ability to validate the provider param in the route itself by a regex - if you have a small definite list of known providers, you can hard code these in the route regex.

By setting up a route that captures this part of the URL it becomes instantly available in $this->params['provider'], but even better than that is the fact that the html helper link() method automatically builds correctly formatted URLs, e.g.

$html->link('label', array(
  'controller' => 'xxx',
  'action' => 'yyy',
  'provider' => 'zzz'
));

This returns a link like /zzz/xxx/yyy

neilcrookes
A: 

It would be more cake-like to use the Sanitize class. In this case Sanitize::escape() or Sanitize::paranoid() seem appropriate.

dr Hannibal Lecter