The Integer-Overflow (IOF) vulnerability family is responsible for a dominant part of C/C++ code vulnerabilities, as I shown in my previous post with a specific example. However, the Integer vulnerability class has more than IOFs in it, and this will be the topic of this post.

CVE 2016-10158:

The exif_convert_any_to_int function in ext/exif/exif.c in PHP … allows remote attackers to cause a denial of service (application crash) via crafted EXIF data…

This vulnerability meant that parsing a hostile TIFF/JPEG file in all PHP versions, could lead to a server crash. Instead of a NULL-dereference or Out-Of-Bounds access, this CVE is caused by an Integer Exception, on intel CPUs.

Integer Basics – Intel:

It is known (I hope) that a division by 0, on intel CPUs, will raise an arithmetic exception. And this is why the PHP developers included a code check to handle this edge case:

case TAG_FMT_SRATIONAL:
  s_den = php_ifd_get32s(4+(char* )value, motorola_intel);
  if (s_den == 0) {
    return 0;
  } else {
    return php_ifd_get32s(value, motorola_intel) / s_den;
  }

However, by reading the full specifications of the DIV command we can see that there is one more edge case:

… If the quotient is too large for the designated register.

Since signed integers are a-symmetric there are more negative values than positive values:

  • x > 0 : 1 <= x <= 2 **31 – 1
  • x = 0
  • x < 0 : -2 ** 31 <= x < 0

This means that the value 2 ** 31 is too big for a signed integer. And how can we trigger such a large quotient?

MIN_INT / -1

Since this is a relatively unknown edge case, the PHP implementation failed to handle the exception, resulting in a Denial-Of-Service (DoS) when parsing the hostile file.

Comment: credit for Ido for pointing out a mistake in the original post in which I mistakenly focused the remainder instead of the quotient.

Added Bonus:

It is somewhat common to implement the ABS macro like this:

#define ABS(_X_) ( (_X_) >= 0 (_X_) ? (-1 * (_X_)) )

However, if we look again at the MIN_INT case, we will see that the multiplication will create a value that is outside the range of a signed int. And so in our case the result will remain MIN_INT, and will remain negative.

White hat security researcher. Recently finished my M.s.c at TAU, and now focus on security research, mainly in open sources.