Does PHP's $_Request Method Have a Security Problem

What's wrong with using $_REQUEST[]?

There's absolutely nothing wrong with taking input from both $_GET and $_POST in a combined way. In fact that's what you almost always want to do:

  • for a plain idempotent request usually submitted via GET, there's the possibility the amount of data you want won't fit in a URL so it has be mutated to a POST request instead as a practical matter.

  • for a request that has a real effect, you have to check that it's submitted by the POST method. But the way to do that is to check $_SERVER['REQUEST_METHOD'] explicitly, not rely on $_POST being empty for a GET. And anyway if the method is POST, you still might want to take some query parameters out of the URL.

No, the problem with $_REQUEST is nothing to do with conflating GET and POST parameters. It's that it also, by default, includes $_COOKIE. And cookies really aren't like form submission parameters at all: you almost never want to treat them as the same thing.

If you accidentally get a cookie set on your site with the same name as one of your form parameters, then the forms that rely on that parameter will mysteriously stop working properly due to cookie values overriding the expected parameters. This is very easy to do if you have multiple apps on the same site, and can be very hard to debug when you have just a couple of users with old cookies you don't use any more hanging around and breaking the forms in ways no-one else can reproduce.

You can change this behaviour to the much more sensible GP (no C) order with the request_order config in PHP 5.3. Where this is not possible, I personally would avoid $_REQUEST and, if I needed a combined GET+POST array, create it manually.

Is it wrong to use $_REQUEST for Data?

In "good" coding practice, you want to disambiguate as much as possible.

Since $_REQUEST contains the data from $_POST, $_GET, and $_COOKIE by default, the value held by the variable that stores the data retrieved using $_REQUEST will be ambiguous as to which method it came from.

If we are more specific, it will benefit readability of code, as well as understanding of logic, and helps for debugging in the future.

(Let alone the security issues concerning each method, especially the $_GET one)

Why should I use $_GET and $_POST instead of $_REQUEST?

I use $_REQUEST when I just want certain data from the user to return certain data.

Never use $_REQUEST when the request will have side effects. Requests that produce side effects should be POST (for semantic reasons, and also because of basic CSRF stuff, a false img tag can hit any GET endpoint without a user even knowing).

$_GET should be used when GETing or POSTing to a page will produce different results.

Among $_REQUEST, $_GET and $_POST which one is the fastest?

$_REQUEST, by default, contains the contents of $_GET, $_POST and $_COOKIE.

But it's only a default, which depends on variables_order ; and not sure you want to work with cookies.

If I had to choose, I would probably not use $_REQUEST, and I would choose $_GET or $_POST -- depending on what my application should do (i.e. one or the other, but not both) : generally speaking :

  • You should use $_GET when someone is requesting data from your application.
  • And you should use $_POST when someone is pushing (inserting or updating ; or deleting) data to your application.

Either way, there will not be much of a difference about performances : the difference will be negligible, compared to what the rest of your script will do.

Security Risk? $_REQUEST variables ... $$ on the local stack

This is like turning back 6 years of PHP security enhancements... Basically, register_globals and magic_quotes put together! Those two are marked deprecated in recent versions of PHP, and will be removed from future versions, for very good reasons.

Imagine the following code:

if ($is_admin) {
do_administrative_task();
}

Now somebody makes the following request:

http://www.example.com/script.php?is_admin=1

And just like that, you're admin!

Likewise, addslashes() doesn't really provide any protections against SQL injection attacks, because it doesn't understand modern character sets. It's ridiculously easy to craft something that will bypass addslashes() and pwn your database.

Should my framework allow access to $_GET and $_POST at the same time?

Yes!

I think you must allow access to both $_GET and $_POST at the same time. And I don't think you can just merge them together either. (You can have the option to, like PHP and the ill concieved $_REQUEST.) You could get a request like:

POST /validator?type=strict HTTP/1.1

type=html/text
body=<h1>Hello World</h1>

Note that the variable name type is used twice, but in different scopes! (Once in the URI defining the resource that should handle the POST, and then in the posted entity itself.) In PHP this looks like:

$_GET => ('type' => 'strict')
$_POST => ('type' => 'html/text', 'body' => '<H1>Hellow World</h1>')

PHP:s way of just parsing the URI and putting the parameters there into $_GET is somewhat confusing. A URI is used with most (all?) of the HTTP methods, like POST, GET, PUT, DELETE etc. (Not just GET, like PHP would have you believe.) Maybe you could be revolutionary and use some of your own lingo:

$a = $this->uri('name');//param passed in the URI (same as PHP:s $_GET)
$b = $this->entity('body');//var passed in an entity (same as PHP:s $_POST)
$c = $this->method(); //The HTTP method in question ('GET', 'POST' etc.)

And maybe even some utility functions:

if($this->isGET()){
...
}elseif($this->isPOST()){
...
)

I know, wild and crazy :)

Good luck and have fun!

cheers!

Is this a good method of ensuring $_REQUEST data is safe?

Basically, there is exactly one thing that you need to look out for: when you issue a command to an external system, you have to make sure that the command means exactly what you think it means.

If you are programming in PHP, you frequently deal with two external systems:

  1. the web browser to wich you send your HTML,
  2. the database where you store data.

For point 1, filter data that comes from the database through htmlspecialchars(). There are cases when you don't want to do this, but in those cases you have to know exactly why this does not compromise the security of your users.

For point 2, use prepared statements to insert and update database records. For new code, there are no exceptions, regardless of where the data is comming from. For old code, that uses interfaces that do not support prepared statements, use something like mysql_real_escape_string() to prepare values for inserting into or updating the database; again, regardless of where the data is comming from.

These two points are technical requirements (i.e. they are imposed by the technology that you are using). Additionally, there might be business requirements (like a credit card number being valid, a birthdate beeing before Aug 30th, 1995, a venue can only be booked for up to 7 days, whatever). Technical requirements and business requirements change at different rates, so you should handle them in different components. Don't mix preparing data to be technically fit for insertion into the database with validating whether the data meets your business needs.

Applying this to your special scenario, it seems that in Script1.php, you want to use some data in the query string of a URL in a HTML document. That's what urlencode() is for. In Script2.php, the browser has sent you data that you want to sent back to the browser. This is usually not critical for your or your users security. Still, the data must be passed through htmlspecialchars, because if the user sends </input> as $_REQUEST['reason'] it will confuse the user. It is not clear, what you intend with strlen and pack; don't do that, it serves no purpose other than to confuse fellow developers (which is bad), users (which is also bad) and potential attackers (which they regard as a challange rather than a hindrance).



Related Topics



Leave a reply



Submit