Fixed error executing SHA-3 code in PHP – check your version! – Naked security


You’ve probably seen story after story in the media about a critical bug in OpenSSL over the past week, although at the time of writing this article (2022-11-01T11:30:00Z) no one reporting on OpenSSL actually knows what to do Let me know about the bug as what’s new is an update due later today but hasn’t been announced yet.

We’ll cover this bug as soon as we actually know what it is so that we can explain it instead of just saying, “Patch now.” (In fact, if you’re not interested in the details of this bug, you can just all the vulnerable Patch versions of OpenSSL in your own ecosystem.)

But there is another unrelated bug in the cryptographic library that has recently been fixed and hasn’t received much attention, and while we assume it’s far less dangerous than the soon to be uncovered OpenSSL bug, it still is worth knowing about.

In the tense and exciting wait for the OpenSSL reveal, we thought we’d jump into it quickly CVE-2022-37454.

This vulnerability is a buffer overwrite bug caused by an arithmetic overflow in the SHA-3 cryptographic code provided by the team that originally developed the SHA-3 hashing algorithm, originally known as Keccak (pronounced “ketchak”, like “ketchup”).

This official implementation, known as XKCP, short for Extended Keccak code packis a collection of open-source library code for Keccak and a set of related cryptographic tools from the Keccak team, including their authenticated encryption algorithms Ketje and Keyak, pseudo-random number generators called Kravatte and Xoofff (yes, three Fs), and a lightweight encryption algorithm for low-power processors named Xoodyak.

Difficult to exploit

Fortunately, it will almost certainly be difficult, if not impossible, to remotely trigger the CVE-2022-37454 bug, as it relies on provoking a very peculiar sequence of calls to the hashing library.

Simply put, you need to perform the hash by feeding it a sequence of blocks of data and making sure that one of those blocks is almost, but not quite, 4GB in size (minimum 4,294,967,096 bytes and maximum 4294967295 bytes).

As you can imagine, code that hashes remotely uploaded data is likely to either retrieve the entire object before hashing it locally, typically by repeatedly processing a much smaller, fixed-length buffer, or it will fold each received block into the Hash on It so happens that far smaller chunks are typically received on each network call.

Still, this bug is reminiscent of one we wrote about earlier this year in a network protocol called NetUSB, which allows virtualization of USB device access across a network, allowing you to, for example, connect a USB device like a hard disk drive plug in a real-time clock or weather station directly to your router, and then access it from any computer on your LAN as if it were locally attached:

For this error, the code checked that you weren’t trying to consume too much memory by comparing the pre-declared size of a request packet to a known limit…

…but before checking, it silently added an additional 17 bytes to the requested amount of memory to provide some buffer space for its own use.

So if you’ve told the NetUSB code that you want to send an unimaginably large amount of data that happens to be within 17 bytes of the 4GB limit imposed by the use of 32-bit integers, you’ve provoked an integer overflow.

When using 32-bit integers, 0xFFFFFFFF + 1 is truncated to 32 bits, so it wraps around to 0x00000000 like an old-fashioned car odometer. There is no place to store the correct 33-bit answer 0x100000000, just as the millennium bug rounded the value 99+1 back to 0, which represented the year 1900, rather than reaching 100, which would have represented the 1900 year 2000

Thus the code would only allocate a few bytes of memory (at most (0xFFFFFFFF + 17) Mod 2).32i.e. 16), but will then accept almost any amount of data you want to send and then try to squeeze it into a block of memory that just doesn’t fit.

The XKCP error is similar, and is caused by a size check that is supposed to fail 200 bytes below the 4GB limit, but is instead effectively testing against the 4GB limit, potentially leading to a range of possible results, all of which are bad:

  • Crash of the program calling the library. This could result in an exploitable DoS (denial of service) attack in which otherwise innocent, booby-trapped data could be sent over and over again to crash a vital server and then crash it over and over again.
  • Incorrect calculation of the final hash value. If the calling code didn’t crash or catch the unexpected error, it could return an incorrect result, which could cause a hash validation to fail. Theoretically, this could result in prohibited data not being captured during a blacklist check, or changed data being incorrectly identified as unchanged during an allow list check.
  • Remote Code Execution. When a crash can be remotely provoked with data selected by an attacker, there is often a chance that well-informed cybercriminals can manipulate the crash and trick the CPU into executing malicious code instead of failing under the control of “safe”. the operating system itself.

What to do?

Unlike OpenSSL, the XKCP implementation of SHA-3 is not used very widely (By the way, OpenSSL has its own Keccak code and is therefore not affected by this bug), but the XKCP code appears in at least PHP 8, which was recently patched was made to prevent this error.

If you have PHP 8, patch it now 8.0.25 or 8.1.12or later.

If you have Python 3.10 or earlier (Python 3.11 has switched to a different implementation of SHA-3 that is not affected), you may be vulnerable.

Fortunately, some builds of Python 3.9 and 3.10 (this was the case on our own Linux system, Slackware-current with Python 3.9.15) are compiled so that the hashlib Functions use OpenSSL and are therefore immune to this particular bug.

You can check if your Python version is using the OpenSSL implementation of SHA-3 instead of XKCP as follows:

>>> import hashlib
>>> hashlib.sha3_224
<built-in function openssl_sha3_224>

A vulnerable Python version says something like this: <class '_sha3.sha3_224'> instead of referencing openssl_sha3_224.

According to the Python team “Python 3.8 and earlier did not delegate sha3 to OpenSSL regardless of version, so these are vulnerable.”.

You can use this code as a basic proof of concept to determine if you are at risk:

$ python3.x
>>> import hashlib
>>> h = hashlib.sha3_224()         # set up a SHA-3 hash calculation
>>> h.update(b"\x00" * 1)          # hash one byte
>>> h.update(b"\x00" * 4294967295) # then hash a further 2^32 - 1 bytes

If Python crashes with an error at this point, e.g python3.x terminated by signal SIGSEGV (an attempt to access memory that you don’t own), then you’ll have to wait for an update to your Python version or reorganize your code, for example by including the bug update() Function so that it proactively returns an error when dangerously sized input is presented.

If Python doesn’t crash, you should be able to complete the hashing process correctly:

>>> d = h.digest()
>>> d.hex()

If you have your own code that uses XKCP, you can update XKCP from the Github page.

Source link

Like it? Share with your friends!



Your email address will not be published. Required fields are marked *