php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #72535 arcfour encryption stream filter crashes php
Submitted: 2016-07-03 05:55 UTC Modified: 2017-10-27 18:05 UTC
From: terrafrost at gmail dot com Assigned: derick (profile)
Status: Closed Package: mcrypt related
PHP Version: 7.0.8 OS: *
Private report: No CVE-ID: None
 [2016-07-03 05:55 UTC] terrafrost at gmail dot com
Description:
------------
I don't think encryption filters are a very well known feature of mcrypt but none-the-less they are a feature: http://php.net/manual/en/filters.encryption.php

The example in the PHP docs (with tripledes) works but arcfour does not work - you try to run it and you get a segfault.

Test script:
---------------
<?php
$passphrase = 'My secret';
$plaintext = 'Secret secret secret data';

$iv = substr(md5('iv' . $passphrase, true), 0, 8);
$key = substr(md5('pass1' . $passphrase, true) .
              md5('pass2' . $passphrase, true), 0, 24);
$opts = array('iv' => $iv, 'key' => $key, 'mode' => 'stream');

$expected = substr($plaintext . $plaintext, 0, 48);

$fp = fopen('php://memory', 'wb+');
stream_filter_append($fp, 'mcrypt.arcfour', STREAM_FILTER_WRITE, $opts);
fwrite($fp, $plaintext);

Expected result:
----------------
The script to actually run

Actual result:
--------------
The script crashes

Patches

mcrypt-filter-uaf (last revision 2017-01-10 12:52 UTC) by leigh@php.net)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-07-03 13:07 UTC] cmb@php.net
-Status: Open +Status: Verified -Package: mcrypt related +Package: Reproducible crash -Operating System: Windows 10 +Operating System: *
 [2016-07-03 13:07 UTC] cmb@php.net
I can reproduce the crash with PHP 5.6.23, PHP 7.0.8 and PHP
7.1.0alpha2 on Windows. A debug build of current master on Linux
reports 2 memory leaks.
 [2016-07-04 02:50 UTC] kalle@php.net
-Status: Verified +Status: Feedback
 [2016-07-04 02:50 UTC] kalle@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a backtrace to see what is happening behind the scenes. To
find out how to generate a backtrace, please read
http://bugs.php.net/bugs-generating-backtrace.php for *NIX and
http://bugs.php.net/bugs-generating-backtrace-win32.php for Win32

Once you have generated a backtrace, please submit it to this bug
report and change the status back to "Open". Thank you for helping
us make PHP better.


 [2016-07-04 19:28 UTC] cmb@php.net
-Status: Feedback +Status: Open
 [2016-07-04 19:28 UTC] cmb@php.net
I've got the following backtrace with a recent master (421cc65)
and an x86 build (apparently the crash doesn't happen with x64
builds):

php7ts_debug.dll!php_stream_bucket_unlink(_php_stream_bucket * bucket) Line 225
php7ts_debug.dll!_php_stream_write_filtered(_php_stream * stream, const char * buf, unsigned int count, int flags) Line 1186
php7ts_debug.dll!_php_stream_write(_php_stream * stream, const char * buf, unsigned int count) Line 1229
php7ts_debug.dll!zif_fwrite(_zend_execute_data * execute_data, _zval_struct * return_value) Line 1214
php7ts_debug.dll!ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER(_zend_execute_data * execute_data) Line 632
php7ts_debug.dll!execute_ex(_zend_execute_data * ex) Line 432
php7ts_debug.dll!zend_execute(_zend_op_array * op_array, _zval_struct * return_value) Line 474
php7ts_debug.dll!zend_execute_scripts(int type, _zval_struct * retval, int file_count, ...) Line 1441
php7ts_debug.dll!php_execute_script(_zend_file_handle * primary_file) Line 2532
php.exe!do_cli(int argc, char * * argv) Line 990
php.exe!main(int argc, char * * argv) Line 1378
[External Code]
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
 [2016-07-05 11:13 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2016-07-05 11:13 UTC] cmb@php.net
I did some debugging, but am not able to resolve the issue. The
following debug hints might be helpful, nonetheless. Note that this
appears to happen only for x86 builds:

 * set two breakpoints:
   <https://github.com/php/php-src/blob/php-7.0.8/main/streams/streams.c#L1180>
   <https://github.com/php/php-src/blob/php-7.0.8/main/streams/memory.c#L68>
 * start debugging
 * when reaching the first breakpoint set watches for the memory
   locations of bucket and stream->abstract, e.g.
   (_php_stream_bucket*)0x00c02b98
   (php_stream_memory_data*)0x00c5cb10
 * continue to the second breakpoint; everything is fine until now
 * step over the assignment
 * now ms->data points to the exact location of bucket
 * a few lines below[1] the buf gets memcpy()d to ms->data,
   thereby overwriting and corrupting bucket, which results in an
   invalid read in php_stream_bucket_unlink() (one statement after
   the first breakpoint)
 
[1] <https://github.com/php/php-src/blob/php-7.0.8/main/streams/memory.c#L76>
 [2016-07-10 14:55 UTC] cmb@php.net
-Type: Bug +Type: Security -Private report: No +Private report: Yes
 [2016-07-10 14:55 UTC] cmb@php.net
This *might* be a security issue.
 [2016-07-10 22:06 UTC] stas@php.net
-Package: Reproducible crash +Package: mcrypt related
 [2016-07-18 07:23 UTC] stas@php.net
Not sure - why is this security issue?
 [2016-08-02 08:16 UTC] stas@php.net
-Assigned To: +Assigned To: derick
 [2017-01-10 12:52 UTC] leigh@php.net
The following patch has been added/updated:

Patch Name: mcrypt-filter-uaf
Revision:   1484052757
URL:        https://bugs.php.net/patch-display.php?bug=72535&patch=mcrypt-filter-uaf&revision=1484052757
 [2017-01-10 13:04 UTC] leigh@php.net
Still not 100% sure if this is a security issue, it is a user-after-free situation, but unsure if the freed buffers can be made to hold useful data.

The comments for php_stream_bucket_make_writeable indicate that it is possible for the bucket passed in to be delref'd and a copy returned.

In this scenario this was exactly the case, the freed bucket was being used rather than the copy returned.

I've attached a patch based on 5.6, can someone please review and offer a revised opinion on whether this needs to go into the security repo or not please.
 [2017-01-20 12:25 UTC] leigh@php.net
Looks like we missed the boat on 5.6 for this one. Would still like someone else's opinion on whether this needs to go into the security repo or can go straight into regular branches.
 [2017-10-24 05:24 UTC] kalle@php.net
-Status: Verified +Status: Assigned
 [2017-10-24 05:49 UTC] stas@php.net
5.6 has security support for more than a year yet, so no boats missed - if it is a security issue, which UAF in crypto module probably would qualify as it doesn't look repro code does something weird. 

I'd just merge it since releases should be this week IIRC and ping RMs to pull the fix into the release branches.
 [2017-10-27 18:05 UTC] ab@php.net
-Status: Assigned +Status: Closed
 [2017-10-27 18:05 UTC] ab@php.net
Thank you for your bug report. This issue has already been fixed
in the latest released version of PHP, which you can download at 
http://www.php.net/downloads.php


 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC