Good night, I have a code that substitutes the data from the request and displays it, like this:
$client = User::find($data['$id']);
$execute = 'Send command ';
$execute .= $client->id;
dd($execute);
It return
^ "Send command 1"
Everything is working.
But I want that if I add a variable to the database, for example, like this
$client->id
, and call it, then I need the code to process it as a variable, and not as a string, how to do this, thanks)
Example:
(inside the variable $cliend in the database will be the following code:
$client->id
Code:
$client = DB::table('users')->where('id', $id)->value('id');
$execute = 'Send command ';
$execute .= $client;
dd($execute);
It is necessary that this variable be executed as a variable. and returned its value not from the database, but as in the first example
Having to store variable names into the database is extremely bad practice although PHP does natively support variables variable.
In your case, I do not see how you could implement this against an object without having to eval some additional code against, assumingly, untrusted user input.
I would first suggest redesigning your database logic to avoid this but if this is necessary or/and your data is controlled then here is a solution:
// Your object you want to access the value of
$client = (object) ['id' => 1];
// Data from your SQL statement that stores that variable name
$databaseValue = '$client->id';
// Eval and store result as variable
eval("\$value = {$databaseValue};");
// Result: Send command 1
echo "Send command {$value}";
See it working over at 3v4l.org
Some additional thoughts, you could potentially use regex to capture that the stored data is indeed a variable and only grab the first match.
^\$(?:[a-z]||[A-Z])\S+
You can see an example of this over on 3v4l.org where we remove any potential bad stuff from the data but this is a very blacklisted approach and you should always look to take a whitelisted approach. Just hoping this helps down the line somewhere else.
For some explanation, please checkout regex101 where I added some examples how this could be easily escaped and is no way the ultimate solution.
Update: Here is another regex you could potentially use to narrow down this even further.
(?:\s|^)\$(?:[^\s]+?)(?:[a-z])+(?:->|$)?(?:[a-z]|[A-Z])+
Example and explanation can be found over at Regex101. PHP example can be found over at 3v4l.org (which remember is still never perfect).
Related
First of all I have checked the other suggested answers and I'm not certain whether they actually cover the question I've got. I'm very new to PHP so please forgive me if I am asking what sounds like a stupid question.
I have a php file which is called from another php file with a parameter
I understand how this works in the calling file.
I don't understand how to extract the parameter contents into a variable at the target end.
Let's say for a moment that in the address bar of the browser I get this:
targetfilename?parameter=Fred_hippy
I now want to pass "Fred" and "hippy" to a two-element array inside targetname.php. That's it, nothing else. (I said I was new to PHP.)
I think the way to do this is:
$file = substr($targetfilename, 13);
$name = explode("_", $file);
Is that correct please? If not could somebody tweak it please?
Thanks.
All parameters (everything after the ?) are returned as $_GET or $_POST array. If you are typing into the address bar (as opposed to using a FORM) then it is always GET. PHP makes it really easy:
$parameter = $_GET['parameter'];
$name = explode("_",$parameter);
That leaves $name[0] = 'Fred' and $name[1] = 'hippy'.
In older versions of PHP, the $_GET to variable assignment was done automagically, which was very useful but also opened a lot of possible security issues, so that has been deprecated.
Another note based on comments. An alternative to:
targetfilename?parameter=Fred_hippy
is
targetfilename?name=Fred&status=hippy
which would be read in PHP as:
$name = $_GET['name'];
$status = $_GET['status'];
with no explode() needed. Basically, PHP understands the standard protocol for sending parameters via GET & POST and takes care of a lot of the details for you.
I have following code:
<?php
$param = $_GET['param'];
echo $param;
?>
when I use it like:
mysite.com/test.php?param=2+2
or
mysite.com/test.php?param="2+2"
it prints
2 2
not
4
I tried also eval - neither worked
+ is encoded as a space in query strings. To have an actual addition sign in your string, you should use %2B.
However, it should be noted this will not perform the actual addition. I do not believe it is possible to perform actual addition inside the query string.
Now. I would like to stress to avoid using eval as if it's your answer, you're asking the wrong question. It's a very dangerous piece of work. It can create more problems than it's worth, as per the manual specifications on this function:
The eval() language construct is very dangerous because it allows
execution of arbitrary PHP code. Its use thus is discouraged. If you
have carefully verified that there is no other option than to use this
construct, pay special attention not to pass any user provided data
into it without properly validating it beforehand.
So, everything that you wish to pass into eval should be screened against a very.. Very strict criteria, stripping out other function calls and other possible malicious calls & ensure that 100% that what you are passing into eval is exactly as you need it. No more, no less.
A very basic scenario for your problem would be:
if (!isset($_GET['Param'])){
$Append = urlencode("2+2");
header("Location: index.php?Param=".$Append);
}
$Code_To_Eval = '$Result = '.$_GET['Param'].';';
eval($Code_To_Eval);
echo $Result;
The first lines 1 through to 4 are only showing how to correctly pass a character such a plus symbol, the other lines of code are working with the data string. & as #andreiP stated:
Unless I'm not mistaking the "+" is used for URL encoding, so it would
be translated to a %, which further translates to a white space.
That's why you're getting 2 2
This is correct. It explains why you are getting your current output & please note using:
echo urldecode($_GET['Param']);
after encoding it will bring you back to your original output to which you want to avoid.
I would highly suggest looking into an alternative before using what i've posted
Okay, so I want to know if there are any (other, and preferably easy) ways to convert a string to a variable.
My code, which works, is as follows:
echo eval('return $'. $date . ';');
$date contains a string. Now, the code works, and I'm fine with leaving it as it is if nothing else, since $date is called from a pre-programmed class declaration:
Time::Format($id = 'id', $name = 'name', $date = 'date->format(Y)');
The reason I ask is due to the PHP official disclaimer/warning on its use of: The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.
As such, I think I am safe in using it, as there is no user-inputted data being eval'd by PHP, it's a string I set as the coder, but I would like a second opinion its use, as well as any input on another simple method to do this (since, if I can avoid it, I'd rather not use a complicated and possibly long block of code to accomplish something that can be done simply (provided it is safe to do quick and dirty).
PHP's variable variables will help you out here. You can use them by prefixing the variable with another dollar sign:
$foo = "Hello, world!";
$bar = "foo";
echo $$bar; // outputs "Hello, world!"
i would like to know if there is a possible injection of code (or any other security risk like reading memory blocks that you weren't supposed to etc...) in the following scenario, where unsanitized data from HTTP GET is used in code of PHP as KEY of array.
This supposed to transform letters to their order in alphabet. a to 1, b to 2, c to 3 .... HTTP GET "letter" variable supposed to have values letters, but as you can understand anything can be send to server:
HTML:
http://www.example.com/index.php?letter=[anything in here, as dirty it can gets]
PHP:
$dirty_data = $_GET['letter'];
echo "Your letter's order in alphabet is:".Letter2Number($dirty_data);
function Letter2Number($my_array_key)
{
$alphabet = array("a" => "1", "b" => "2", "c" => "3");
// And now we will eventually use HTTP GET unsanitized data
// as a KEY for a PHP array... Yikes!
return $alphabet[$my_array_key];
}
Questions:
Do you see any security risks?
How can i sanitize HTTP data to be able use them in code as KEY of an array?
How bad is this practice?
I can't see any problems with this practice. Anything you... errr... get from $_GET is a string. It will not pose any security threat whatsoever unless you call eval() on it. Any string can be used as a PHP array key, and it will have no adverse effects whatsoever (although if you use a really long string, obviously this will impact memory usage).
It's not like SQL, where you are building code to be executed later - your PHP code has already been built and is executing, and the only way you can modify the way in which it executes at runtime is by calling eval() or include()/require().
EDIT
Thinking about it there are a couple of other ways, apart from eval() and include(), that this input could affect the operation of the script, and that is to use the supplied string to dynamically call a function/method, instantiate an object, or in variable variables/properties. So for example:
$userdata = $_GET['userdata'];
$userdata();
// ...or...
$obj->$userdata();
// ...or...
$obj = new $userdata();
// ...or...
$someval = ${'a_var_called_'.$userdata};
// ...or...
$someval = $obj->$userdata;
...would be a very bad idea, if you were to do it with sanitizing $userdata first.
However, for what you are doing, you do not need to worry about it.
Any external received from GET, POST, FILE, etc. should be treated as filthy and sanitized appropriately. How and when you sanitize depends on when the data is going to be used. If you are going to store it to the DB, it needs to be escaped (to avoid SQL Injection. See PDO for example). Escaping is also necessary when running an OS command based on user data such as eval or attempting to read a file (like reading ../../../etc/passwd). If it's going to be displayed back to the user, it needs to be encoded (to avoid html injection. See htmlspecialchars for example).
You don't have to sanitize data for the way you are using it above. In fact, you should only escape for storage and encode for display, but otherwise leave data raw. Of course, you may want to perform your own validation on the data. For example, you may want dirty_data to be in the list of [a, b, c] and if not echo it back to the user. Then you would have to encode it.
Any well-known OS is not going to have a problem even if the user managed to attempt to read an invalid memory address.
Presumably this array's contents are meant to be publicly accessible in this way, so no.
Run it through array_key_exists()
Probably at least a little bad. Maybe there's something that could be done with a malformed multibyte string or something that could trigger some kind of overflow on a poorly-configured server... but that's pure (ignorant) speculation on my part.
I have part of a query string that I want to make a replacement in. I want to use preg_replace but am kind of hung up on the regex.
Can someone please help? What I need replaced are the GET vars.
Here is the string:
bikeType=G&nikeNumber=4351
PHP has a convenient function to parse query strings: parse_str(). You might want to take a look at that or provide more details as your question isn't exactly clear.
You can use parse_str as was mentioned already.
In addition, if you want to put them back into a query string you can use http_build_query
Example:
parse_str('bikeType=G&nikeNumber=4351', $params);
$params['bikeType'] = 'F';
$params['nikeNumber'] = '1234';
echo http_build_query($params, '', '&');
Output
bikeType=F&nikeNumber=1234
Please note that you should not use parse_str without the second argument (or at least not with some consideration). When you leave it out, PHP will create variables from the query params in the current scope. That can lead to security issues. Malicious users could use it to overwrite other variables, e.g.
// somewhere in your code you assigned the current user's role
$role = $_SESSION['currentUser']['role'];
// later in the same scope you do
parse_str('bikeType=G&nikeNumber=4351&role=admin');
// somewhere later you check if the user is an admin
if($role === "admin") { /* trouble */ }
Another note: using the third param for http_build_query is recommended, because the proper encoding for an ampersand is &. Some validators will complain if you put just the & in there.