Headline
CVE-2017-11147: Seg fault when loading hostile phar
In PHP before 5.6.30 and 7.x before 7.0.15, the PHAR archive handler could be used by attackers supplying malicious archive files to crash the PHP interpreter or potentially disclose information due to a buffer over-read in the phar_parse_pharfile function in ext/phar/phar.c.
Sec Bug #73773
Seg fault when loading hostile phar
Submitted:
2016-12-17 12:06 UTC
Modified:
2017-07-12 17:09 UTC
From:
eyal dot itkin at gmail dot com
Assigned:
stas (profile)
Status:
Closed
Package:
PHAR related
PHP Version:
5.6.29
OS:
Private report:
No
CVE-ID:
2017-11147
[2016-12-17 12:06 UTC] eyal dot itkin at gmail dot com
Description:
phar.c - phar_parse_pharfile() has insufficient sanity checks on the entry data. A hostile phar archive can lead the parser to access memory out of the allocated buffer, resulting in a crash.
The for loop that parses the manifest entries does not properly checks that the metadata_len 4 bytes field is inside the buffer, enabling a huge page aligned archive to trigger an out-of-page read, causing a segmentation fault - as presented in the attached trace.
The proposed fix is to add a check before reading this length field (just like the check in the start of the for loop): if ( 4 > (size_t)(endbuffer - buffer)) { <report error> }
This report is somewhat connected to report #73764, and both should probably be fixed together so to avoid confusion.
Test script:
<?php $p = new Phar('example_hostile.phar’, 0); echo "Loaded the phar archive\n"; ?>
Expected result:
no crash, calling the echo with the specified message as intended
Actual result:
segmentation fault.
(gdb) bt #0 0xb4c7cb56 in ?? () from /usr/lib/php/20151012/phar.so #1 0xb4c7ebce in phar_create_or_parse_filename () from /usr/lib/php/20151012/phar.so #2 0xb4c7f8b7 in phar_open_or_create_filename () from /usr/lib/php/20151012/phar.so #3 0xb4c8120e in zim_Phar___construct () from /usr/lib/php/20151012/phar.so #4 0x80348662 in execute_internal () #5 0x802a1dce in dtrace_execute_internal () #6 0x80339f65 in ?? () #7 0x802f26da in execute_ex () #8 0x802a1c35 in dtrace_execute_ex () #9 0x8034a1b6 in zend_execute () #10 0x802b210d in zend_execute_scripts () #11 0x80251054 in php_execute_script () #12 0x8034c01f in ?? () #13 0x8012b64f in main () (gdb) info reg eax 0xa8200000 -1474297856 ecx 0x0 0 edx 0xb49fffec -1264582676 ebx 0xb4ca6c40 -1261802432 esp 0xbfeee240 0xbfeee240 ebp 0xb5274000 0xb5274000 esi 0x640001b 104857627 edi 0xb4a00000 -1264582656 eip 0xb4c7cb56 0xb4c7cb56 eflags 0x210246 [ PF ZF IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
Patches
Add a Patch
Pull Requests
Add a Pull Request
History
AllCommentsChangesGit/SVN commitsRelated reports
[2016-12-27 07:05 UTC] [email protected]
-Status: Open +Status: Feedback
[2016-12-27 07:05 UTC] [email protected]
Please provide example_hostile.phar
[2016-12-27 09:04 UTC] eyal dot itkin at gmail dot com
-Status: Feedback +Status: Open
[2016-12-31 00:07 UTC] [email protected]
-Status: Open +Status: Feedback
[2016-12-31 00:07 UTC] [email protected]
I can’t reproduce this after fix for #73764 is applied. Could you please check if it still happens for you?
[2016-12-31 08:56 UTC] eyal dot itkin at gmail dot com
-Status: Feedback +Status: Open
[2016-12-31 08:56 UTC] eyal dot itkin at gmail dot com
It still happens, and this is because:
- #73764 checked that the static 24 entry bytes (entry.filename_len, entry.uncompressed_filesize, timestamp, compressed_filesize, crc32, flags) have enough space in the buffer.
- #73764 also checked that the dynamic filename has enough space in the buffer
- After all of these fields there are additional fields: a) 4 bytes - len (metadata_len) b) len bytes - the actual metadata
The current code reads the 4 bytes (without checking it is inside the buffer), and the checks that has enough (len) bytes so to read the metadata itself.
[2016-12-31 09:19 UTC] [email protected]
-Status: Open +Status: Feedback
[2016-12-31 09:19 UTC] [email protected]
Could you please supply the file that reproduces it for you? For me it does not reproduce with the file at the link here.
[2016-12-31 10:29 UTC] eyal dot itkin at gmail dot com
-Status: Feedback +Status: Open
[2016-12-31 10:29 UTC] eyal dot itkin at gmail dot com
* I uploaded a new .phar file that was tested in my environment to reproduce the error. * Again, I uploaded the python script that generated it (build_phar_new.py). * Both files can be found in the same link as before: http://www.cs.tau.ac.il/~eyalitki/Upload/73773/
[2017-01-01 02:48 UTC] [email protected]
-PHP Version: 7.1.0 +PHP Version: 5.6.29 -Assigned To: +Assigned To: stas
[2017-01-01 04:02 UTC] eyal dot itkin at gmail dot com
I approve of the suggested fix.
[2017-01-03 05:11 UTC] [email protected]
-Status: Assigned +Status: Closed
[2017-01-05 23:57 UTC] [email protected]
-Summary: Seg fault when loading hostile phar +Summary: Segfault when loading hostile phar
[2017-01-06 00:00 UTC] [email protected]
-Summary: Segfault when loading hostile phar +Summary: Seg fault when loading hostile phar
[2017-07-12 10:41 UTC] henri at nerv dot fi
CVE-2017-11147 has been assigned for this issue.
[2017-07-12 17:09 UTC] [email protected]
-CVE-ID: needed +CVE-ID: 2017-11147
Related news
spl_array.c in the SPL extension in PHP before 5.5.37 and 5.6.x before 5.6.23 improperly interacts with the unserialize implementation and garbage collection, which allows remote attackers to execute arbitrary code or cause a denial of service (use-after-free and application crash) via crafted serialized data.
The phar_make_dirstream function in ext/phar/dirstream.c in PHP before 5.6.18 and 7.x before 7.0.3 mishandles zero-size ././@LongLink files, which allows remote attackers to cause a denial of service (uninitialized pointer dereference) or possibly have unspecified other impact via a crafted TAR archive.
The cdf_check_stream_offset function in cdf.c in file before 5.19, as used in the Fileinfo component in PHP before 5.4.30 and 5.5.x before 5.5.14, relies on incorrect sector-size data, which allows remote attackers to cause a denial of service (application crash) via a crafted stream offset in a CDF file.