Sec Bug->Bug #72742 [Opn]: Stack-based buffer overflow vulnerability in php_check_specific_open_basedir
| From: | stas@php.net | Date: | Wed, 03 Aug 2016 06:44:56 +0000 |
| Subject: | Sec Bug->Bug #72742 [Opn]: Stack-based buffer overflow vulnerability in php_check_specific_open_basedir | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-202859@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72742&edit=1
ID: 72742
Updated by: stas@php.net
Reported by: tinduong at vnsecurity dot net
Summary: Stack-based buffer overflow vulnerability in
php_check_specific_open_basedir
Status: Open
-Type: Security
+Type: Bug
Package: Filesystem function related
PHP Version: 7.1Git-2016-08-03 (Git)
Block user comment: N
Private report: Y
New Comment:
This sounds rather artificial to be security issue.
Previous Comments:
------------------------------------------------------------------------
[2016-08-03 06:20:04] tinduong at vnsecurity dot net
Description:
------------
PHPAPI php_check_specific_open_basedir in php-src/main/fopen_wrappers.c has a integer overflow
vulnerability leads to buffer overflow if open_basedir is set.
<snippet php-src/main/fopen_wrappers.c:138>
```
PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path)
{
char resolved_name[MAXPATHLEN];
<...>
path_len = (int)strlen(path);
if (path_len > (MAXPATHLEN - 1)) { /*path_len can be overflow to negative value and pass this
check */
/* empty and too long paths are invalid */
return -1;
}
/* normalize and expand path */
if (expand_filepath(path, resolved_name) == NULL) {
return -1;
}
path_len = (int)strlen(resolved_name);
memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
```
</snippet>
PoC here using fopen, but it is not the only way since many functions are affected by open_basedir
I propose the following patch:
--- a/main/fopen_wrappers.c
+++ b/main/fopen_wrappers.c
@@ -154,7 +154,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
}
path_len = (int)strlen(path);
- if (path_len > (MAXPATHLEN - 1)) {
+ if (path_len <= 0 || path_len > (MAXPATHLEN - 1)) {
/* empty and too long paths are invalid */
return -1;
}
Test script:
---------------
<?php
ini_set('memory_limit', -1);
ini_set('open_basedir', '/');
fopen(str_repeat('a', 0xfffffff0), 'r');
?>
Expected result:
----------------
No crash
Actual result:
--------------
Stopped reason: SIGSEGV
#0 __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:37
#1 0x00000000007bf277 in xbuf_format_converter (xbuf=0x7fffffffac10, is_char=0x1, fmt=0xd70849
"s", ap=0x7fffffffad58)
at /home/vps/git/php-src/main/spprintf.c:814
#2 0x00000000007bf60d in vspprintf (pbuf=0x7fffffffac90, max_len=0x0,
format=0xd707f8 "File name is longer than the maximum allowed path length on this platform
(%d): %s", ap=0x7fffffffad58)
at /home/vps/git/php-src/main/spprintf.c:843
#3 0x00000000007b4f7b in php_verror (docref=0x0, params=0xd6eff1 "", type=0x2,
format=0xd707f8 "File name is longer than the maximum allowed path length on this platform
(%d): %s", args=0x7fffffffad58)
at /home/vps/git/php-src/main/main.c:756
#4 0x00000000007b59d8 in php_error_docref0 (docref=0x0, type=0x2,
format=0xd707f8 "File name is longer than the maximum allowed path length on this platform
(%d): %s")
at /home/vps/git/php-src/main/main.c:943
#5 0x00000000007c0144 in php_check_open_basedir_ex (path=0x7ffef5a00018 'a' <repeats
200 times>..., warn=0x1)
at /home/vps/git/php-src/main/fopen_wrappers.c:295
#6 0x00000000007c00ce in php_check_open_basedir (path=0x7ffef5a00018 'a' <repeats 200
times>...)
at /home/vps/git/php-src/main/fopen_wrappers.c:279
#7 0x00000000007e12b9 in php_plain_files_stream_opener (wrapper=0x10a7980
<php_plain_files_wrapper>,
path=0x7ffef5a00018 'a' <repeats 200 times>..., mode=0x7ffff6858e58
"r", options=0x0, opened_path=0x0, context=0x7ffff6858d40,
php_stream_call_depth=0x1, zend_filename=0xd723f8
"/home/vps/git/php-src/main/streams/streams.c", __zend_lineno=0x809,
zend_orig_filename=0xd550d0 "/home/vps/git/php-src/ext/standard/file.c",
zend_orig_lineno=0x366)
at /home/vps/git/php-src/main/streams/plain_wrapper.c:1058
#8 0x00000000007da8db in _php_stream_open_wrapper_ex (path=0x7ffef5a00018 'a' <repeats
200 times>..., mode=0x7ffff6858e58 "r", options=0x8,
opened_path=0x0, context=0x7ffff6858d40, __php_stream_call_depth=0x0,
zend_filename=0xd550d0 "/home/vps/git/php-src/ext/standard/file.c", zend_lineno=0x366,
__zend_orig_filename=0x0,
__zend_orig_lineno=0x0) at /home/vps/git/php-src/main/streams/streams.c:2055
#9 0x0000000000730e32 in php_if_fopen (execute_data=0x7ffff6814100, return_value=0x7ffff68140e0)
at /home/vps/git/php-src/ext/standard/file.c:870
#10 0x0000000000670167 in phar_fopen (execute_data=0x7ffff6814100, return_value=0x7ffff68140e0)
at /home/vps/git/php-src/ext/phar/func_interceptors.c:427
#11 0x00000000008ae50b in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER () at
/home/vps/git/php-src/Zend/zend_vm_execute.h:675
#12 0x00000000008adc2e in execute_ex (ex=0x7ffff6814030) at
/home/vps/git/php-src/Zend/zend_vm_execute.h:429
#13 0x00000000008add40 in zend_execute (op_array=0x7ffff687c000, return_value=0x0) at
/home/vps/git/php-src/Zend/zend_vm_execute.h:474
#14 0x000000000084e490 in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at
/home/vps/git/php-src/Zend/zend.c:1447
#15 0x00000000007b9126 in php_execute_script (primary_file=0x7fffffffd6c0) at
/home/vps/git/php-src/main/main.c:2533
#16 0x000000000092d910 in do_cli (argc=0x2, argv=0x10d5770) at
/home/vps/git/php-src/sapi/cli/php_cli.c:990
#17 0x000000000092ead4 in main (argc=0x2, argv=0x10d5770) at
/home/vps/git/php-src/sapi/cli/php_cli.c:1378
#18 0x00007ffff6faaf45 in __libc_start_main (main=0x92e2cc <main>, argc=0x2,
argv=0x7fffffffea68, init=<optimized out>, fini=<optimized out>,
rtld_fini=<optimized out>, stack_end=0x7fffffffea58) at libc-start.c:287
#19 0x0000000000422ca9 in _start ()
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=72742&edit=1