While I'm......*grossly* against the /e switch (or eval()s in general) at all (and its use with tainted sources even moreso), I realize my whinning and moaning isn't going to change the fact /e and eval() exist and are used. But here's a thought...
How about a /E switch to preg_replace which would function like /e except that it temporarily enables safe_mode. Similarly eval() could be extended with a second parameter that does the same. I realize safe_mode is generally intended for sysadmins to protect themselves from malicious content authors, but why not use this functionality at the content level to protect from malicious clients? There *might* be a need to have an eval.* version of the safe_mode ini options to specify how much is (dis)allowed when in eval-safe_mode. I havn't thought through the implications of doing this, but it seems worth exploring. -Pollita Cross-Posting to php-dev "James E. Flemer" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED]... > Just one more example. Even when using double quotes, it > is possible to execute code: > > <?php > $a = '___! ${`rm -rf /tmp/sess_*`} !___'; > $b = preg_replace("/!(.*)!/e", "print(\"\\1\");", $a); > ?> > > Again, assume $a comes from a tainted source. > > -James > > On Mon, 3 Feb 2003, James E. Flemer wrote: > > > A warning about preg_replace() command needs to be added to > > the docs page for this command. The preg_replace() command > > can use the "/e" modifier to have the "replacement" be > > eval()d by PHP, just like perl. > > > > There is a high potential for exploitable PHP code if a > > programmer uses the /e modifier and does not use quotes > > around the back references (backrefs). Without quotes, > > arbitrary commands may be executed by using the backtick > > operator. Other commands may be executed as well, but are > > more difficult, since addslashes() prevents the characters > > ['"\\\0] from being used. > > > > An clear and explicit warning should be added to the doc > > page for preg_replace, indicating the backrefs must always > > be quoted. Single quotes are preferable, since double > > quotes allow variable expansion. > > > > See the messages below for examples of how this may be > > exploited. (Assume that $a comes from an untrusted source, > > i.e. a get/post/cookie/header variable.) > > > > -James > > > > ---------- Forwarded message ---------- > > Date: Mon, 3 Feb 2003 01:04:23 -0500 (EST) > > From: James E. Flemer <[EMAIL PROTECTED]> > > To: [EMAIL PROTECTED] > > Subject: Re: [PHP-DEV] preg_replace oddity [exploitable] > > > > I found a more evil example: > > > > <?php > > $a = "___! `rm -rf /tmp/sess_*` !___"; > > $b = preg_replace("/!(.*)!/e", "print(\\1);", $a); > > ?> > > > > This happily executes "rm -rf /tmp/sess_*". I will not > > give out more examples, but if one examines the code for > > addslashes() it is quite obvious what you can an cannot do > > here. Thus it is clearly a Bad Thing for someone to use > > preg_replace with the /e modifier and not use quotes around > > the \\n or $n backrefs. > > > > The docs should be updated to include a very noticeable > > warning about this hole. I am contemplating possible > > solutions for this problem... > > > > Also as a side note, it does not seem to be possible to use > > 'echo' as part of the expression, print must be used. (Yes > > I know why, just pointing it out.) > > > > -James > > > > > > On Thu, 30 Jan 2003, James E. Flemer wrote: > > > > > Can someone explain what is going on here: > > > > > > --- foo.php --- > > > <?php > > > $a = "___! 52); echo(42 !___"; > > > $b = preg_replace("/!(.*)!/e", "print(\\1);", $a); > > > print("\n---\na: $a\nb: $b\n"); > > > ?> > > > --- end --- > > > --- output --- > > > 52 > > > --- > > > a: ___! 52); echo(42 !___ > > > b: ___1___ > > > --- end --- > > > > > > I understand that one is supposed to use single quotes > > > around the \\1 in the above preg_replace. But what happens > > > when they do not? Clearly the echo(42); is not executed, > > > and it is not printed by print(). Even more interesting is > > > if you put something like echo(\"42 in $a, then you get a > > > bunch of errors including: > > > Fatal error - Failed evaluating code: > > > print( 52); echo(\"42 ); > > > > > > It seems like preg_replace() is doing some strange things, > > > and might be something that could be exploitable if a > > > remote user can supply the first argument, and the second > > > argument does not enclose \\n options. > > > > > > -James > > > > > > > -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php