Improve company productivity with a Business Account.Sign Up

x
?
Solved

Validating contents of $_GET

Posted on 2013-01-23
11
Medium Priority
?
359 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 36

Accepted Solution

by:
gr8gonzo earned 2000 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 36

Assisted Solution

by:gr8gonzo
gr8gonzo earned 2000 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 35

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
Get 10% Off Your First Squarespace Website

Ready to showcase your work, publish content or promote your business online? With Squarespace’s award-winning templates and 24/7 customer service, getting started is simple. Head to Squarespace.com and use offer code ‘EXPERTS’ to get 10% off your first purchase.

 
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 36

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 84

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 36

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 35

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 84

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 111

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 111

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: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Strategic internal linking is often considered an SEO power technique, especially for content marketing. Do you need to hire an SEO agency to optimize you internal linking? No, this article will help you understand the basics of internal linking and…
I recently worked on a Wordpress site that utilized the popular ContactForm7 (https://contactform7.com/) plug-in that only sends an email and does not save data. The client wanted the data saved to a custom CRM database. This is my solution.
This tutorial walks through the best practices in adding a local business to Google Maps including how to properly search for duplicates, marker placement, and inputing business details. Login to your Google Account, then search for "Google Mapmaker…
This video teaches users how to migrate an existing Wordpress website to a new domain.

606 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