Advertisement






PHP 7.0.10 Heap overflow in mysqlnd related to BIT fields

CVE Category Price Severity
CVE-2015-0273 CWE-119 $15,000 High
Author Risk Exploitation Type Date
Mateusz Jurczyk, Gynvael Coldwind, and Fermin Serna of Google Project Zero High Local 2016-09-15
CPE
cpe:cpe:/a:php:mysqlnd:7.0.10
CVSS EPSS EPSSP
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2016090110

Below is a copy:

PHP 7.0.10 Heap overflow in mysqlnd related to BIT fieldsDescription:
------------
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);
?>

Copyright ©2024 Exploitalert.

All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use.