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 Documentation Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php