How to demonstrate an exploit of extract($_POST)? - php

I am not a PHP developer but I'm assessing the security of a PHP5 application.
The author relied on extract($_POST) and extract($_GET) in some places, outside of functions.
My suggestion is to call extract($_POST, EXTR_PREFIX_ALL, 'form') and change the code accordingly, but his stance is that any variable is being redefined inside subsequent includes anyway.
I can easily change the superglobals by providing, for instance, _ENV=something inside the post values, but superglobals are arrays and I'm turning them into strings, I'm not sure it can have evil effects.
I could have a look at the several isset() uses and go backwards from there.. but I imagine there are attacks of this kind that don't require knowledge or divination of the source.
Is there some interesting variable to be set/changed, maybe in the innards of PHP?
Thanks

For assessing "might" try this:
File:htdocs/mix/extraction.php
<?php
extract($_GET);
var_dump($_SERVER);//after extract
?>
and call it like that:
http://localhost/mix/extraction.php?_SERVER=test
After the extract on my Xampp the output looks something like that:
string(4) "test"
If any one knows anything about your variable naming and you use extract on $_POST or $_GET globals, then you have a serious problem.
With a bit of time and work it would be possible to find out some namings by try and error.
Without knowing your source an intruder could try to hijack any global variabl like $_SESSION (but here it will only take any effect if you do the session_start(); before the extract($_GET), $_COOKIE or $_SERVER and even set specific values for them like that:
//localhost/mix/extraction.php?_SERVER[HTTP_USER_AGENT]=Iphone
If you use extract like that:
extract($var,EXTR_SKIP);
extract($var,EXTR_PREFIX_SAME,'prefix');
extract($var,EXTR_PREFIX_ALL,'prefix');
then you will be perfectly safe.

A common name for the database connection is $db, but that would just blow up the system, you can overwrite the $_SESSION variable.
session_start();
$_SESSION['test'] ='test';
var_dump($_SESSION);
$vars = array("_SESSION" => 'awww');
extract($vars);
var_dump($_SESSION);
output
array(1) {
["test"]=>
string(4) "test"
}
string(4) "awww"
Overwrite variables $idUser or other fun stuff, want to mess up the iterables?
Pass array('i' => 5) to extract, there are all sorts of fun you can have depending on scope.
Edit:
I just thought of another, if the form is handeling file uploads, why not try and overwrite variables named $file, $fileName, $fileExtention and see if you can get it to read files outside your permission level.

I'm not aware of any universal exploitability.
Anyway, it definitely is awfully bad practice.
What the script's author is saying is that the script's security relies on him not forgetting anything in the subsequent includes, which is horrible.
For strong general arguments against global extract()ing, see What is so wrong with extract()?

Related

phpbb 3.1 passing variable between 2 pages

With phpbb3.1 it appears they have disabled more superglobals.
I have tried passing a variable between using sessions, but have had no success.
$_SESSION['example'] = 'example';
$example = $_SESSION['example'];
Nothing is stored because nothing is there due to phpbb disabling superglobals. What's the next best and most secure way to pass variables in between pages?
You might want to take a look at this answer, where I explained that you can also temporarily (or globally) switch Superglobals back:
Globally
Open the /phpbb/config/parameters.yml file and change the core.disable_super_globals key from true to false.
Programmatically
This is a sample code that can be used to temporarily enable superglobals (per-request scope):
// temporarily enable superglobals
$request->enable_super_globals();
// TODO: do your stuff here.
// disable superglobals again
$request->disable_super_globals();
You can also read this blog post that I wrote on this topic for further info.
I'm not sure if $_SESSION is included, but try phpBBs request class...
$example = $request->variable('example','');
Docs for the class are here - https://wiki.phpbb.com/PhpBB3.1/RFC/Request_class

Is there a way to protect the $_SERVER global from modification?

I would like to prevent php scripts from being able to modify the contents of the $_SERVER global.
Specifically I don't want to allow
unset $_SERVER['foo'];
but it would be nice to forbid any modification, e.g. a module or php.ini declaration.
Is there one?
If you're in control of the root level script you could just copy it:
$_my_server = $_SERVER;
I think it would be helpful to know your reason for this; the $_SERVER variable shouldn't be modified by included scripts, because there's rarely a reason for someone to need to modify it. It's generated at run-time so any changes aren't persisted to subsequent runs of the script.
Also your extra point about php.ini declarations is a bit more confusing - the point of many componentes of $_SERVER is to inform scripts about those declarations, so having it send fake data would seem a very odd use case and maybe not possible.
Not as far as i'm aware.
If you are relying on the contents of $_SERVER throughout you code, and dont want other code (plugin?) to modify it, your best option is to make a copy during the bootstrap stage of your application, then use that copy throughout your code:
$serverDetails = $_SERVER;
$foo = $serverDetails['foo'];

Get variables inside includes [duplicate]

This question already has answers here:
PHP include() with GET attributes (include file.php?q=1)
(7 answers)
Closed 8 years ago.
What are the security implications of passing a get variable through an include?
Example:
index.php:
$lastname = $pulleddatabasevalue;
include "../includes/header?lastname=$lastname";
header.php:
echo $_GET["lastname"];
As the variable is dynamic, I have struggled to make include() or sessions work to assign the variable $lastname with the database value within the php include. However, $_GET here has worked fine. It doesn't show up on the browser address bar, thus can't be manipulated in a hostile manner there. Is there another way someone with malicious intent could work this code? Assume that the include directory is locked and I'm only referring to index.php.
Sorry, no way to pass get parameters to included file... See:
PHP include() with GET attributes (include file.php?q=1).
Include is a strict let's name it "Physical function". To make a get request, you must make a request. Include just read the file from the server.
BTW. I'm curious, how it is possible, you made it work. I think there is some misunderstood in your code.
You should think about include, as a COPY PASTE function.
In that case:
$var = true;
include ('include.php');
include.php:
var_dump($var);
should echo bool(true).
Hope it helps.
When talking about security issues, as far as I'm concerned, include in the way I describe, should not create any new security holes. But you should check all the permissions of included files, to be 100% sure.
The security implications of outputting user supplied input is the same no matter how it is done: ESCAPING AND VALIDATION IS ESSENTIAL! Otherwise you are implementing big security holes.
Apart from that, there isn't any difference whether you directly access $_GET, or first stuff that value into another variable and access that inside your include.
The only difference is of general software maintenance: The former usually is considered bad because it is access to a global variable, while the latter might be part of a function call and might encapsulate the variable name better.
Your code, however, is wrong. You cannot pass query parameters as part of the filename. It works because $_GET is available as an array everywhere without any further code (read "superglobal variable" in the PHP documentation).
Keep it simple and don't confuse...
index.php
$lastname = $pulleddatabasevalue;
include "../includes/header.php";
header.php
echo $lastname;
External refs. and recommended read:
http://www.php.net/manual/en/function.include.php
http://www.php.net/manual/en/reserved.variables.get.php

URL Parameters to PHP Variables

I've been doing PHP for a while now, never needed assistance, but totally confused this time. I have a single line of code with one echo statement.
Problem: URL parameters are automatically assuming PHP variable values of the same name. For example, I have a URL with a parameter named var_name like this:
http://www.example.com?var_name=abc123
and a 1-line PHP script with a variable named var_name, like this:
echo $var_name;
then I get output on the page of: abc123
This is the only code in the PHP page! This behavior is exactly how I expect $_GET to work, but I'm not using it.
I am having this problem only on 1 specific server, which is running PHP 5.2. I have tested on 4 other servers, none have this behavior. I assume it's a PHP config issue, but running default config and can't find anything in config documentation.
This is called register globals. If a server has register globals turned on, then you can do this.
I would recommend not to have register globals on any server. Since it can introduce a security flaw in your system.
An example of a security flaw with this.
if($auth == true)
{
// sensitive stuff here
}
If auth is just a regular variable, then I can do this in the URL.
http://www.example.com/page.php?auth=true
And see the sensitive information.
You probably have register_globals enabled:
See the manual for info.

Display all currently defined variables

Is this possible without a debugger?
I mean, we have $_POST, $_GET, $_SESSION, etc. I'm looking for something like $_CURRENT_VARS
$GLOBALS contains all global variables. Or you use get_defined_vars().
well, it's overkill, but you can call phpinfo() to display (essentially) everything.

Categories