{"record":{"id":"58f17e6bf148829d","repo":"digininja/DVWA","slug":"decryption-failed","errorCode":null,"errorMessage":"Decryption failed","messagePattern":"Decryption failed","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"vulnerabilities/cryptography/source/medium.php","lineNumber":5,"sourceCode":"<?php\nfunction decrypt ($ciphertext, $key) {\n\t$e = openssl_decrypt($ciphertext, 'aes-128-ecb', $key, OPENSSL_PKCS1_PADDING);\n\tif ($e === false) {\n\t\tthrow new Exception (\"Decryption failed\");\n\t}\n\treturn $e;\n}\n\n$key = \"ik ben een aardbei\";\n\n$errors = \"\";\n$success = \"\";\n$messages = \"\";\n\nif ($_SERVER['REQUEST_METHOD'] == \"POST\") {\n\ttry {\n\t\tif (!array_key_exists ('token', $_POST)) {\n\t\t\tthrow new Exception (\"No token passed\");\n\t\t} else {\n\t\t\t$token = $_POST['token'];\n\t\t\tif (strlen($token) % 32 != 0) {\n\t\t\t\tthrow new Exception (\"Token is in wrong format\");","sourceCodeStart":1,"sourceCodeEnd":23,"githubUrl":"https://github.com/digininja/DVWA/blob/5d5c76cced604e54462b13723f5c69af58e78748/vulnerabilities/cryptography/source/medium.php#L1-L23","documentation":"decrypt() wraps openssl_decrypt with cipher aes-128-ecb, the hard-coded key \"ik ben een aardbei\" and OPENSSL_PKCS1_PADDING, and throws this Exception whenever openssl returns false. ECB has no IV, so a false result means one of: the raw bytes (after hex2bin) were not produced with the same key, the ciphertext length is not a multiple of the 16-byte AES block, or the decrypted PKCS padding did not validate (corrupted or spliced ciphertext).","triggerScenarios":"POSTing a hex token encrypted with a different key or mode (for example re-using the high-level key 'rainbowclimbinghigh'); submitting an empty token, which passes the % 32 length gate (0 % 32 == 0) and makes openssl_decrypt fail on empty input; hex containing non-hex characters so hex2bin yields garbage; block-splicing ECB blocks so the final block's padding no longer validates; raw ciphertext not a multiple of 16 bytes.","commonSituations":"Copy/paste truncation of the sample tokens; re-encrypting tokens externally (other languages reject or pad the 18-byte key differently from PHP's zero-padding, so cross-stack tokens fail); editing hex in editors that introduce smart quotes or whitespace; OpenSSL configuration differences between environments.","solutions":["Resubmit one of the three provided sample tokens unchanged to confirm the happy path decrypts.","Verify the token is pure hex, even-length, and a multiple of 32 characters before submitting.","When crafting your own token, encrypt with aes-128-ecb using the exact key \"ik ben een aardbei\" (PHP zero-pads it), then bin2hex() the raw ciphertext.","Confirm the openssl extension is loaded and check the PHP error log for openssl warnings.","Remember the decrypted plaintext must then be valid JSON or you hit the next exception."],"exampleFix":"// before\n$decrypted = decrypt(hex2bin ($token), $key);\n// after\n$raw = hex2bin($token);\nif ($raw === false || strlen($raw) === 0 || strlen($raw) % 16 !== 0) {\n    throw new Exception(\"Token is in wrong format\");\n}\n$decrypted = decrypt($raw, $key);","handlingStrategy":"try-catch","validationCode":"$token = trim($_POST['token'] ?? '');\nif ($token === '' || !ctype_xdigit($token) || strlen($token) % 32 !== 0) {\n    $errors = 'Token is in wrong format';\n} else {\n    $raw = hex2bin($token);\n    if ($raw === false || strlen($raw) % 16 !== 0) {\n        $errors = 'Token is in wrong format';\n    }\n}","typeGuard":"function isHexEncryptedToken(string $token): bool\n{\n    return $token !== ''\n        && ctype_xdigit($token)\n        && strlen($token) % 32 === 0;\n}","tryCatchPattern":"try {\n    $decrypted = decrypt(hex2bin($token), $key);\n} catch (Exception $e) {\n    // Distinguish crypto failure from transport/shape failures for actionable messages\n    error_log('Token decrypt failed: ' . $e->getMessage());\n    $errors = 'Token could not be decrypted with the expected key and mode.';\n}","preventionTips":["Validate hex characters and block alignment before calling openssl_decrypt.","Keep cipher, key, and encoding configuration in one place so producer and consumer cannot drift.","Log openssl_error_string() when decrypt returns false to capture the concrete OpenSSL reason.","Treat decrypt failure on user input as expected control flow, not a crash."],"tags":["php","openssl","aes-128-ecb","cryptography","padding","dvwa"],"backgroundTag":"openssl-decrypt-failed","analyzedSha":"5d5c76cced604e54462b13723f5c69af58e78748","analyzedAt":"2026-08-21T01:20:26.904Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}