Aug 28, 2026·6 min read·78 visits
A timing side-channel in Phalcon allows remote, unauthenticated attackers to forge encrypted payloads by guessing HMAC signatures byte-by-byte.
Phalcon versions prior to 5.14.1 are vulnerable to a timing side-channel attack in the authenticated decryption process. The HMAC signature verification utilizes a non-constant-time byte comparison, allowing unauthenticated remote attackers to reconstruct valid signatures and forge arbitrary encrypted payloads.
The Phalcon PHP framework, distributed as a high-performance C extension, provides cryptographic capabilities through its Phalcon\Encryption\Crypt component. When message signing is enabled, this component is designed to follow an Encrypt-then-MAC paradigm to guarantee the integrity and authenticity of encrypted data before decryption.
Prior to version 5.14.1, the implementation of the signature verification process introduced a critical security flaw. The framework used a standard, non-constant-time byte-wise comparison operator to validate the Hash-based Message Authentication Code (HMAC) of incoming payloads.
This behavior exposes an observable timing side-channel, classified as CWE-208. An unauthenticated remote attacker can exploit this discrepancy to bypass signature checks and subsequently perform payload forgery, leading to unauthorized data manipulation or privilege escalation depending on how the application processes decrypted data.
The root cause of CVE-2026-54736 resides in the Zephir source code of the Crypt::decrypt() method. Zephir is a high-level language compiled into native C code to produce PHP extensions. The vulnerable version of Phalcon performed the HMAC comparison using the strict inequality comparison operator !==.
During compilation from Zephir to native C, the inequality comparison operator for string values is lowered to the ZEPHIR_IS_IDENTICAL macro. For equal-length string arguments, this macro invokes the standard library function memcmp. Because memcmp is optimized for execution speed, it terminates and returns as soon as it encounters the first non-matching byte between the two compared memory blocks.
This early-termination behavior creates an execution path whose duration is directly proportional to the number of matching prefix bytes in the compared hashes. By measuring the precise network latency of decryption requests, a remote attacker can discern whether their guess for a specific byte position was correct. This timing leak breaks the cryptographic security guarantees of the signature check.
An analysis of the vulnerable source code in phalcon/Encryption/Crypt.zep reveals two significant flaws. First, the comparison uses the non-constant-time operator. Second, the decryption pipeline performs plaintext unpadding before verifying the signature, which violates the standard Encrypt-then-MAC workflow.
// VULNERABLE CODE PATH
let decrypted = this->decryptGcmCcmAuth(mode, cipherText, decryptKey, iv);
let padded = decrypted;
// Unpadding occurs before verifying the integrity signature
let decrypted = this->decryptGetUnpadded(mode, blockSize, decrypted);
if true === this->useSigning {
// Strict inequality comparison lowers to non-constant-time memcmp
if digest !== hash_hmac(hashAlgorithm, padded, decryptKey, true) {
throw new Mismatch("Hash does not match.");
}
}The official patch in commit ad53ab1b2e7ec59b3af92b0b37b8aaa099011137 reorganizes the processing order and introduces constant-time validation. By using hash_equals(), which maps to a constant-time comparison helper, the framework ensures that execution latency remains independent of the input values.
// PATCHED CODE PATH
if true === this->useSigning {
// Verification now uses constant-time hash_equals against the padded data
if true !== hash_equals(hash_hmac(hashAlgorithm, decrypted, decryptKey, true), digest) {
throw new Mismatch("Hash does not match.");
}
}
// Unpadding is deferred until after successful signature verification
return this->decryptGetUnpadded(
mode,
blockSize,
decrypted
);Exploiting this timing side-channel requires high-precision latency profiling over a network interface. Because the execution variance introduced by memcmp is on the order of nanoseconds or microseconds, the attacker must mitigate network jitter by collecting multiple timing samples for each candidate byte value.
The attack begins with a baseline assessment where the attacker supplies an arbitrary ciphertext and a random HMAC tag. The attacker then iterates through all possible byte values (0x00 to 0xFF) for the first byte of the signature. By analyzing the statistical distribution of response times, the attacker identifies the single candidate value that produces a statistically significant increase in execution time, indicating that the comparison reached the second byte.
Once the first byte is determined, the attacker fixes its value and repeats the procedure for the second byte. This process is repeated sequentially for each byte of the signature. After reconstructing the valid HMAC tag for a manipulated ciphertext, the attacker can submit the forged payload, which the application will accept as authentic, bypassing all integrity controls.
The impact of CVE-2026-54736 is critical because it compromises the core security guarantees of Phalcon's encryption wrapper. When applications rely on Crypt::decrypt() to process sensitive data, such as session cookies, password reset tokens, or stateful identifiers, the ability to forge valid signatures allows for comprehensive integrity violation.
Depending on the application logic, payload forgery can lead to privilege escalation, session hijacking, or arbitrary state manipulation. For example, if an application stores serialized user sessions inside an encrypted cookie, an attacker who successfully recovers the HMAC signature can modify the session properties to gain administrator access.
Although the attack complexity is rated as High due to the statistical profiling required to overcome network noise, the impact is severe because it requires no prior authentication or administrative privileges. This vulnerability is assigned a CVSS v4.0 base score of 8.2, reflecting the critical integrity compromise without direct confidentiality leak from the channel itself.
The primary remediation path is upgrading the Phalcon framework extension and its associated PHP library dependencies to version 5.14.1 or higher. This release integrates the constant-time hash_equals verification mechanism and enforces correct Encrypt-then-MAC order of operations.
For environments where immediate system upgrades are not feasible, network-level mitigations must be implemented. Security teams should deploy Web Application Firewall (WAF) rules or rate-limiting policies that restrict the volume of consecutive, failing requests to endpoints utilizing the decryption routine. Because the attack relies on thousands of precise requests to isolate each byte, aggressive rate limits will disrupt the profiling phase.
Additionally, developers should audit their codebases to ensure that they do not expose detailed cryptographic error messages to the client. Detailed exceptions, such as 'Hash does not match' versus general application errors, should be caught internally and logged, returning only generic status codes to external users.
CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
cphalcon Phalcon | < 5.14.1 | 5.14.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-208 |
| Attack Vector | Network |
| CVSS v4.0 | 8.2 (High) |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
The product uses a non-constant-time algorithm to compare sensitive cryptographic secrets, allowing attackers to infer the value of the secret through timing analysis.
CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.
In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.