|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2016-05-31 00:33 UTC] stas@php.net
-Assigned To:
+Assigned To: mysql
[2016-08-15 15:38 UTC] bugs at themadbat dot com
[2016-08-15 17:26 UTC] stas@php.net
-Assigned To: mysql
+Assigned To: andrey
[2016-09-13 03:31 UTC] stas@php.net
-PHP Version: 7.0.7
+PHP Version: 5.6.25
-CVE-ID:
+CVE-ID: needed
[2016-09-13 04:04 UTC] stas@php.net
[2016-09-13 04:04 UTC] stas@php.net
-Status: Assigned
+Status: Closed
[2016-09-13 04:06 UTC] stas@php.net
[2016-09-13 04:09 UTC] stas@php.net
[2016-09-13 04:11 UTC] stas@php.net
[2016-09-13 04:11 UTC] stas@php.net
[2016-09-13 09:02 UTC] ab@php.net
[2016-09-15 09:30 UTC] tyrael@php.net
[2016-09-16 13:37 UTC] kaplan@php.net
-CVE-ID: needed
+CVE-ID: 2016-7412
[2016-10-17 10:08 UTC] bwoebi@php.net
[2016-10-17 10:08 UTC] bwoebi@php.net
[2016-10-17 10:08 UTC] bwoebi@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 03:00:02 2025 UTC |
Description: ------------ mysqlnd extension assumes the `flags` returned for a BIT field necessarily contain UNSIGNED_FLAG; this might not be the case, with a rogue mysql server, or a MITM attack. In php_mysqlnd_rowp_read_text_protocol_aux (mysqlnd_wireprotocol.c) BIT fields are treated specially and use extra space pre-allocated for that processing at the end of `row_buffer` (see the comment there). The size of that extra space that is allocated is calculated in mysqlnd_res_meta::read_metadata (in mysqlnd_result_meta.c), and depends on the number of BIT fields and their respective size in bytes. For a BIT(8) field, which has 8 bits, the function reserves 3 bytes. This is fine if the field is UNSIGNED (which BIT values should always be with a normal mysql server), however if the server returns BIT fields without the UNSIGNED_FLAG set, a BIT(8) will then be interpreted as signed, and can contain negative values such as -127, which no longer fit the reserved space: To read BIT values off a row_buffer, php_mysqlnd_rowp_read_text_protocol_aux uses the generic function ps_fetch_from_1_to_8_bytes (mysqlnd_ps_codec.c) which starts exactly with a check of the UNSIGNED_FLAG but is not aware of whether it is processing a BIT field. Thus, a malicious mysql server or MITM can return field metadata for BIT fields that does not contain the UNSIGNED_FLAG, leading to a heap overflow. Tested in 5.6.x and latest packaged PHP 7.0.7, but should affect a lot more versions. Affects queries through mysql / mysqli / anything that uses mysqlnd. To simulate a rogue mysql server apply the following patch to mysqlnd_ps_codec.c before running the test case: < if (field->flags & UNSIGNED_FLAG) { > if (field->flags & UNSIGNED_FLAG && field->type != MYSQL_TYPE_BIT) { Test script: --------------- <?php /* Please setup the following database/table: CREATE DATABASE php; USE php; CREATE TABLE `php` (`moo` bit(8) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO `php` VALUES (0x81); # -127 when signed */ $link = mysqli_connect('127.0.0.1', 'root', '', 'php'); if (!$link) die("Cannot connect"); $s = str_repeat("moo,", 60000); /* can play with this value a bit to see different corruption */ $result = mysqli_query($link, "SELECT $s 1 FROM php"); while($row = mysqli_fetch_row($result)) { $v = print_r($row, true); /* just to exercise heap */}; mysqli_close($link); ?>