Eval is dead! Long live Eval!

I’m Lachlan Donald, the new guy here at SitePoint. I’ll be helping out with PHP blog content along with the other guys here.

Eval seems to be a hot topic of discussion lately, especially in light of the recent vBulletin exploits and past exploits in common applications such as phpMyAdmin. Eval is one of the functions in PHP which can execute arbitrary code. Generally eval is used either by inexperienced programmers for a variety of misguided reasons, or by people attempting to push the boundries of PHP. What inspired me to post this article was this quote from Rasmus Lerdorf, creator of PHP:

If eval() is the answer, you’re almost certainly asking the wrong question.

Perhaps it’s just my argumentative nature, but when people use that quote I always wonder whether there are any common problems that are only solvable by using eval. Before I get into the nitty-gritty details, a brief recap of what eval actually does from the PHP manual:

mixed eval ( string code_str )

eval() evaluates the string given in code_str as PHP code.
Among other things, this can be useful for storing code in a database
text field for later execution.

To an inexperienced programmer this might sound like a fantastic idea, allowing for snippets of code to be stored in a database and executed depending on other criteria stored along with the record. In practice, writing an application that interprets pieces of code that are stored along with user data is asking for trouble. Take this example, which calls a function and assigns the result to a variable.


function getTemplate($tpl) { return "a template"; }

eval('$content = getTemplate("'.$_GET['tpl'].'");');

With Magic Quotes disabled this creates a huge security hole, as all an attacker must do to execute arbitrary php code is insert it into the request url. For instance, the following query string causes the contents of the current directory to be output to the screen.

/eval.php?tpl=%22);+passthru(%22ls+-al

Naturally this example is contrived, but its very similar to the code that was the target of recent attacks on PHPBB and VBulletin. This sort of code is generally a result of lazy programming or bad design. Some more advanced uses of Eval are less dangerous and more interesting, for instance:

Please feel free to post feedback or examples of good or bad use of eval.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • joshie

    allowing dynamic content to be stored in a blog or other cms entry, or page template. (for instance, breadcrumb links in a template page)

  • Ghandi

    I myself use eval() to input information retrieved from the database into a template. No variables are passed into eval via $_GET or $_POST. I imagine this would not create a security threat.

  • http://www.sitepoint.com/ mmj

    I use eval() to call a static method of a given class $classname.

    For instance,


    $classname = 'someclass';
    eval('$instance = ' . $classname . '::method();');

    But I discovered today (thanks Lachlan) that this can be achieved using call_user_func.


    // Type 2: Static class method call
    call_user_func(array('MyClass', 'myCallbackMethod'));

    More Information About Callback Types

  • http://www.jeroenmulder.com/ JMulder

    I couldn’t agree more. Luckily, back in the day, I had a mentor who would repeat “eval() is the root of all evil” every single day ;)

    In my experience the people that are learning need such direct comments to keep them from using it. Let’s face it, we all know that in some rare cases eval() might be a viable solution, but only if you’re an experienced programmer and know what you’re doing. If you’re still learning, I’ll keep yelling at you for using eval() — nothing personal. :P

  • http://timvw.madoka.be timvw

    using eval on code stored in the database is not a problem per definition.

    the problem is as usual: the lazy/dumb/unknowing programmer that uses eval on insecure/unvalidated data.

  • Nico Edtinger

    Always when I read phpBB I think “who cares – they can’t code anyway”. If someone has read the comments they made after their last big security bug, saying it’s a PHP problem, he knows what I mean. They’re just hacking code. Like the phpnuke guys. And they make PHP look bad, which it isn’t.

    eval() can be quite handy. But if someone puts some userdata in it without even checking I don’t see a problem in eval(), but in the programming challenges.

    I know I wrote a rss-parser which uses eval() and got some fame for it and this parser doesn’t check the input data enough. But the parser was meant for trusted sources. I’ve only used it that way.

    b4n

  • Greg Beaver

    One hackish use of eval that is currently the only way out is if your software uses both PHP 4 and PHP 5, and you would like to clone an object, the only way to do this in php 5 is with the “clone” keyword – but this is a parse error in php 4. The solution is:

    class myClass
    {
    function myClone()
    {
    if (version_compare(zend_version(), ’2.0′, ‘>=’)) {
    return eval(‘clone $this’);
    } else {
    return $this;
    }
    }
    }

    Of course, I prefer to create two files, one for php 4 and one for php 5, and then use the power of include_once.

    There are several reasons this is better.

    1) if the code is executed with any frequency, eval()ed code is about 30% slower than normal code, even after the initial declaration.
    2) errors in an eval() statement look odd, and can make debugging a total nightmare, as the code is by nature transient.

    Greg

  • http://www.oscarm.org/ omerida

    I’ve replaced eval with call_user_func for static method calls as well and ran into one glitch – call_user_func can’t return references in PHP4, see the comments at http://www.php.net/call_user_func

  • Dr Livingston

    lazy programming? bad programming? it’s these sorts of programmers that should think about getting another job in my view

    yer, you are spot on there. eval() is evil and the work of the devil :eek2: alas due to the nature of the language, sometimes the need is called for.

  • Nate Cavanaugh

    Coming from someone who has never used eval(), I still havent seen any display that eval is evil, nor that it has any use.

    The security problem isnt eval. It’s accepting unfiltered, unquestioned data.

    Now seriously, who write’s code dependent upon magic quotes, without first at least running a check to see if it’s on?

    If you’re using eval() on your own code, and not depending upon data from the user, Im not sure that is insecure.

    The problem is the input source, not the function, IMHO…

  • Anonymous

    I don’ t think so that eval is an evil, instead people doesn’ t know how to secure their applications, they don’ t really filter the data they receive…

  • Anonymous

    I find eval() essential for invoking all manor of external programs on the Windows platform. Steve Ballmer has assured us that Microsoft has the most secure software in the world so I can only assume I have nothing to worry about.

  • http://www.deanclatworthy.com Dean C

    I use eval in my template engine to parse php variables into html code. I always clean every variable that possibly is passed via $_POST or $_REQUEST. Also just to clear up, I’m pretty sure that there was no security hole in vBulletin recently related to the eval function.

  • drumdance

    eval() would be very useful in e.g. WordPress – that way I could write PHP expressions in my posts. The alternative is to cache the post in the filesystem and include(). I’ve thought about writing a plug-in to do this.

    But it certainly shouldn’t be used in comments.

  • Itshim

    I learned PHP from books, and I guess I was lucky in the fact that none of those books ever introduced me to eval(). By the time I had gotten around to learning about it I was able to recognize the security problems with it.

    I have now been using PHP for about two years, and I understand I am not writing the most advanced code, but I have yet to run into a situation where eval() was needed.

    For this reason I have always considered eval() a hack, and until I am writing cutting edge applications I believe I will keep it in that category.

  • Cyril Doussin

    Eval being almost useless and potentially representing a very good way to introduce security holes, I would disable eval by default in php and make it a php.ini setting.
    This would probably prevent beginners from using it and force them to have a second look at the manual to find other ways to achieve what they want to do …

  • Lachlan

    I use eval in my template engine to parse php variables into html code. I always clean every variable that possibly is passed via $_POST or $_REQUEST. Also just to clear up, I’m pretty sure that there was no security hole in vBulletin recently related to the eval function.

    The recent vBulletin exploit used eval to execute arbritrary code, so did the recent PHPBB exploit. Both of those used eval for templating. I would be very nervous about using that technique for templating, a much safer approach is to use preg_match and str_replace to just replace variables in the page. A more comprehensive approach (which I use in my projects) is Brian Lozier’s Template class.

  • http://www.phpism.net Maarten Manders

    I’m convinced that eval can’t be needed in any regular PHP application. It’s mostly used by novices who are trying to build something fancy and particularly smart. The problem is: eval() is never smart, since there always is another (ultimately smarter) solution out there.

    I have yet to see a reasonable application for eval(). Those two examples above aren’t reasonable to me: Creating the mocks with eval() isn’t the smartest idea, as well as using eval() for that clone() hack. Allthough those (and many other) examples seem to be safe from abuse I don’t think that they’re elegant and should be omitted. Apart from the (serious) security issues: Eval constructs are hard to read, hard to debug, can pull down your whole application and last but not least they’re just bad style because the PHP script and it’s programmer lose control of what’s getting executed.

    There’s nothing wrong with code generation though, e.g. for caching issues. That code is stored in files and included later on. However, when code is generated in every PHP instance, there must be something wrong with the concept.

  • http://www.jonhehir.com Young Twig

    Like a lot of others have said, I’ve still not found a reason to use eval in any of my code. I’ve written plenty of code, but never even found a reason for it.

  • EViL3

    These type of scare mongering posts can get annoying – instead or preaching, try teaching – when telling readers something is wrong, give examples of do’s and don’t and possible alternatives.

    I don’t agree that eval is the root of all evil, but I would go along with Maarten in saying its an easy way to leave huge security holes and complicate code if mis-used.

    But it does have it uses and can be very productive – a while back I had to create an XML feed parser for a client who uses php4 (so no SimpleXML), I reduced a 500 line script downto 50 lines, the script became cleaner, more manageable and yet still remained secure.

  • Nico Edtinger

    Ok some people never thought they’d need eval. Where I found it usefull in PHP5 is with error handling and __autoload().

    As you might know you can’t throw an exception in __autoload(). But it can be handy to have something like

    try {
    $foo = new Foobar();
    } catch(Exception $e) {
    // …
    }

    Now if you can’t find a file with this class in __autoload() you can create a class throwing an exception in the contructor. Maybe I just haven’t seen the “create_class” function in PHP5, but AFAIK eval is the only way to create such a class.

    b4n

  • php_man

    How would you do conditionals in a template system (ifs, loops) without using eval() at some point?

  • Anonymous Coward

    Testing out this bb code.


    foreach ($comments as $comment) {
    echo "Comment: $comment
    ";
    }

  • ca_redwards

    While I’m no PHP expert, I use JavaScript’s eval() function to build very elaborate HTML constructs with minimal client-side code. In my (only) article I wrote on here, I described how my tiny library (4K) churns out over 200 intuitively named functions that can generate any desired HTML tag, container, attribute or CSS style. My use of a single eval() is vital to very quickly defining all those functions in under 4K.

  • http://www.yourmusicforums.com duuudie

    I recently worked on a cms-like application. The admin could create as many pages as he wanted, everything was stored in the db, you know how it works.

    Then I got asked to give the ability to the admin to add php code to his pages. I had no solution but to use eval() since the data of any given pages is stored in the db.

    If someone know of a better solution to do this, I’m keen on learning this new trick :)

  • Berislav Lopac

    Very briefly, I yet have to see an eval() use that can’t be easily resolved with variable variables and callback functions.

  • php_man

    Berislav Lopac, and others that keep saying there is no use to eval – how would you propose doing a template system that uses if/elseif/loop etc?

  • Lachlan

    Preventing security holes in templating systems is a particularly challanging problem. I personally use the templating system described in Beyond the Template Engine. This allows for php to be included in templates which are included using the require statement. Variables are set on the template object and then imported into the templates symbol table with the extract function. This approach provides more protection from arbitrary code being inserted and executed, as so often happens with template systems that use eval.

    The key to using eval safely is to never allow user data into eval. Ever. Not even if you think it has been cleaned. It’s too easy to make mistakes, as the exploits in phpBB and vBulletin prove.

  • porneL

    @Greg Beaver: No, you don’t need eval for this. Use clone() (like function, with parens) and write that function for php4.

  • http://ptprophecy.com Daijoubu

    One thing is enough to make eval() evil: It’s awfully slow
    Yet there’s peoples who call this douzens of time in their templating engine…

  • http://doitslower.com/ lartexpert

    eval() in templates is the kind of thing that can give you nightmares. If some functionality is needed in a template engine, you can code for this in your template syntax. Using include() or require() for templates is ok, in theory, but remember that you’re still executing whatever code is in those templates, so you’re back with the same problem.

    If you need $SOME_WHIZZY_FUNCTION in your CMS, then code it into your CMS.

    I have used eval() for one thing though – checking for the existence of a function (e.g. image library support). Better error handling removes the need for this though.

  • Lewis

    I currently use eval() for a template system that allows the admin to include raw php in their templates. I cannot see any better way of doing this and the only security threat would be the admin, and why would he want to ruin his own website anyway? If you know a better way of doing this please email lewis[nospam]wright[@t]gmail[dot]com

  • Lewis

    For those who use eval() to allow execution of PHP code in their templates. When loading your template try using…


    ob_start();
    include("file.php");
    $template = ob_get_contents();
    ob_end_clean();

    Which will execute any PHP and also return the template to $template. This is faster and supposedly more secure.

  • http://www.spiffdog.com Spiff Dog

    I’m not a PHP programmer, myself. However, old ASP had the “Execute()” method that was just as problematic in the hands of a new/bad programmer.

    Eval() in PHP and Execute() in ASP are just tools. Don’t use a hammer to drive a bolt and you’ll be fine. Use the tool for what it was intended for and always, always, always validate your data (in fact, once you done that, validate it again.. hehe).

    Remember kids, methods don’t kill security. Bad/newb programmers kill security. :)

  • Gaetano Giunta

    Never trust code to be passed to eval: 1st.
    Clean it up: 2nd.
    Do not trust your clean-up routines: 3d.

    I speak from experience: I have been hacking on the php-xmlrpc lib for literally years, and I tought the lib had xml input fed to eval() escaped really solid.

    I was bitten in the a***.

    To wannabe gurus one extra pearl of wisdom: NEVER trust data from the db, either.
    Cross site scripting attacks are all about having privileged users run code unprivileged users have written. And this includes SQL scripts tha will put nasty php inside the armored database.
    If any kind of data in the db is the (indirect) result of a web input, clean it up before inserting it into the db and clean it up after extracting it from the db.

  • Pingback: SitePoint Blogs » Blog Archive » How Readable is Your PHP?

  • sadi

    I faced a of problem using eval() with javascrip. If there are php or
    simple HTML code then eval is simply ok with me.But when ever i have
    to deal with javascript i always found myself in shit. Can anyone
    give me any way to use javascript contained code in eval()?I am
    running behind my time in my project

  • C~

    I used Eval for dynamically loading code into an ircbot i wrote. As all the modules had to be classes there didn’t seem to be a way to add functions to existing classes so i had to use Eval to creat a new class and kinda add it to my existing one.

  • sina salek

    i usually use eval to craete complicated classes. it really decrease number of codes, and help to make inherit from main class easily and with less code.
    but the big problem is, eval is really slow with loops.

  • http://h97v.searchik.info ma214zda

    c749t

  • http://idownload.ws iDownload

    Very interesting. But completely disable eval it’s not a good idea. It must be the way to limit it functionality using black and white list of functions. I am searching for it now… have anybody idea how to do that?

  • Jim

    What I am using eval() for is to do error checking based on some comparison/condition/whatever that is determined when calling the error checking function.

    In other words, I would call check_error($user_input,$formula). And then I can have the conditional formula be something like “%x > 10″ or “strtoupper(%x)==”ABC”"… And %x is replaced with $user_input. Totally arbitrary examples, but the point is I as the programmer using the function need full latitude in choosing the conditional formula.

    How else can I do this other than by using eval()? And what is the best way to cleanse the user input?

    Thanks – Jim

  • Lachlan

    Hi Jim,

    The cardinal sin with eval is letting it anywhere near user data. With that system you could very easily end up with a bug that resulted in users being able to inject php into your system, for instance by making %x=”system(‘rm -rf /’); 20′.

    It looks like you have a straight-up validation problem, something solved by WACT’s form validation library (http://www.phpwact.org/wact/form_validation), or Zend or Symphony. Basically you want to move all of those snippets of eval’d code into small, light objects which you use to validate your user data.

  • Jim

    Thanks. Zend Form looks like it might have the potential to what I need to do, though I’m not sure there is any open ended conditional (haven’t looked extensively enough).

    Pre-written packages aside, I’d be curious to know what PHP function alternatives there are, and how someone can get around something like addslashes(). For example the system call injection didn’t work (of course, I didn’t test using that exact system call) when I used addslashes.

    Thanks – Jim

  • Criss

    Eval is a nice example of a thing that should never enter a scripting language which is meant to be secure.

    It is incredible that nobody of the PHP developers has set an option to disable it (and also, it cannot be disabled with disable_function directive).

    Along with a interesting toy for academic exercises, his is a real gift for hackers! Wowwwww!

  • Gavin Engel

    Did you discover a way to limit functions to eval by using a whitelist/blacklist?