{"record":{"id":"4d53e7c58c08c7fe","repo":"digininja/DVWA","slug":"token-is-in-wrong-format","errorCode":null,"errorMessage":"Token is in wrong format","messagePattern":"Token is in wrong format","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"vulnerabilities/cryptography/source/medium.php","lineNumber":23,"sourceCode":"\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\");\n\t\t\t} else {\n\t\t\t\t$decrypted = decrypt(hex2bin ($token), $key);\n\n\t\t\t\t$user = json_decode ($decrypted);\n\t\t\t\tif ($user === null) {\n\t\t\t\t\tthrow new Exception (\"Could not decode JSON object.\");\n\t\t\t\t}\n\n\t\t\t\tif ($user->user == \"sweep\" && $user->ex > time() && $user->level == \"admin\") {\n\t\t\t\t\t$success = \"Welcome administrator Sweep\";\n\t\t\t\t} else {\n\t\t\t\t\t$messages = \"Login successful but not as the right user.\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch(Exception $e) {\n\t\t$errors = $e->getMessage();\n\t}","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/digininja/DVWA/blob/5d5c76cced604e54462b13723f5c69af58e78748/vulnerabilities/cryptography/source/medium.php#L5-L41","documentation":"Cheap length gate before any cryptography: the hex-encoded token must have a strlen that is a multiple of 32, because each 16-byte AES block is 32 hex characters. The check says nothing about the characters being valid hex - that surfaces later as a decrypt failure - it only rejects lengths that cannot represent whole blocks.","triggerScenarios":"A token with an odd number of characters; a truncated or extended hex string; a trailing newline or space copied along from the textarea (adds 1-2 characters); pasting a base64 token instead of hex; concatenating two tokens with a stray separator character.","commonSituations":"Terminal/editor copy-paste picking up whitespace; manual editing of hex strings; mixing encodings between systems (base64 vs hex); scripts that join or slice hex without checking alignment.","solutions":["Re-copy one of the sample tokens exactly - each is 128 hex characters.","Strip surrounding whitespace before submitting (the handler does not trim for you).","Verify strlen(token) % 32 == 0 and the string is pure hex.","If generating tokens, bin2hex() raw CBC/ECB ciphertext so the length is inherently block-aligned."],"exampleFix":"// before\n$token = $_POST['token'];\n// after\n$token = trim($_POST['token'] ?? '');","handlingStrategy":"validation","validationCode":"$token = trim($_POST['token'] ?? '');\nif ($token === '' || strlen($token) % 32 !== 0 || !ctype_xdigit($token)) {\n    $errors = 'Token is in wrong format';\n    return;\n}","typeGuard":"function isWellFormedHexToken(string $token): bool\n{\n    return $token !== ''\n        && ctype_xdigit($token)\n        && strlen($token) % 32 === 0;\n}","tryCatchPattern":"} catch (Exception $e) {\n    if ($e->getMessage() === 'Token is in wrong format') {\n        $errors = 'Token must be hex, whole 16-byte blocks (32 chars per block), no whitespace.';\n    } else {\n        $errors = $e->getMessage();\n    }\n}","preventionTips":["trim() POSTed tokens before length checks - trailing newlines are the most common cause.","Enforce a hex pattern client-side (^[0-9a-fA-F]+$) with length % 32 == 0.","Reject odd-length strings early; they can never be valid hex of block-aligned ciphertext."],"tags":["php","validation","hex","aes-block-size","dvwa"],"backgroundTag":"invalid-input-format","analyzedSha":"5d5c76cced604e54462b13723f5c69af58e78748","analyzedAt":"2026-08-21T01:20:26.904Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}