Solved

Validating contents of $_GET

Posted on 2013-01-23
11
319 Views
Last Modified: 2013-02-13
I am looking for a way to validate the contents of $_GET and/or $_POST, something along the lines of PHP is_uploaded_file() works.  Here is the specific scenario.

Two programmers are working on different classes as part of a larger web site.  The "bad" programmer intends to sabotage the project by changing the request variable with something like this, before handing off control to the class coded by the good programmer.

$_GET['username'] = 'Evil';

Since $_GET is mutable and present in every class and namespace, this risk exists.  Is there a way to verify the original request variable, other than to trust $_GET?

Thanks to all, ~Ray
0
Comment
Question by:Ray Paseur
  • 4
  • 2
  • 2
  • +2
11 Comments
 
LVL 34

Accepted Solution

by:
gr8gonzo earned 500 total points
Comment Utility
Hi Ray,

That's going to be difficult to control, since a malicious programmer will typically have ways to gain access to just about every part of the code (if not directly, then via PHP's own permissions).

However, you can probably make it more difficult by using a custom class to take control over the values, and then only allow for data retrieval and no modification. For example, let's say you use auto_prepend_file to include a file called SafeRequest.class.php:

<?php

// Run the init() routine before anything else can modify $_GET.
SafeRequest::init();

class SafeRequest
{
  private static $data = null;
  private static $instances = 0;

  public static function init()
  {
    // Don't allow multiple init()s to run!
    if(self::$instances == 0)
    {
      global $_GET, $_POST;
      self::$data = array($_GET,$_POST);
      self::$instances = 1;
    }
  }

  private static function getData($type,$var,$default)
  {
    if(isset(self::$data[$type][$var]))
    {
       return self::$data[$type][$var];
    }
    else
    {
       return $default;
    }
  }

  public static function Get($var,$default = null)
  {
    return self::getData(0,$var,$default);
  }

  public static function Post($var,$default = null)
  {
    return self::getData(1,$var,$default);
  }
  
}

?>

Open in new window


Then instead of something like:

$username = $_GET["username"];

you would use it like:

$username = SafeRequest::Get("username");
0
 
LVL 34

Assisted Solution

by:gr8gonzo
gr8gonzo earned 500 total points
Comment Utility
Also bear in mind that this means that you would double the amount of memory used by GET and POST for each request. It might be wise to even clear out $_GET and $_POST in the init() routine:

$_GET = array();
$_POST = array();

...to help enforce programmers to use SafeRequest and to reduce the memory footprint.

You'd have to keep SafeRequest write / mod perms locked down so that the auto_prepend_file would only be able to be read by PHP and other potential malicious sources.
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
greetings   Ray_Paseur, , ,  There are ways to get the PHP page URI query string that are not using the $_GET array, please look on manual at -
http://php.net/manual/en/reserved.variables.server.php

you might should try the -
$uri = $_SERVER['REQUEST_URI'];
or
$qs = $_SERVER['QUERY_STRING'];

but these are the NON parsed and separated strings, so you will have to separate out any string info in them. I do not believe that you can change these with -
$_SERVER['QUERY_STRING'] = '?user=evil&cost=none';
but I have not tried to do that.

Oh and if it's a file upload or LONG post, then this query string can be alot of text to parse.
0
 
LVL 30

Expert Comment

by:Marco Gasi
Comment Utility
Hi Ray,
hi gr8gonzo,
I apologize if I post here a comment: I'm not so presumptuous to think to can give some answer here, but it seems an ideal job for a bootstrap file: if all requests are intercepted by one file, something like what happens in MVC pattern, there you can operate all dirty job about securing and validating data. Am I wrong?
0
 
LVL 34

Expert Comment

by:gr8gonzo
Comment Utility
Hi marqusG,

That is what I was suggesting. The auto_prepend_file directive means that the specific script will be automatically included with every request.
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 82

Expert Comment

by:Dave Baldwin
Comment Utility
On both Apache and IIS, $_SERVER['REQUEST_URI'] contains the file name and the query string like "/index.php?qstr=99" and should be unaffected by changing the $_GET values.  You can parse that to get the original value sent to the server.  Explode at '?' first and then explode the second part at '&' to get the individual name/value pairs.
0
 
LVL 34

Expert Comment

by:gr8gonzo
Comment Utility
Dave and Slick,

I see two problems with the approach of checking against REQUEST_URI:

1. To validate GET against REQUEST_URI means parsing REQUEST_URI anytime you want to validate something, which can have an impact on performance (assuming the application is large enough to allow malicious code to go unseen, there are probably many instances that would need this).

2. REQUEST_URI is editable. A malicious user could also change the REQUEST_URI fairly easily if they were trying hard enough to cover their tracks. The same applies to all environment variables, really. The only way for a malicious user not to be able to completely clear their tracks is if there were a signature applied at the web server level prior to the request entering the PHP engine. However, PHP would need to be able to validate the signature, which usually means that unless it's a secured method that can't be reverse engineered, a malicious user could probably just recreate the signature after the injection.
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
not sure that  Ray_Paseur is even reading this comment train, but, , , I do agree wid  gr8gonzo, as I tested the $_SERVER['REQUEST_URI'] , you can after all change it by assignment wid =
it is also limited to only the GET as the URI would indicate.  I tried the php function  apache_request_headers()  but it was not enabled on that particular server.
I do not see the parse of a string as being much of a drawback, at least for me, do it quite alot.
But I have been in development teams, and I really can not see how having a team coder, purposefully sabotage a teams work, be something that does not demand the entire attention of the whole Web site personnel , coders, owners, sponsors, to fix that problem, not just have a GET entry validation.

I am also suprized that I can not get the raw request headers for a POST in PHP, before they are placed on the $_POST array, I tried several things, and web searched it, except for the apache_request_headers()  I found no valid examples, , LOL guess I too dumb to find it, LOL
0
 
LVL 82

Expert Comment

by:Dave Baldwin
Comment Utility
You can get 'ALL_HTTP' in IIS but not Apache.  $_SERVER['REQUEST_URI'] and $_GET come from the same place (passed from the web server) so there is no difference in the ability to edit them at the source.  Ray asked for some way to check $_GET and that is the only thing I see that corresponds to the $_GET array.

I agree with Slick812 that having a person on the team that sabotages the code that the others use is a Real Problem.  Worthy of a first class beat-down.
0
 
LVL 108

Author Closing Comment

by:Ray Paseur
Comment Utility
I've chewed this question fairly well and the cud is that auto_prepend is probably the best solution.  Too bad that PHP made all the SuperGlobal variables mutable.  I'll post a code sample showing how lame that is!  And I agree with all the comments about what a problem it would be to have a rogue programmer on the team!

Thanks, colleagues.  Thoughtful contributions all around, ~Ray
0
 
LVL 108

Author Comment

by:Ray Paseur
Comment Utility
A test case...

<?php // get.php 
error_reporting(E_ALL);

// LOOKING FOR A WAY TO TELL IF GET HAS BEEN TAMPERED WITH...
// TEST WITH ?foo=bar
// TEST WITH ?a=b

// THIS SHOULD SET $_get EQUAL TO $_GET
parse_str($_SERVER["QUERY_STRING"], $_get);

// AND IT DOES
if ($_GET == $_get) echo ' == ';
if ($_GET === $_get) echo ' === ';
var_dump($_GET, $_get);

// MUNG $_GET AND TEST
$_GET['foo'] = 'bar';
if ($_GET == $_get) echo ' == ';
if ($_GET === $_get) echo ' === ';
var_dump($_GET, $_get);

// BUT ALAS, $_SERVER IS NOT IMMUTABLE, EVEN THOUGH IT SHOULD BE READ-ONLY
$_SERVER['QUERY_STRING'] = 'WHACKED';
phpinfo();

Open in new window

0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
Any business that wants to seriously grow needs to keep the needs and desires of an international audience of their websites in mind. Making a website friendly to international users isn’t prohibitively expensive and can provide an incredible return…
The viewer will learn how to count occurrences of each item in an array.
The viewer will get a basic understanding of what section 508 compliance can entail, learn about skip navigation links, alt text, transcripts, and font size controls.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now