Page 1 of 2
Faking a post variable......is it possible?
Posted: Wed Apr 19, 2006 7:54 am
by malcolmboston
Its not for my use, but rather defending my application.
is there anyway (even if its not perfectly feasible) for an EU to fake a post variable?
Posted: Wed Apr 19, 2006 8:10 am
by R4000
yup it is possible, but you have to use sockets ect. and build your own fake http client as such.
Open socket, send headers (not hard to work out), ignore all output untill a blank newline (unless you want to parse return headers), then print everything after..
Posted: Wed Apr 19, 2006 8:25 am
by malcolmboston
how is it stopped?
Posted: Wed Apr 19, 2006 8:34 am
by Maugrim_The_Reaper
You can try to force the user to use your own forms.
To be honest your application should not care how a user chooses to send input. So long as it filtered effectively they can fake all the POST requests they want... As a quick rule - if a URI on your app does not expect any POST data, then your input filter should simply discard any such data immediately.
Posted: Wed Apr 19, 2006 8:42 am
by Chris Corbyn
Maugrim_The_Reaper wrote:You can try to force the user to use your own forms.
To be honest your application should not care how a user chooses to send input. So long as it filtered effectively they can fake all the POST requests they want... As a quick rule - if a URI on your app does not expect any POST data, then your input filter should simply discard any such data immediately.
You can also write a function that collects post data into variables for you, in the expected formats. You tell it at the start of the script you're expecting 'foo' from POST and that it should be an integer. If it's not an integer it gets dropped. This is also a great way to prevent SQL injection.
Posted: Wed Apr 19, 2006 9:37 am
by Chris Corbyn
Here's a little class I just made up that would do some filtering of data coming in from any of the superglobals.
Bear in mind that POST and GET send strings almost all the time so a '42' wouldn't validate as is_int() but rather is_numeric(). The use of the PCRE match will be a big help.
If any of the expected variables are not found they are nulled, if they don't satisfy the level of sanity you set they are nulled, if they look ok, they are stored.
Code: Select all
<?php
/*
A basic class for sanitizing data being received over HTTP
in PHP Super Globals.
Author: d11wtq (Chris Corbyn)
Date: 2006-04-19
License: none.. Just use it
*/
class htDataHandler
{
private
$htVars = array(),
$expectVars = array(), //Variable names
$expectLocs = array(), //POST, GET, COOKIE, REQUEST, SESSION
$expectTypes = array(), //Data types
$expectMatches = array(); //PCRE
public function __construct()
{
//
}
public function expectData($array)
{
foreach ($array as $k => $a)
{
if (is_array($a) && sizeof($a) >= 2)
{
$params = array_values($a);
$this->addVar($params, $k);
$this->addLoc($params, $k);
$this->addMatch($params, $k);
$this->addType($params, $k);
}
}
$this->validate();
}
public function getVar($v)
{
if (isset($this->htVars[$v])) return $this->htVars[$v];
}
private function validate()
{
foreach ($this->expectVars as $k => $v)
{
//It seems this is needed for variable variable in the superglobal scope
global ${$this->expectLocs[$k]};
if (isset(${$this->expectLocs[$k]}[$v]))
{
$tmp = ${$this->expectLocs[$k]}[$v]; //Read it but don't use it yet
if ($this->expectTypes[$k] && !$this->checkType($tmp, $this->expectTypes[$k])) $tmp = null;
if ($this->expectMatches[$k] && !$this->checkMatch($tmp, $this->expectMatches[$k])) $tmp = null;
$this->htVars[$v] = $tmp;
}
else $this->htVars[$v] = null;
}
}
private function checkType($v, $type)
{
switch (strtolower($type))
{
case 'str':
case 'string': return is_string($v);
case 'int':
case 'integer': return is_int($v);
case 'float': return is_float($v);
case 'double': return is_double($v);
case 'array': return is_array($v);
case 'object': return is_object($v);
case 'numeric': return is_numeric($v);
}
return false;
}
private function checkMatch($v, $pattern)
{
if (preg_match($pattern, $v)) return true;
else return false;
}
private function addVar($a, $k)
{
if (isset($a[0])) $this->expectVars[$k] = $a[0];
else $this->expectVars[$k] = null;
}
private function addType($a, $k)
{
if (isset($a[1])) $this->expectTypes[$k] = $a[1];
else $this->expectTypes[$k] = null;
}
private function addMatch($a, $k)
{
if (!empty($a[2])) $this->expectMatches[$k] = $a[2];
else $this->expectMatches[$k] = null;
}
private function addLoc($a, $k)
{
if (!empty($a[3])) $this->expectLocs[$k] = $this->getLocation($a[3]);
else $this->expectLocs[$k] = $this->getLocation(0);
}
private function getLocation($loc)
{
switch (strtolower($loc))
{
case 'get':
case '$_get':
case '_get': return '_GET';
//
case 'post':
case '$_post':
case '_post': return '_POST';
//
case 'cookie':
case '$_cookie':
case '_cookie': return '_COOKIE';
//
case 'session':
case '$_session':
case '_session': return '_SESSION';
//
case 'request':
case '$_request':
case '_request':
default: return '_REQUEST';
}
}
}
?>
Code: Select all
/*
array (
array( string varName, string varType [, string match [, string requestLocation] ] )
)
*/
$a = array(
array('foo', 'string', '/^foo\d{2}$/i', 'get'),
array('bar', 'numeric')
);
$handler = new htDataHandler;
$handler->expectData($a);
echo $handler->getVar('foo');
echo $handler->getVar('bar');
EDIT | Changed isset() to !empty() for the optional params.
Posted: Wed Apr 19, 2006 11:30 am
by John Cartwright
Shiftlett some input on the matter
viewtopic.php?p=252019#252019
Hey Chris, going a bit off topic here, but instead only nulling the invalid values, perhaps check them in a garbage variables, which can be access via $this->_getRaw() or something..
Posted: Wed Apr 19, 2006 12:47 pm
by Chris Corbyn
Jcart wrote:Shiftlett some input on the matter
viewtopic.php?p=252019#252019
Hey Chris, going a bit off topic here, but instead only nulling the invalid values, perhaps check them in a garbage variables, which can be access via $this->_getRaw() or something..
Yeah I guess you could do that. I just knocked it up as a rough example.
Part of the reason it's done like that is so that the logic reads nicely when checking it was validated ok.
Code: Select all
if ($obj->getVar('foo') !== null) echo $obj->getVar('foo');
I guess there's always the chance that you wanted it to be null though.... but if that's the case you'd know before hand. The basic idea of filtering is still the same however.
Posted: Wed Apr 19, 2006 12:49 pm
by John Cartwright
I meant you do assign them null, but before you do
Code: Select all
$this->raw['variable'] = $variable;
// if is invalid
$variable = null;
then
Code: Select all
public function getRaw($key) {
return $this->raw[$key];
}
This would be useful for error reporting and such, although I usually do throw my getRaw functions through some sort of minimal filtering to prevent XSS attacks and such aswell
Talk to you on msn about this furtur, as we (or I

) sorta have hijacked the thread

Posted: Wed Apr 19, 2006 12:56 pm
by Chris Corbyn
Jcart wrote:I meant you do assign them null, but before you do
Code: Select all
$this->raw['variable'] = $variable;
// if is invalid
$variable = null;
then
Code: Select all
public function getRaw($key) {
return $this->raw[$key];
}
This would be useful for error reporting and such, although I usually do throw my getRaw functions through some sort of minimal filtering to prevent XSS attacks and such aswell
Talk to you on msn about this furtur, as we (or I

) sorta have hijacked the thread

Ah gotcha. Good point since if the data didn't validate you may still want to use it but do soemthing else with it.
/me steers thread back on topic
Posted: Wed Apr 19, 2006 1:28 pm
by Roja
R4000 wrote:yup it is possible, but you have to use sockets ect. and build your own fake http client as such.
Open socket, send headers (not hard to work out), ignore all output untill a blank newline (unless you want to parse return headers), then print everything after..
No, you don't have to.
There are plugins for Firefox that allow you to modify forms realtime, there are proxies that let you do so, and more.
It is trivial - not nearly as complicated as you are implying it to be.
Posted: Wed Apr 19, 2006 1:40 pm
by John Cartwright
you can easily send post headers in a couple lines of code..
cURL
Posted: Wed Apr 19, 2006 5:13 pm
by alvinphp
Your application should validate all the data on the server side to make sure the data is what it should be (ie accessory methods). Then you should not need to worry about a fake post. One of the weakness of javascript is since the validation is done on the client it can be bypassed and then a person could theoretically inject harmful code that could mess up your form/site/application.
Posted: Fri Apr 28, 2006 7:44 pm
by a94060
could you possibly check the URl that the data is coming from? use like a strpos or something?
Posted: Fri Apr 28, 2006 7:54 pm
by alex.barylski
a94060 wrote:could you possibly check the URl that the data is coming from? use like a strpos or something?
Most anything you would use to uniquely indentify a user is most likley easily spoofed...
You have no choice but to sanitize data...
You could possibly make sure that data was sent by a unique person as opposed to abot of some sort by using CAPTCHA, which would require human intervention...
But that POST could have come from anywhere, including there own web site, etc...allowing them to spoof all the headers they want...