I know some people may just respond "never" as long as there's user input. But suppose I have something like this:
$version = $_REQUEST['version'];
$test = 'return $version > 3;';
$success = eval($test);
This is obviously a simplified case, but is there anything that a user can input as version to get this to do something malicious? If I restrict the type of strings that $test can take on to comparing the value of certain variables to other variables, is there any way anybody can see to exploit that?
Edit
I've tried running the following script on the server and nothing happens:
<?php
$version = "exec('mkdir test') + 4";
$teststr = '$version > 3;';
$result = eval('return ' . $teststr);
var_dump($result);
?>
all I get is bool(false). No new directory is created. If I have a line that actually calls exec('mkdir test') before that, it actually does create the directory. It seems to be working correctly, in that it's just comparing a string converted to a number to another number and finding out the result is false.
Ohhhh boy!
$version = "exec('rm-rf/...') + 4"; // Return 4 so the return value is "true"
// after all, we're gentlemen!
$test = "return $version > 3";
eval($test);
:)
You would have to do at least a filter_var() or is_numeric() on the input value in this case.
By the way, the way you use eval (assigning its result to $success) doesn't work in PHP. You would have to put the assignment into the eval()ed string.
If you do this. Only accept ints.
If you must accept strings, don't.
If you still think you must. Don't!
And lastly, if you still, after that, think you need strings. JUST DON'T!
yes, anything. I would use $version = (int)$_REQUEST['version']; to validate the data.
You need to be more precise with your definitions of "malicious" or "safe". Consider for example
exec("rm -rf /");
echo "enlarge your rolex!";
while(true) echo "*";
all three snippets are "malicious" from the common sense point of view, however technically they are totally different. Protection techniques that may apply to #1, won't work with other two and vice versa.
The way to make this safe would be to ensure that $version is a number BEFORE you try to eval.
Use this code to remove everything except numbers (0-9): preg_replace('/[^0-9]+/', '', $version);
Related
eval("echo {$row11['incentive']};");
In my table column named incentive , I have values stored like a string for eg. '($workshop_sales*0.005)' and there are mutliple kind of formula stored for calculation of incentive.
I have result generated using above code in php but when I am going to store its value in any variable then it is not getting stored.
How can I store its result? is it possible or not ??
Instead of echoing inside the eval-ed code, return the value:
<?php
$workshop_sales = rand(1000, 9999);
$row11['incentive'] = '($workshop_sales*0.005)';
$result = eval("return {$row11['incentive']};");
var_dump($result);
From the docs:
eval() returns NULL unless return is called in the evaluated code, ...
And obvious eval is dangerous-statement (also from the docs):
Caution 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.
simply you can assign the variable to the new value inside the eval function
and use your variable later
for example :
eval('$result = "2";');
echo $result;
this will print out the value of the $result variable
PS,
you have to take a look at what #yoshi had mentioned about the dangerous of using eval
Assumption:
$workshop_sales = 15;
$row11['incentive'] = '($workshop_sales*0.005)';
Variant 1 Saving result directly (unsecure):
$foo = eval("return {$row11['incentive']};");
echo $foo; //Outputs 0.075
Variant 2 Replace variable before (should be pretty secure)
function do_maths($expression) {
eval('$o = ' . preg_replace('/[^0-9\+\-\*\/\(\)\.]/', '', $expression) . ';');
return $o;
}
//Replace Variable with value before
$pure = str_replace("\$workshop_sales", $workshop_sales, $row11['incentive']);
//$pure is now (15*0.005)
//Interpret $pure
$foo = do_maths($pure);
echo $foo; // Outputs 0.075
But be careful with eval(), it is evil.
Further information on When is eval evil in php?
The main problems with eval() are:
Potential unsafe input. Passing an untrusted parameter is a way to fail. It is often not a trivial task to make sure that a parameter (or part of it) is fully trusted.
Trickiness. Using eval() makes code clever, therefore more difficult to follow. To quote Brian Kernighan "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it"
I know that a lot would be against using eval, but I do know the
dangers. Everything I use eval for will be for my own use and no user
input will be used.
I'm trying to grab some content by using $Content = "Content here"; But I also need to use eval($content); as the value of content will be containing php code that i'll need to execute. I also want to be able to use eval as a value. So for example using $Example = eval($content);
As I said, I know it can be dangerous, But its a risk im going to take to handle it. I'd just like my question to be answered. Thank you in advance
Here is an example of use of eval that returns a value:
php > $a = 'return 3+3;';
php > $b = eval($a);
php > echo $b;
6
As written in a comment, read always the documentation. In this case, the page about eval.
I'm doing something where I need to store if statements in a mysql database. I need to pull these statements and use them, each one is an algorithm that I'm testing. I know you can store an if statement in a variable like "$abc = $x > 1 && $f == 1;" and if you run if($abc) {} it will work, I figured I could do the same here, but when I run if($abc) with $abc being an if statement from the database it's not working, it's running the code within the if statement because $abc exists. Code is as follows...
$getAlgorithms = mysqli_query($mysql_connect, "SELECT * FROM `algorithms2`");
while($algorithms = mysqli_fetch_array($getAlgorithms)) {
$algorithmID = $algorithms['id'];
$algorithm = $algorithms['algorithm'];
if($algorithm) {
echo("HELLO WORLD");
}
}
dummy example of what $algorithms['algorithm']; would pull: $r >= $var_x && $z <= $var_y && $lz >= $var_c
I'd really appreciate the help, this is very important. If you have any questions please ask.
NOTE: This is a 100% internal platform
Your code needs to make use of eval() to work as-is:
$getAlgorithms = mysqli_query($mysql_connect, "SELECT * FROM `algorithms2`");
while($algorithms = mysqli_fetch_array($getAlgorithms)) {
$algorithmID = $algorithms['id'];
$algorithm = $algorithms['algorithm'];
if(eval("return {$algorithm};")) {
echo("HELLO WORLD");
}
}
However, executing arbitrary code from an external source (the database) is potentially a horrible security risk: just because you're expecting $algorithm to be a benign arithmetic expression doesn't mean that it can't be a malicious function call or other statement, for example if someone can enter system('rm -rf /') as the algorithm into your database, you're probably going to have a bad day.
Without knowing the precise problem you're trying to solve, it's hard to suggest a better solution, but I'd favour putting the "algorithms" in an array or other hard-coded data-structure within your code rather than the database, it's far safer as anyone who can alter that list can already execute arbitrary code.
For further reference: http://php.net/manual/en/function.eval.php
Sounds like you're looking for eval(), but note that it is especially dangerous to use if there's any chance someone besides you will be creating the strings. There is probably a better, safer way to achieve whatever it is you are trying to do here.
Store the If condion in your db as string. And then execute it using eval() php function .
usage
mixed eval ( string $code )
PHP eval documentation
I'm very new to php .I want to convert the string to integer value.
I used following code to convert
$val='(100*2)';
echo (int)($val); //This will showing output as 0
But echo (int)((100*2)); /This will showing output as 200
Please help me any one to solve this .Thanks advance
(int)($val) evaluates to 0 because $val's value is not a numeric string (ie one that can be directly cast to a number).
If you really need this kind of functionality, try eval():
$val='(100*2)';
echo (int)($val); //This will showing output as 0
eval('$newval='.$val.';');
echo $newval;
But be warned: eval() can be dangerous!
From http://php.net/manual/en/function.eval.php:
Caution
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.
EDIT: Added .';' to eval parameter to make it a legit php instruction.
The most common suggestion will be - evaluate your string as PHP code, like:
$val = '(100*2)';
eval('$val = '.$val.';');
-but that's unsafe, eval should be avoided as long as possible.
Alternatively, there is bcParser for PHP, which can solve such issues. That's more safe than eval.
Finally, I doubt that you really need do such things - it seems you're solving some problem with wrong method (see XY-problem description)
You can do it using php eval function.
For that first you have to check for special characters and equation characters.
$val='(100*2)';
echo matheval($val);
function matheval($equation)
{
$equation = preg_replace("/[^0-9+\-.*\/()%]/","",$equation);
// fix percentage calcul when percentage value < 10
$equation = preg_replace("/([+-])([0-9]{1})(%)/","*(1\$1.0\$2)",$equation);
// calc percentage
$equation = preg_replace("/([+-])([0-9]+)(%)/","*(1\$1.\$2)",$equation);
// you could use str_replace on this next line
// if you really, really want to fine-tune this equation
$equation = preg_replace("/([0-9]+)(%)/",".\$1",$equation);
if ( $equation == "" )
{
$return = 0;
}
else
{
eval("\$return=" . $equation . ";" );
}
return $return;
}
I not recommended this, but you can use eval to suit your need
eval('$val = (100*2)');
echo intval($val);
Why not just:
$x=intval(100);// <- or an other value from the cleaned user input
$y=intval(2);
$val=$x*$y;
echo $val;
You are not giving a goal.
I can just explain why your code works like it does.
'(100*2)' is a String that cannot be converted to int, since it does contain other chars than numbers. Every String that cannot be converted will result in 0.
echo (int)(100*2) will work, because you use numbers and no strings. No need to convert, either, would work without the cast, just echo (100*2);
Remember PHP use loose typing. You will almost never need to convert types. This scenario is very set up.
I found this line of code in the Virtuemart plugin for Joomla on line 2136 in administrator/components/com_virtuemart/classes/ps_product.php
eval ("\$text_including_tax = \"$text_including_tax\";");
Scrap my previous answer.
The reason this eval() is here is shown in the php eval docs
This is what's happening:
$text_including_tax = '$tax ...';
...
$tax = 10;
...
eval ("\$text_including_tax = \"$text_including_tax\";");
At the end of this $text_including_tax is equal to:
"10 ..."
The single quotes prevents $tax being included in the original definition of the string. By using eval() it forces it to re-evaluate the string and include the value for $tax in the string.
I'm not a fan of this particular method, but it is correct. An alternative could be to use sprintf()
This code seems to be a bad way of forcing $text_including_tax to be a string.
The reason it is bad is because if $text_including_tax can contain data entered by a user it is possible for them to execute arbitrary code.
For example if $text_include_tax was set to equal:
"\"; readfile('/etc/passwd'); $_dummy = \"";
The eval would become:
eval("$text_include_tax = \"\"; readfile('/etc/passwd'); $_dummy =\"\";");
Giving the malicious user a dump of the passwd file.
A more correct method for doing this would be to cast the variable to string:
$text_include_tax = (string) $text_include_tax;
or even just:
$text_include_tax = "$text_include_tax";
If the data $text_include_tax is only an internal variable or contains already validated content there isn't a security risk. But it's still a bad way to convert a variable to a string because there are more obvious and safer ways to do it.
I'm guessing that it's a funky way of forcing $text_including_tax to be a string and not a number.
Perhaps it's an attempt to cast the variable as a string? Just a guess.
You will need the eval to get the tax rate into the output. Just moved this to a new server and for some reason this line caused a server error. As a quick fix, I changed it to:
//eval ("\$text_including_tax = \"$text_including_tax\";");
$text_including_tax = str_replace('$tax', $tax, $text_including_tax);
It is evaluating the string as PHP code.
But it seems to be making a variable equal itself? Weird.
As others have pointed out, it's code written by someone who doesn't know what on earth they're doing.
I also had a quick browse of the code to find a total lack of text escaping when putting HTML/URIs/etc. together. There are probably many injection holes to be found here in addition to the eval issues, if you can be bothered to audit it properly.
I would not want this code running on my server.
I've looked through that codebase before. It's some of the worst PHP I have seen.
I imagine you'd do that kind of thing to cover up mistakes you made somewhere else.
No, it's doing this:
Say $text_including_tax = "flat". This code evaluates the line:
$flat = "flat";
It isn't necessarily good, but I did use a technique like this once to suck all the MySQL variables in an array like this:
while ($row = mysql_fetch_assoc($result)) {
$var = $row["Variable_name"];
$$var = $row["Value"];
}