php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #74886 Type confusion when processing yaml array merges ("<<")
Submitted: 2017-07-09 20:17 UTC Modified: 2018-11-25 22:22 UTC
From: admin at stickman dot hu Assigned: bd808 (profile)
Status: Closed Package: yaml (PECL)
PHP Version: Irrelevant OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: admin at stickman dot hu
New email:
PHP Version: OS:

 

 [2017-07-09 20:17 UTC] admin at stickman dot hu
Description:
------------
In handle_mapping, there is code to handle the array merge tag (http://yaml.org/type/merge.html). The code assumes that it gets a reference, or an array of references, but that is not guaranteed by libyaml. In fact, it can be any value type, or an array of values.

In the "array of references" case, the current code just loops through the received array, dereferences all values it has (if they are references), and unconditionally casts them to array before supplying it to zend_hash_merge as a source parameter. If we supply an int, for example, that directly gets used as a pointer to a hash table, and after that, all bets are off.

It is exploitable much the same way as the spl_array unserialize exploit from 2014 (https://sektioneins.de/en/blog/14-08-27-unserialize-typeconfusion.html), so RCE can be achieved, if yaml_parse is ran on untrusted data, and ASLR is disabled, or circumvented another way.

The fix should be just "Z_TYPE_P(zvalp) == IS_ARRAY" somewhere in the foreach.

Test script:
---------------
yaml_parse("x:\n <<: [ 0xDEADBEEF ]");

Expected result:
----------------
The above code should throw a serialization error, or deserialize to array("x" => NULL)

Actual result:
--------------
It dumps a segfault with the following backtrace:

#0  0x00000000005a4668 in _zend_hash_merge (target=0x7ffff605f310, source=0xdeadbeef, pCopyConstructor=0x58e790 <zval_add_ref>, overwrite=0 '\000') at /home/alex/projects/php/php-src/Zend/zend_hash.c:1859
#1  0x000000000052ad96 in handle_mapping (state=0x7fffffffa4b8, retval=<optimized out>) at /home/alex/projects/php/php-src/ext/yaml/parse.c:419
#2  0x000000000052af58 in handle_mapping (state=0x7fffffffa4b8, retval=<optimized out>) at /home/alex/projects/php/php-src/ext/yaml/parse.c:391
#3  0x000000000052a7d2 in handle_document (state=0x7fffffffa4b8, retval=0x7fffffffa490) at /home/alex/projects/php/php-src/ext/yaml/parse.c:350
#4  php_yaml_read_partial (state=0x7fffffffa4b8, pos=0, ndocs=0x7fffffffa480, retval=0x7fffffffa490) at /home/alex/projects/php/php-src/ext/yaml/parse.c:176
#5  0x0000000000529af0 in zif_yaml_parse (execute_data=<optimized out>, return_value=0x7fffffffa748) at /home/alex/projects/php/php-src/ext/yaml/yaml.c:364
#6  0x000000000062b0d8 in ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_HANDLER (execute_data=0x7ffff601c030) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:738
#7  0x00000000005d3568 in execute_ex (ex=0x7ffff601c030) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:59094
#8  0x00000000005d36d9 in zend_execute (op_array=0x7ffff607f2a0, return_value=0x0) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:63125
#9  0x0000000000590ae4 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/alex/projects/php/php-src/Zend/zend.c:1490
#10 0x0000000000530e97 in php_execute_script (primary_file=0x7fffffffcb90) at /home/alex/projects/php/php-src/main/main.c:2550
#11 0x0000000000658003 in do_cli (argc=2, argv=<optimized out>) at /home/alex/projects/php/php-src/sapi/cli/php_cli.c:1002
#12 0x00000000006571ba in main (argc=2, argv=<optimized out>) at /home/alex/projects/php/php-src/sapi/cli/php_cli.c:1395


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-10-24 06:25 UTC] stas@php.net
-Assigned To: +Assigned To: bd808
 [2018-11-24 04:09 UTC] bd808@php.net
-Status: Assigned +Status: Closed
 [2018-11-24 04:09 UTC] bd808@php.net
Fixed in 1.3.2 and 2.0.4
 [2018-11-25 22:22 UTC] cmb@php.net
Since the new versions have been released, this ticket can be disclosed.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 13:01:28 2024 UTC