Re: preg_replace() docs need expliot warning
| From: | pollita@php.net | Date: | Sat, 08 Feb 2003 05:39:58 +0000 |
| Subject: | Re: preg_replace() docs need expliot warning | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-94104@lists.php.net to get a copy of this message | ||
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" <jflemer@acm.jhu.edu> wrote in message
news:Pine.LNX.4.33L2.0302072305090.16866-100000@centaur.acm.jhu.edu...
> 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 <jflemer@acm.jhu.edu>
> > To: php-dev@lists.php.net
> > 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
> >
> >
> >
>