Solved

Validating contents of $_GET

Posted on 2013-01-23
11
334 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
ID: 38811856
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
ID: 38811870
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 34

Expert Comment

by:Slick812
ID: 38811922
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
How Do You Stack Up Against Your Peers?

With today’s modern enterprise so dependent on digital infrastructures, the impact of major incidents has increased dramatically. Grab the report now to gain insight into how your organization ranks against your peers and learn best-in-class strategies to resolve incidents.

 
LVL 31

Expert Comment

by:Marco Gasi
ID: 38811965
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
ID: 38812047
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
 
LVL 83

Expert Comment

by:Dave Baldwin
ID: 38812293
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
ID: 38813961
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 34

Expert Comment

by:Slick812
ID: 38815913
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 83

Expert Comment

by:Dave Baldwin
ID: 38815950
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 109

Author Closing Comment

by:Ray Paseur
ID: 38885603
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 109

Author Comment

by:Ray Paseur
ID: 38885610
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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Because your company can’t afford for you to make SEO mistakes, you’ll want to ensure you’re taking the right steps each and every time you post a new piece of content. This list of optimization do’s and don’ts can help you become an SEO wizard.
FAQ pages provide a simple way for you to supply and for customers to find answers to the most common questions about your company. Here are six reasons why your company website should have a FAQ page
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

821 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