Full Report
BCrypt is a popular hashing algorithm for passwords. In PHP, this is one of the standard ways to verify passwords. PHP assumes that the hash will be in a proper format when using password_verify. This takes in the plaintext version of a password, alongside the salted and hashed password. Within the modification to cryp_blowfish.c, there is a line of code that will cut a salt short if it contains a $ inside of it. However, since this was a modification of the code and not an original implementation, the developer didn't consider the ramifications this would have down the road. This change is literally labeled "PHP Hack", which is awesome. Different places in the code assume that the salt and hash are a specific size. Since this isn't the case, this creates creates an out of bounds read in C. More impactful though, is that the string can become truncated from this action as well. This occurs because of a strlen being used on a string that was assumed to have a specific length, which isn't the case. In some cases, this could even verify a password when it's incorrect. Pretty neat! This attack is only possible via craftable hashes. Since this is a weird use case that isn't super common, it is doubtful this affects very many people but is interesting none-the-less.
Analysis Summary
# Vulnerability: BCrypt Hash Truncation and Out-of-Bounds Read in PHP `password_verify`
## CVE Details
- CVE ID: CVE-2023-0567
- CVSS Score: Not explicitly provided in the text, **Severity: Low** is mentioned. (Note: Without a standard CVSS calculation, the severity is based on the qualitative assessment provided.)
- CWE: CWE-125 (Out-of-bounds Read), potentially CWE-190 (Integer Overflow or Wraparound) or issues related to inadequate string handling.
## Affected Systems
- Products: PHP using the `password_verify()` function relying on the BCrypt implementation (`crypt_blowfish.c`).
- Versions: Unspecified, but the flaw originates from a specific "PHP Hack" modification within the BCrypt handling code that likely existed over several versions until patched.
- Configurations: Applications using `password_verify()` with craftable, non-standard BCrypt hashes that contain a `$` character in the salt portion.
## Vulnerability Description
A flaw exists in PHP's implementation of the BCrypt hashing algorithm within `crypt_blowfish.c`, introduced via a specific modification known as the "PHP Hack." This modification is intended to handle certain hash formats but incorrectly processes salts containing a `$` character by prematurely truncating the salt processing.
This truncation leads to two main issues when `password_verify()` is used with such a craftable hash:
1. **String Truncation/Incorrect Verification:** An early `strlen()` call after processing a truncated salt results in a string shorter than expected, potentially causing an incorrect password verification (validating an incorrect plaintext password against the malformed hash).
2. **Out-of-Bounds Read (OOB Read):** A subsequent `memcpy` operation copies data using fixed sizes based on the expected BCrypt format. If the actual input `setting` (derived from the truncated salt) is too short, this results in an Out-of-Bounds Read when accessing the input buffer.
The vulnerability is only exploitable when using **craftable hashes** that are not generated by the standard recommendation (`password_hash()`).
## Exploitation
- Status: PoC available (Valgrind output demonstrating memory errors is provided).
- Complexity: Medium (Requires crafting a specific, malformed BCrypt hash).
- Attack Vector: Indirect (The malicious hash must be stored and then supplied to `password_verify()`).
## Impact
- Confidentiality: Potential information disclosure if the OOB read leaks memory content, although the primary direct impact is integrity failure.
- Integrity: **High.** An incorrect password might be falsely validated by `password_verify()`, leading to unauthorized access.
- Availability: Low. The vulnerability triggers memory errors (OOB read), which could lead to crashes (denial of service) depending on the environment, though not the primary stated impact.
## Remediation
### Patches
- The suggested fix is to **remove the "PHP Hack"** found in `crypt_blowfish.c` to ensure PHP's implementation aligns with the standard BCrypt specification enforced by Openwall.
- **Action**: Update PHP to a version where this specific hack has been removed and standard hash validation logic is enforced.
### Workarounds
- Do not accept user-provided or untrusted hashes for password verification that do not strictly conform to the expected BCrypt structure generated by standard APIs like `password_hash()`.
- Ensure that all passwords stored and verified are generated using PHP's recommended `password_hash()` function, as these generated hashes will comply with expected standards and avoid triggering the internal logic flaw.
## Detection
- **Indicators of Compromise:** Logs showing successful `password_verify()` calls against hashes that are known to be malformed or were not created using secure, standard methods. Monitor application logs for unexpected successful logins when hash integrity might be in question.
- **Detection Methods and Tools:** Static analysis of PHP source code to identify usage of `password_verify()` against potentially tainted input strings that might resemble malformed BCrypt salts. Dynamic analysis using memory sanitizers (like Valgrind, as demonstrated in the PoC context) can reveal the underlying OOB reads during testing.
## References
- Vendor advisories: Not explicitly listed, attributed to community research.
- Relevant links:
- PHP Source Code commit/file reference (for context on the 'PHP Hack'): hxxps://github.com/php/php-src/blob/2740920a392c043b034e2f0e41d819549836712a/ext/standard/crypt_blowfish.c
- Commit referenced: hxxps://github.com/php/php-src/commit/2740920a392c043b034e2f0e41d819549836712a