1. Vulnerability Topic
Insecure deserialization in CSRF token validation via attacker-controlled biny-csrf cookie.
2. Vendor / GitHub Repo
Tencent / Tencent/Biny
3. Product Name
Biny PHP Framework
4. Release Version / Commit Hash / Affected Range
Observed in the packaged source for Biny release 2.10.11 as indicated in ReadMe.md.
Affected range is not fully determined from the minimal source package. Any version containing the same Request::validateCsrfToken() logic is likely affected.
5. Vulnerability Type
PHP object injection through unsafe deserialization of attacker-controlled cookie data.
6. CWE
CWE-502: Deserialization of Untrusted Data
7. Vulnerability Summary
biny\lib\Request::validateCsrfToken() deserializes the biny-csrf cookie before verifying the HMAC that is prepended when the cookie is generated. An attacker can supply any 64-byte prefix followed by a serialized PHP payload. The code strips the prefix and passes the remaining bytes to unserialize(), enabling attacker-controlled object deserialization before the CSRF token comparison fails.
The standalone PoC demonstrates that a crafted cookie reaches unserialize() and executes a test gadget's __wakeup() method even though validateCsrfToken() ultimately returns false.
8. Root Cause
Cookie creation adds a hash prefix:
private function hashData($data, $key)
{
$hash = hash_hmac('sha256', $data, $key);
return $hash . $data;
}
createCsrfToken() stores:
App::$base->response->setCookie($trueKey, $this->hashData(serialize([$trueKey, $trueToken]), 'platformtest'));
But validation only calculates the expected hash length and strips that many bytes. It never verifies that the prefix matches the serialized suffix:
$trueToken = $_COOKIE[$trueToken];
$test = @hash_hmac('sha256', '', '', false);
$hashLength = mb_strlen($test, '8bit');
$trueToken = unserialize(mb_substr($trueToken, $hashLength, mb_strlen($trueToken, '8bit'), '8bit'))[1];
The missing integrity check turns a cookie value into an untrusted deserialization source.
9. Attack Preconditions
- The target application uses Biny's default
Action base class with $csrfValidate = true.
- The attacker can cause a non-GET/HEAD/OPTIONS request to reach a Biny action from a non-whitelisted IP.
- The attacker can set or inject the
biny-csrf cookie value for the target application domain.
- Practical high-impact exploitation requires an autoloaded PHP class with exploitable magic methods (
__wakeup, __destruct, __toString, etc.).
10. Impact Analysis
The vulnerability provides a framework-level PHP object injection primitive. The PoC proves magic-method execution during CSRF validation. Depending on the application and installed dependencies, this can lead to arbitrary code execution, file write/delete, SSRF, data exfiltration, or denial of service. Even without a known gadget chain in the minimal source package, deserializing attacker-controlled cookie data before authentication/CSRF rejection is a security vulnerability.
11. Affected Code
File: lib/business/Request.php
Relevant code:
$trueToken = $_COOKIE[$trueToken];
$test = @hash_hmac('sha256', '', '', false);
$hashLength = mb_strlen($test, '8bit');
$trueToken = unserialize(mb_substr($trueToken, $hashLength, mb_strlen($trueToken, '8bit'), '8bit'))[1];
Default reachability through lib/business/Action.php:
protected $csrfValidate = true;
...
if ($this->csrfValidate && !$this->request->validateCsrfToken()) {
header(App::$base->config->get(401, 'http'));
echo $this->response->error("Unauthorized");
exit;
}
12. PoC
https://github.com/fa1c4/security-advisories/tree/main/biny
Expected vulnerable output:
validateCsrfToken() returned: false
wakeup marker: TRIGGERED
[VULNERABLE] Attacker-controlled biny-csrf cookie reached unserialize() and executed ProofGadget::__wakeup() before CSRF rejection.
1. Vulnerability Topic
Insecure deserialization in CSRF token validation via attacker-controlled
biny-csrfcookie.2. Vendor / GitHub Repo
Tencent /
Tencent/Biny3. Product Name
Biny PHP Framework
4. Release Version / Commit Hash / Affected Range
Observed in the packaged source for Biny release
2.10.11as indicated inReadMe.md.Affected range is not fully determined from the minimal source package. Any version containing the same
Request::validateCsrfToken()logic is likely affected.5. Vulnerability Type
PHP object injection through unsafe deserialization of attacker-controlled cookie data.
6. CWE
CWE-502: Deserialization of Untrusted Data
7. Vulnerability Summary
biny\lib\Request::validateCsrfToken()deserializes thebiny-csrfcookie before verifying the HMAC that is prepended when the cookie is generated. An attacker can supply any 64-byte prefix followed by a serialized PHP payload. The code strips the prefix and passes the remaining bytes tounserialize(), enabling attacker-controlled object deserialization before the CSRF token comparison fails.The standalone PoC demonstrates that a crafted cookie reaches
unserialize()and executes a test gadget's__wakeup()method even thoughvalidateCsrfToken()ultimately returnsfalse.8. Root Cause
Cookie creation adds a hash prefix:
createCsrfToken()stores:But validation only calculates the expected hash length and strips that many bytes. It never verifies that the prefix matches the serialized suffix:
The missing integrity check turns a cookie value into an untrusted deserialization source.
9. Attack Preconditions
Actionbase class with$csrfValidate = true.biny-csrfcookie value for the target application domain.__wakeup,__destruct,__toString, etc.).10. Impact Analysis
The vulnerability provides a framework-level PHP object injection primitive. The PoC proves magic-method execution during CSRF validation. Depending on the application and installed dependencies, this can lead to arbitrary code execution, file write/delete, SSRF, data exfiltration, or denial of service. Even without a known gadget chain in the minimal source package, deserializing attacker-controlled cookie data before authentication/CSRF rejection is a security vulnerability.
11. Affected Code
File:
lib/business/Request.phpRelevant code:
Default reachability through
lib/business/Action.php:12. PoC
https://github.com/fa1c4/security-advisories/tree/main/binyExpected vulnerable output: