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.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum