PHP adding backslashes to POST data - php

I have a form that submits to a database. But before it enters the database the submitted data is output on the screen. Currently, if I have "Mike's" submitted, it outputs "Mike\'s".
I have tried the below code to see if it is Magic Quotes, but this has not helped.
if ((function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) ||
ini_get('magic_quotes_sybase')
) {
foreach($_GET as $k => $v)
$_GET[$k] = stripslashes($v);
foreach($_POST as $k => $v)
$_POST[$k] = stripslashes($v);
foreach($_COOKIE as $k => $v)
$_COOKIE[$k] = stripslashes($v);
}
What should I look for?

Note: To sanitize the string
<?php
$mike = "Mike's";
echo filter_var($mike, FILTER_SANITIZE_STRING);
?>

Despite looking like a constant, editing $_POST should work. Then again, your code didn't work for me, either.
This works:
function getReq($key){
return isset($_REQUEST[$key]) ? stripslashes($_REQUEST[$key]) : "";
}
I haven't found why PHP (5.3.0 on WAMPSERVER 2.0 in my case) seems to magically change POST data while get_magic_quotes_gpc() returns 0, and frankly don't care to waste more time on its dirty innards.

There's a possibility it's in the code you're using to output to the screen.
If you were, for instance, using var_export(), one would expect to see character escapes on apostrophes.

It seems silly to answer after all these years but I see your post is active so i'll try.
First try this function stripslashes(). Doc: (https://www.php.net/manual/en/function.stripslashes.php)
Should this not work.
Do you display the data directly from the $_POST variable or retrieve it from the DB?
It might be saved as is in the DB and that would mean a UTF8 convert issue.
I kept my answer short and don't wish to add more unncessary info unless you need it.

Related

Foreach loop that loops through $_POST data instead of static isset($_POST["name"]......)

So here I am again trying to find better ways of doing things. 90% of tutorials do things the normal way below:
if (isset($_POST['name']) && isset($_POST['password'])) {
// Does some stuff...
}
It is fine but it does seem too static since I prefer something far more dynamic. For example lets say looping through all $_POST arrays within a contact form. This way I can change the name or the fields to whatever I want or add more...my code will always handle the rest.
I know a foreach loop would come in handy but, as someone new to the world of programming and php I thought you could show me how something like this is done. So how do I replace the above with a for loop? I am not sure where to start.
try this:
$check=true;
if(isset($_POST)){
foreach($_POST as $key=>$value){
if(!isset($_POST[$key]){
$check = false;
break;
}
}
}
based on $check you can verify if it was properly sent or not.
Another approach is to have a sort of verification because it is possible you might not get the key in $_POST
$keys =array("input1","input2");
$check=true;
if(isset($_POST)){
foreach($keys as $input){
if(!array_key_exists($input,$_POST)){
$check = false;
break;
}
}
}
Well you could try something like this :-
<?php
$inputNames = array("input1","input2");
foreach($inputNames as $input)
{
if (isset($_POST["$input"]) && isset($_POST["$input"])) {
// Does some stuff...
}
}
?>
Make an array with the names of all your input tags, and then simply do a foreach between them. In this way, you always only need to edit the names array.
You can always use foreach loop like that:
foreach($_POST as $key => $value){ echo '$_POST["'.$key.'"] = "'.$value.'"'}
But remember, that anyone, can modify your form, prepare some post statement and send data that can create little mess with your code. So it`s good way to validate all fields.
Dynamic validation is of course possible, but you need to do it right!

I am trying to solve a PHP exercise but am unable to understand what's happening

First of all I'm very sorry for my irrelevant question title, as I did not know how to write it better.
To start with, I am a PHP beginner. I am solving some PHP exercise and I came upon a question I don't know where to start with:
function q3() {
// I am supposed to write stuff here and not change anything to get the question right.
}
function a3($admin = false) {
assertion_group("Question 3");
foreach ($GLOBALS as $k => $v) $$k = $v;
if ($admin) {
$file = q3("edsi.pem");
}
$key = #file_get_contents($file);
$key = substr($key, 0, 4);
assert($key == substr(file_get_contents(__FILE__), 0, 4));
return $key;
}
First of all, I understand what $GLOBALS does, but why assign the $$k to $v (so the $k value to the $v value)? And does $GLOBALS get the values within functions?
How can I set $admin = true? I believe through q3(), but I don't see how...
Next thing that confuses me most is: $file = q3("edsi.pem"). As my q3 function doesn't have any arguments, and that I'm not supposed to add one, how can I use that?!
Thank you all very much in advance for your answer. My apologies again for the very vague question...
EDIT:
With the help of #mario to better understand this whole mess, basically what I had to put in q3 was:
if ($info == 'edsi.pem') {
$info = __FILE__;
return $info;
}
plus add an argument for q3 (q3($info)) and add ?admin=true in the header...
Many thanks again!
First of all, I understand what $GLOBALS does, but why assign the $$k to $v (so the $k value to the $v value)? And does $GLOBALS get the values within functions?
What that foreach … $$k = $v; snippet does is basically extract($GLOBALS);
This isn't a very useful way to pass arguments around. Using global vars only makes sense if they have somewhat descriptive names, and if they're not misused as state flags between different code sections.
And no, globals aren't available in all functions right away. Read up on variable scope.
How can I set $admin = true? I believe through q3(), but I don't see how...
You are confusing the function names here (precisely because they aren't rather useful function names to begin with). You can pass the $admin parameter when calling a3() instead:
a3(true);
Next thing that confuses me most is: $file = q3("edsi.pem"). As my q3 function doesn't have any arguments, and that I'm not supposed to add one, how can I use that?!
The only way to get the argument in q3 is per func_get_arg().
And again really, unless this is an exercise about how not to write code or a tutorial about weird use cases, you shouldn't really bother further.

Can't understand syntax error, unexpected '=' in eval()'d code

I've search different forms but didn't understand how to solve the problem first found here (first link, second link) but its giving me the error in eval. I can't figure it out how to solve in that code in foreach loop.
foreach($_POST as $key => $value) {
if(!strstr($key, 'removeFile')){
//initialize variables using eval
eval("$" . $key . " = '" . sanitize($value) . "';");
}
}
First, the issues I have with your code:
eval is very, very rarely needed, and extremely dangerous, use with caution. I've been developing in PHP for over 10 years, and never really encountered a situation that needed eval. This is no exception. Eval is not required
You're sanitizing the entire $_POST array. That's great, but there are special functions for doing that, like: filter_input_array, array_filter and many, many more... not to mention ready-made, open source projects and frameworks that already contain a solid request validation component.
Always check the return values of functions, which you seem to be doing with strstr, but be weary of functions that return different types (like strstr: it returns false if the needle isn't found, but returns 0 if the needle is found at the start of the haystack string). Your if statement might not work as intended.
You're assuming sanitize($value) values will not contain any single quotes. Why? Because if they do, you'll end up with a syntax error in your evaled string
Be that as it may, you could easily write your code using variable variables and add a simple check not to step on existing variables in scope:
$sanitized = array_filter($_POST, 'sanitize');//call sanitize on all values
foreach ($sanitized as $key => $value)
{
if (!isset($$key) && strstr($key, 'removeFile') === false)
$$key = $value;
}
But really, $_POST values belong together, they are part of the request, and should remain grouped... either in an array, or in an object of some sort. Don't assign each value to its own variable, because pretty soon you'll loose track of what variables are set and which are not. Using an unset variable creates that variable, assigning value null, so what you have now makes for very error-prone code:
//request 1: POST => id=123&foo=bar
foreach ($sanitized as $k => $v)
$$k = $v;
$query = 'SELECT x, y, z FROM tbl WHERE id = ?';//using posted ID as value
$stmt = $db->prepare($query);
$stmt->execute(array($id));
All is well, because $id was set, but never trust the network, don't assume that, just because $_POST is set, all the keys will be set, and their values will be correct:
//request 2: POST => foo=bar&page=2
foreach ($sanitized as $k => $v)
$$k = $v;
$query = 'SELECT x, y, z FROM tbl WHERE id = ?';//using posted ID as value
$stmt = $db->prepare($query);
$stmt->execute(array($id));//id is null
Now we have a problem. This is just one example of how your code might cause issues. Imagine the script grows a bit, and look at this:
//request 3: POST => id=123&foo=bar&page=2
foreach ($sanitized as $k => $v)
$$k = $v;
//$id is 123, $foo is bar and $page = 2
$query = 'SELECT x, y, z FROM tbl WHERE id = ? LIMIT 10';//using posted ID as value
//a lot more code containing this statement:
$page = someFunc();
$log->write('someFunc returned log: '.$page);
//more code
$offset = 10*($page-1);//<-- page is not what we expected it to be
$query .= sprintf(' OFFSET %d', $offset);
$stmt = $db->prepare($query);
$stmt->execute(array($id));
Now this may seem far-fetched, and idiotic, but believe me: all of these things happen, more than I care to know. Adding some code that accidentally overwrites an existing variable that is used further down happens all the time. Especially in procedural code. Don't just blindly unpack an array. Keep that single variable, and use the keys to avoid:
grey hair
sudden, dramatic baldness
loss of sanity
bleeding ulcers
In a work environment: catastrophic loss of data
Sudden loss of job
... because code like this makes unicorns cry, and bronies will hunt you down
As the first answer to the post you linked to, the problem is that when using double quotes PHP thinks your eval() code starts with a variable. As that is not the case you have two options. Use single quotes and remember to escape the single quotes declaring a string in the code or escape the dollar sign.
Bonus note
There exist more elegant solutions to the problem you are trying to solve. The best solution I can think of is using the extract function. This gives to two main benefits.
It works with all associative arrays
You can specify different flags that can help you distinguish the extracted variables apart and avoid variable injection.
One flag you can use is EXTR_PREFIX_ALL. This will prefix all the extracted variables with your own prefix. You would then access the variables with a prefix of 'PREFIX_' like the following:
$array = [
'variable1' => 'foo',
'variable2' => 'bar'
];
extract($array, EXTR_PREFIX_ALL, 'PREFIX_');
$value1 = $PREFIX_variable1; // Equals: foo
$value2 = $PREFIX_variable2; // Equals: bar
A little on code injection
Suppose you have some code:
$login = false;
The $login variable determines if a user is logged in or not.
Then somewhere you use the ´extract´ function with an array of the following without using any flags.
$array = [
'login' => true,
'foo' => 'bar'
];
extract($array);
Now your $login variable would be set to true and the user posting the data would have overwritten the initial setting and gained access to your website without a valid login. Bear in mind this is a over simplified example, but nonetheless valid.
To overcome this you can use the flag EXTR_SKIP or prefix them like I previously showed. The EXTR_SKIP flag will skip the array element if a variable with the same name already is defined. So now your code would not overwrite your $login variable.
extract($array, EXTR_SKIP); // Skip existing variables
// Or
extract($array, EXTR_PREFIX_ALL, 'prefix'); // Prefix them all.
Hope this can guide to the right choice for your needs.
Regards.

Naming variables automatically from $_POST array.

My PHP script processes some POST variables.
Instead of manually naming each variable
$name = $_POST['name'];
$email = $_POST['account'];
I'd like my script to grab all the variable names from the $_POST array and automatically create variables with those names, e.g. (not code, just illustrating the principle)
foreach ($_POST as $name => $value) {
$[$name] = $value;
}
Is something like that possible?
You can use the extract function for this. But there is a risk, because you cannot know what data is posted, and it will create or overwrite variables in the scope in which you call it, possibly leading to unexpected behaviour.
You can partially counter this, using one of the flags for extract, for instance:
extract($_POST, EXTR_SKIP);
Anyway, make sure to read the two warnings (red block) on the documentation page of this function. And of course, the same warning applies when you do this using your own foreach loop, so answers suggesting that are no more secure.
There is extract function in php:
extract($_POST);
This is a very bad idea because it allows a user to create any variable in your PHP script (within the scope that it this code is used). Take for example if you have a $debugging flag:
$debugging = false;
foreach ($_POST as $name => $value) {
$$name = $value;
}
// some time later, we do a query and output the SQL if debugging
if($debugging){
echo $sql;
}
What if a malicious user submitted an input called debugging with a value of 1? Your debugging flag would be changed and the user could see sensitive debug data.
Try this (which is a bad practice):
foreach ($_POST as $name => $value) {
$$name = $value;
}
You can do this with variable variables as follows:
foreach ($_POST as $name => $value) {
$$name = $value;
}
You can also use the following format if you want to muck about with the variable names some more:
foreach ($_POST as $name => $value) {
${$name.'_1'} = $value;
}
There are comments here saying don't use variable variables - mainly because they are hard as heck to troubleshoot, make it damn hard for others to read your code and will (for the most part) create more headaches than they solve.

Any easier way to do $name = $_REQUEST["name"];?

So I'm new to PHP and am trying to create a form. I accept a bunch of parameters and want to process them in the same page. I'm not sure how to do this without a giant if-else containing the entire page as if($_POST). This doesn't seem ideal.
In addition, I'm finding that I do the following a lot. Is there any way to shorten this? The names all remain the same.
$name = $_REQUEST["name"];
$gender = $_REQUEST["gender"];
$age = $_REQUEST["age"];
And I have a lot of lines which are just doing that, and it seems terribly inefficient
You can use the extract() function to do that. But it has a security downside: existing variables can be overwritten if someone would add variables to the POST header.
Edit: hsz's solution is better
What process you are doing with if..else..if you have to post the code so that we can let you know how that can be shorten.
you can avoid the assignment for each variable using extract function.
extract($_POST);
But be aware that can overwrite your existing variable if the are named same as your input controls.
Stop using $_REQUEST, because it is a combination of $_COOKIE , $_POST and $_GET.
It becomes a security risk.
Instead of using $_REQUEST you should use $_POST here.
$keys = array('name', 'gender', 'age');
foreach ( $keys as $key ) {
if ( isset($_POST[$key]) ) {
$$key = $_POST[$key];
}
// optional:
else {
$$key = ''; // default value
}
}
Magic quotes? http://php.net/manual/en/security.magicquotes.php
For the first thing: Turn it around. Don't do
if ($_POST) {
// Your handling code
} else {
echo "No data!";
}
do
if (!$_POST) {
die("No data!");
}
// Your handling code
You can use extract(), however, this means that you're bringing in a lot of variables that you (might not know about) int your current scope.
My suggestion would be to loop through your array and do something with the variables in there (e.g. - validation)
foreach ($_POST as $key => $valu) {
//do something with the variables
}
Also, don't use $_REQUEST unless you really want to check $_GET, $_POST and $_COOKIE. Use the proper array when accessing variables or people can send data you don't expect.

Categories