|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [2016-08-03 06:20 UTC] 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 ()
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 16:00:01 2025 UTC | 
You are correct ! The error is not occurred in php_check_specific_open_basedir. Sorry for the mistake. The error in fact occurred in xbuf_format_converter (which is called by vspprintf() in php_verror() ) while trying to print error message contains my large input. In the below debugging result, it seems like memcpy() tries to read an unmapped memory location, which causes segment fault. Although the root cause is not what I mentioned in the previous comments, I do think this a security issue. Debugging result: ------------------- Continuing. [----------------------------------registers-----------------------------------] RAX: 0x7ffef6600018 ('a' <repeats 200 times>...) RBX: 0x1 RCX: 0x7ffff687f252 --> 0x5060000000000000 ('') RDX: 0xfffffff0 RSI: 0x7ffef6600018 ('a' <repeats 200 times>...) RDI: 0x7ffff687f252 --> 0x5060000000000000 ('') RBP: 0x7fffffffa800 --> 0x7fffffffa850 --> 0x7fffffffa940 --> 0x7fffffffaa40 --> 0x7fffffffaa80 --> 0x7fffffffaaa0 (--> ...) RSP: 0x7fffffffa2c0 --> 0x0 RIP: 0x7b6545 (<xbuf_format_converter+10062>: call 0x422a80 <memcpy@plt>) R8 : 0xd65060 ("/home/ubuntu/php-src/main/spprintf.c") R9 : 0x32e R10: 0x7d8555 (<php_plain_files_stream_opener>: push rbp) R11: 0x7ffff6858898 --> 0x72 ('r') R12: 0x422c80 (<_start>: xor ebp,ebp) R13: 0x7fffffffe680 --> 0x2 R14: 0x7ffff6814030 --> 0x7ffff68691e0 --> 0x8a5593 (<ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER>: push rbp) R15: 0x7ffff68691e0 --> 0x8a5593 (<ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER>: push rbp) EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x7b6538 <xbuf_format_converter+10049>: mov rax,QWORD PTR [rbp-0x4b0] 0x7b653f <xbuf_format_converter+10056>: mov rsi,rax 0x7b6542 <xbuf_format_converter+10059>: mov rdi,rcx => 0x7b6545 <xbuf_format_converter+10062>: call 0x422a80 <memcpy@plt> 0x7b654a <xbuf_format_converter+10067>: mov rax,QWORD PTR [rbp-0x460] 0x7b6551 <xbuf_format_converter+10074>: mov rdx,QWORD PTR [rbp-0x470] 0x7b6558 <xbuf_format_converter+10081>: mov QWORD PTR [rax+0x8],rdx 0x7b655c <xbuf_format_converter+10085>: jmp 0x7b6580 <xbuf_format_converter+10121> Guessed arguments: arg[0]: 0x7ffff687f252 --> 0x5060000000000000 ('') arg[1]: 0x7ffef6600018 ('a' <repeats 200 times>...) arg[2]: 0xfffffff0 arg[3]: 0x7ffff687f252 --> 0x5060000000000000 ('') [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa2c0 --> 0x0 0008| 0x7fffffffa2c8 --> 0x0 0016| 0x7fffffffa2d0 --> 0x0 0024| 0x7fffffffa2d8 --> 0x0 0032| 0x7fffffffa2e0 --> 0x7fffffffa978 --> 0x3000000028 ('(') 0040| 0x7fffffffa2e8 --> 0xd65501 --> 0x6f00000000000073 ('s') 0048| 0x7fffffffa2f0 --> 0x100000000 0056| 0x7fffffffa2f8 --> 0x7fffffffa830 --> 0x7ffff687f200 ("File name is longer than the maximum allowed path length on this platform (4096): ") [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 2, 0x00000000007b6545 in xbuf_format_converter (xbuf=0x7fffffffa830, is_char=0x1, fmt=0xd65501 "s", ap=0x7fffffffa978) at /home/ubuntu/php-src/main/spprintf.c:814 814 INS_STRING(xbuf, s, s_len, is_char); gdb-peda$ c Continuing. Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0xfffffffdffd80dd6 RBX: 0x1 RCX: 0x1ffffffe0 RDX: 0xfffffff0 RSI: 0x7ffef6600018 ('a' <repeats 200 times>...) RDI: 0x7ffff687f252 ('a' <repeats 16 times>) RBP: 0x7fffffffa800 --> 0x7fffffffa850 --> 0x7fffffffa940 --> 0x7fffffffaa40 --> 0x7fffffffaa80 --> 0x7fffffffaaa0 (--> ...) RSP: 0x7fffffffa2b8 --> 0x7b654a (<xbuf_format_converter+10067>: mov rax,QWORD PTR [rbp-0x460]) RIP: 0x7ffff7020ef5 (movdqu XMMWORD PTR [rdi+rdx*1-0x10],xmm8) R8 : 0xd65060 ("/home/ubuntu/php-src/main/spprintf.c") R9 : 0x32e R10: 0x7d8555 (<php_plain_files_stream_opener>: push rbp) R11: 0x7ffff6858898 --> 0x72 ('r') R12: 0x422c80 (<_start>: xor ebp,ebp) R13: 0x7fffffffe680 --> 0x2 R14: 0x7ffff6814030 --> 0x7ffff68691e0 --> 0x8a5593 (<ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER>: push rbp) R15: 0x7ffff68691e0 --> 0x8a5593 (<ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER>: push rbp) EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x7ffff7020ee5: cmp rdx,0x20 0x7ffff7020ee9: movdqu XMMWORD PTR [rdi],xmm8 0x7ffff7020eee: movdqu xmm8,XMMWORD PTR [rsi+rdx*1-0x10] => 0x7ffff7020ef5: movdqu XMMWORD PTR [rdi+rdx*1-0x10],xmm8 0x7ffff7020efc: ja 0x7ffff7020f10 0x7ffff7020efe: mov rax,rdi 0x7ffff7020f01: ret 0x7ffff7020f02: data16 data16 data16 data16 nop WORD PTR cs:[rax+rax*1+0x0] [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa2b8 --> 0x7b654a (<xbuf_format_converter+10067>: mov rax,QWORD PTR [rbp-0x460]) 0008| 0x7fffffffa2c0 --> 0x0 0016| 0x7fffffffa2c8 --> 0x0 0024| 0x7fffffffa2d0 --> 0x0 0032| 0x7fffffffa2d8 --> 0x0 0040| 0x7fffffffa2e0 --> 0x7fffffffa978 --> 0x3000000028 ('(') 0048| 0x7fffffffa2e8 --> 0xd65501 --> 0x6f00000000000073 ('s') 0056| 0x7fffffffa2f0 --> 0x100000000 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x00007ffff7020ef5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6