PHP extracting without extract() - php

I have something like:
if(isset($_POST['submit']))
{
$linktitle=strtolower(str_replace(" ","-",$title));
etc.
$linktitle and $title are actually variables from $_POST - ie $_POST['linktitle'] and $_POST['title'].
Somehow, even though (as far as I can see!) I haven't extract()ed $_POST at this stage in the code, it is still working - PHP is understanding that $title is referring to $_POST['title']. Could anyone please explain why this might be?
Thanks!
ps. Sorry, but I really can't get this inline code quote formatting thing to work...!

register_globals is enabled in your PHP instance. See here for more info.
This is behaviour that should be relied upon as it's use is now deprecated. You will find that you can still use $_POST['keyname'] as well as $keyname, and that is what you should refer to in your code.

Your php.ini file must have register_globals enabled, so GPC variables are being added to the symbol table. This is why you see this behaviour. See the security risks of such a feature here

You have register globals activated in your webserver (php.ini), so PHP replace the unknoe variables with the corresponding GET or POST value. This option is deprecated and dangerous! Disable it if you can!

Related

Why check if stripslashes function exists?

I've found the following code that checks if the stripslashes() function exists.
if ( function_exists( 'stripslashes' ) ) {
// Do something
} else {
// Do something
}
The stripslashes() function works on PHP4 and PHP5, so I wonder why it needs a conditional statement to check if the function exists. I don't get it.
It's not a subjective question. Just tell me what is the difference between the usage of this statement and not using it. Thanks in advance!
Here are related links as to where they were used:
http://trevordavis.net/blog/wordpress-jquery-contact-form-without-a-plugin/
PHP contact form will not submit
There used to be a feature in PHP known as magic quotes, which while well-intentioned, has caused endless confusion.
Most likely this code is intended to detect magic quotes, however this is not the correct way to do this, especially since it does not work.
The correct way to detect if magic quotes are enabled is to use the fuction made for the purpoes, get_magic_quotes_gpc like so.
if (get_magic_quotes_gpc()) {
Or perhaps the following, if you are concerned this will be removed.
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
That being said, the whole magic quotes feature was removed back in PHP 5.4, so unless you need to support obsolete versions of PHP, you can just forget the whole thing ever existed (unless you use WordPress that is...).
On a side note, I suppose it's possible the stripslashes function may be removed in the future, and may not have existed at one point, but in this context that's probably not the reason.
Sidenote: Transcribed from some of my comments (slightly modified) to supply the question with a complimentary answer to that of Alexander's.
This is probably to check if some coder went and created a custom function called the same (a method to someone's madness?), or somebody hacked the PHP core and removed it; I'm speculating of course, it's not impossible.
However, the same thing goes for if ( function_exists( 'mysql_real_escape_string' ) ).
If a server doesn't support those old and deprecated mysql_ functions, then the conditional statement is needed and would prove to be effective/useful for something of that nature to be used.
References: (mysql_ removed as of PHP 7, and other deprecation notices)
https://wiki.php.net/rfc/mysql_deprecation
https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7
https://wiki.php.net/rfc
Personally, function_exists() should only be used against probable deprecated functions; mysql_ being one of them and session_register() - I'm sure there are more.
It's listed in the manual from contributed notes http://php.net/manual/en/function.stripslashes.php and it seems to have something to do with magic_quotes_gpc as per what Alexander (O'Mara) said in comments.
N.B.:
I am by no means looking to gain anything from this, but for others visiting the question.

PHP auto-assigning query string variables without me doing anything

I came across this when I realized I had a script that was working, but shouldn't be. I tested it by making a one line script as follows:
<?php
echo "<br>lang - $lang";
?>
When I run the script with query string ?lang=japanese it outputs:
lang - japanese
What the hell? No $_GET or $_REQUEST statements or anything but that one line. How is this happening???
Like Pekka said, it is likely you have register_globals turned on in your configuration. This is usually regarded as a security risk and should be turned off.
The feature itself was actually removed as of PHP 5.4.0

Confusion about mysql_real_escape_string and strip_slashes

I have users entering their name, as in: O'riley.
Before I enter this data into the MySQL DB, I run mysql_real_escape_string.
Problem is, when I then select this data for display and use later, it comes out as: O\'riley.
Obviously, this is the intended operation. What I'm wondering is if there's someway to be sure I can store it in the DB (still safely escaping possible malicious code), so that I don't have to use strip_slashes() on the output EVERY time I call the data throughout the entire web app? Or, am I missing something here?
Thanks.
UPDATE
Please refer to the comments in Deceze's answer.
No, it's not the intended operation to store the string as "O\'riley"; it should only be escaped in the query, but not stored this way. I'll guess that PHP puts in the backslash through Magic Quotes, and you escape it again to make it stick.
Disable Magic Quotes.
I personally always turn off magic quotes because it is doing something I haven't told it to do. If you dont have the ability to turn it off, consider including this code at the top of all of your pages.
if (get_magic_quotes_gpc()) {
function strip_array($var) {
return is_array($var)? array_map("strip_array", $var):stripslashes($var);
}
$_POST = strip_array($_POST);
$_SESSION = strip_array($_SESSION);
$_GET = strip_array($_GET);
}
If you have magic quotes disabled, and in the case that get_magic_quotes_gpc returned 1 and you did something like #Michael shows and this still occurs, magic quotes runtime may be enabled.
Magic quotes runtime will add slashes to strings when doing database queries and even when writing to files. To disable this in the currently executing script, do:
if(function_exists('get_magic_quotes_runtime') && get_magic_quotes_runtime())
{
set_magic_quotes_runtime(false);
}
You can also disable this configuration option through php.ini as well, if you can do so. However, if you can't disable it through php.ini permanently, you may need to add # before get_magic_quotes_runtime and set_magic_quotes_runtime as PHP may through E_DEPRECATED errors if error_reporting is set to log such errors (and this will get fairly annoying).
Alright, here's what you need to do. First, based on the comments, from other questions:
ISOLATE
You need to determine what is causing the problem. Is it the server? Is it some hidden code somewhere? What? Some programmers may include code like this on a configuration page:
<?php if (isset($_POST))
foreach ($_POST as $key => $value) $_POST[$key] = addslashes($value);
?>
So here are some checks to see if it is the server. This is about as solid a way of checking as possible. Create a NEW page. Leave it entirely blank and add this code:
<?php print_r($_POST); ?>
<form action="" method="POST">
<input type="text" name="test" value="O'riley" />
<input type="submit" name="submit" value="submit" />
</form>
Save it and load it in the browser. Hit submit. See if the slash is added still.
If it is still adding it, you need to troubleshoot your server / configuration. If it's a server you're paying for, you need to tell them to fix it or shove it. If it's your own server, then you're going to need to do some messing / googling to figure out how to turn off magic quotes.
If there are no quotes showing up, then there is definitely some code adding slashes to your post variables. It might not be as obvious as the code above, however. You need to run a search on your code for "addslashes", "mysql_real_escape_string", and possibly "str_replace". If you find one of these, you need to disable it. But be advised this may break other parts of your site that are assuming this action is taking place. You're other option for storing it in the database is to do a function similar to the code above, but instead, run stripslashes on it. Then you can run mysql_real_escape_string on it later. (A bit more unneeded overhead.)
Use
var_dump(get_magic_quotes_gpc());
somewhere near the actual use of the posted data to see if the Magic Quotes are really off.
Also some weird frameworks may add said quotes for you so grep your code for addslashes and other escape_string-like functions.
I would honestly suggest the use of PDO.
PDO employs the use of prepare and execute statements, which in turn adds security and removes some extra headache.
$pdo = new PDO();
$stm = $pdo->prepare('INSERT... (LastName) VALUES (:LastName)');
$stm->execute(array(':LastName' => "O'Rily"));
$stm->fetchAssoc(PDO::FETCH_ASSOC);
You no longer will need to worry about removing the escaping slashes as well as securing basic sql injection tactics.
It's possible magic quotes are turned on in your httpd.conf or in a virtual host declaration.
The exact location and file will depend on OS and distro. I'd check Apache configuration files for the php_flag setting.
Just use clean the data before inserting in to database,
function check_input($value)
{
if( get_magic_quotes_gpc() )
{
$value = stripslashes( $value );
}
//check if this function exists
if( function_exists( "mysql_real_escape_string" ) )
{
$value = mysql_real_escape_string( $value );
}
//for PHP version < 4.3.0 use addslashes
else
{
$value = addslashes( $value );
}
return $value;
}
$cleandata = check_input($value);
$sql = "INSERT INTO `table_name` SET `field_name`='".$cleandata."'";
While fetching the data and show into it use stripslashes($val)
Thank you everyone for the answers. I will award the +50 out, but I wanted to tell my real solution here, all which people did help with...
I was performing mysql_real_escape_string on all of the data AS SOON as it posted (before any processing). So, a slash was added to escape the ' character that was submitted. This, we know is normal.
However, there was no reason that the backslash \ should show up in the DB entry, right? The escape was there to be sure the ' was entered.
Turns out, AFTER escaping, I would then save the variable to be reloaded to the page in the session, in case the user had an error that PHP found while validating all of the form fields. In this case, the user's input (formerly O'riley was now printed to their screen as O\'riley. Then, the user didn't catch this - so they would often just fix their error that PHP caught during validation (unrelated to the name field), and thus the O\'riley would land in the database because mysql_real_escape_string would escape the characters.
Lesson:
When processing a form, FIRST save data for form-refill use. SECOND validate form fields. THIRD escape the data for processing into the database.
Or better yet, use PDO and avoid this =).
Comments welcome. THANKS ALL!

PHP 5.3 support for strange '${}' code?

I've just upgraded to PHP 5.3 and started supporting an old website for a new client. It seems to use rather odd PHP code which I've not come across before.
Whilst trying to access $_GET or $_REQUEST variables, the developer has used the following: ${"variable_name"}
I get notices generated due to undefined variables (presumably because PHP is not parsing the ${"variable_name"} style code).
Changing this to $_REQUEST['variable_name'] works as expected, but I can't go through all their code and change it as the site is massive and uses proprietry layout methods.
Does anyone know if it's possible to switch on support for these tags / codeblocks? I've taken a look in PHP.ini and there is a mention of ASP style tags and short tags but enabling these has no effect (they look totally different anyway, I just thought it was worth a shot).
I don't think there is anything new with that syntax :
$a = 10;
var_dump(${"a"});
Works just fine ;-)
You problem is probably due to the fact that, before, register_globals was enabled (by default, if PHP <= 4.something), and is now disabled -- and that is good for security !
With register_globals set to On, any variable in $_REQUEST is automatically injected as a vartiable in your application -- well, actually, this depends on the variables_order configuration option, but this one almost always includes Get, Post, and Cookie, at least.
For instance, if there is a variable like $_GET['my_var'], you will also have a $my_var variable... And this one can also be accessed with the syntax ${'my_var'}
Considering register_globals is Off by default since something like PHP 4.2, and should disappear in PHP 6 (if I remember correctly), I would advise against re-activating it... at least, if you have the time required to correct / test the code...
Curly brace syntax for variables is an embedded part of PHP, and has been around for quite awhile. The reason it exists is to resolve ambiguities with arrays and object syntaxes when using variable variables.
From the manual:
In order to use variable variables
with arrays, you have to resolve an
ambiguity problem. That is, if you
write $$a1 then the parser needs to
know if you meant to use $a1 as a
variable, or if you wanted $$a as the
variable and then the 1 index from
that variable. The syntax for
resolving this ambiguity is: ${$a1}
for the first case and ${$a}1 for
the second.
It's a very handy syntax in several situations, such as using array or object variables while outputting something using heredoc syntax.
I won't reiterate the advice by others about using register_globals, I just wanted to expound on this unusual syntax.
The ${"variable_name"} syntax is practically the same as $variable_name, except that the contents of the curly braces are evaluated first. It is supported by all recent versions of PHP, even the beta versions. What is not supported by recent versions of PHP though is the support of registering $_REQUEST (and other) variables as global variables. There's a setting for enabling it:
register_globals = on
It is NOT recommended for production use because of security issues though. It may be easier to run you source through some 'sed'-like tool and replace the usages with regular expression.
The old server probably has REGISTER_GLOBALS on. So the weird brackets aren't the problem.
REGISTER_GLOBALS puts all the variables in $_REQUEST as regular variables in the global scope, meaning you can access $_REQUEST['test'] can be accessed like $test or ${"test"}
The bracket syntax is on by default, and I don't believe you can turn it on/off.
register_globals was likely switched on. {$variable_name} syntax is always on, but register_globals turns things like $_REQUEST['variable_name'] into $variable_name.
Avoid switching it on if at all possible, though - there's a reason it's been long advised against, and it's going away entirely in PHP6.
register_globals is deprecated as of php 5.3 and will be removed as of php 6.0. What you want to do is use the Refactoring feature found in most PHP IDE's (zendo studio 6+) to rename the variable to something more appropriate, ie $_GET['variable_name'].

$var instead of $_GET['var'] in PHP?

Ok I cannot remember the details on this but on some servers you can use
$var instead of $_GET['var'] to access a variable in the URL, I know this is BAD but I can't remember why it is bad?
I think you mean Register Globals.
You shouldn’t use them because you cannot distinguish the source of that variable values since they can come from any source of the EGPCS variables (Environment, GET, POST, Cookie, Server).
So if you have a the $var, you cannot say if the value is either from $_ENV['var'], $_GET['var'], $_POST['var'], $_COOKIE['var'] or $_SERVER['var'].
The feature is called Register Globals and it allows people to inject variables into your code. See the documentation for examples; here's one:
<?php
// define $authorized = true only if user is authenticated
if (authenticated_user()) {
$authorized = true;
}
// Because we didn't first initialize $authorized as false, this might be
// defined through register_globals, like from GET auth.php?authorized=1
// So, anyone can be seen as authenticated!
if ($authorized) {
include "/highly/sensitive/data.php";
}
?>
You can use that if your server has register_globals set to 1 (or true) on the php.ini file.
At some point, this started to be off by default, and applications started to break, which is a reason why this is a bad practice.
You can see a list of php.ini variables here.
It's also bad because you can confuse yourself with the way that PHP will scope your variables. You may wind up overwriting data if you aren't careful. Also, using $_GET is much clearer as to what you are attempting to accomplish.
Because letting people inject values into arbitrary variables is a very bad thing. You could be storing anything there and they could overwrite some value that compromises your security. Remember to use isset to check that a value has been set before trying to use it.
It's bad because if you're not careful to initialize every variable before you use it (something that PHP won't force you to do), people can easily cause your code to do Very Bad Things with a request as simple as /myapp/index.php?admin_privileges=1.
The setting is called REGISTER_GLOBALS and it was discussed here:
Why is REGISTER_GLOBALS so bad?
If you can do that, then "register_globals" is turned on. This is bad because you won't know where a variable came from, and it mixes your variables with the ones any user can inject via the URL. Read more here: http://www.php.net/manual/en/security.globals.php
Once you get used to using $_POST, $_GET, etc your code's purpose will be easier to read and much, much easier to maintain.
Register globals would work but it's going to go away in a future version of PHP. Not to mention that it really is wrong to have it enabled.
You can use extract() for a more controlled behavior. It will extract the keys from an array (in this case, $_GET) into the local context as variables. You can give them a common prefix so that they don't collide with your existing variables. And you can filter the array beforehand to make sure you're only getting the expected variables.
int extract( $var_array [, $type = EXTR_OVERWRITE [, $prefix ]] )
Import variables from an array into the current symbol table.

Categories