*/ $GLOBALS['csrf']['input-name'] = '__csrf_magic'; /** * Set this to false if your site must work inside of frame/iframe elements, * but do so at your own risk: this configuration protects you against CSS * overlay attacks that defeat tokens. */ $GLOBALS['csrf']['frame-breaker'] = true; /** * Whether or not CSRF Magic should be allowed to start a new session in order * to determine the key. */ $GLOBALS['csrf']['auto-session'] = true; /** * Whether or not csrf-magic should produce XHTML style tags. */ $GLOBALS['csrf']['xhtml'] = true; // FUNCTIONS: // Don't edit this! $GLOBALS['csrf']['version'] = '1.0.4'; /** * Rewrites
CSRF check failed. Your form session may have expired, or you may not have cookies enabled.
Debug: $tokens
', $script . '', $buffer, $count); if (!$count) { $buffer .= $script; } } return $buffer; } /** * Checks if this is a post request, and if it is, checks if the nonce is valid. * @param bool $fatal Whether or not to fatally error out if there is a problem. * @return True if check passes or is not necessary, false if failure. */ function csrf_check($fatal = true) { if ($_SERVER['REQUEST_METHOD'] !== 'POST') return true; global $cspNonce; csrf_start(); $name = $GLOBALS['csrf']['input-name']; $ok = false; $tokens = ''; do { if (!isset($_POST[$name])) { #Logger::Debug("POST[$name] is not set"); break; #} else { #Logger::Debug("POST[$name] is set as " . $_POST[$name] ); } // we don't regenerate a token and check it because some token creation // schemes are volatile. $tokens = $_POST[$name]; if (!csrf_check_tokens($tokens)) { #Logger::Debug("Failed checking tokens"); break; #} else { #Logger::Debug("Token passed"); } $ok = true; } while (false); if ($fatal && !$ok) { $callback = $GLOBALS['csrf']['callback']; if (trim($tokens, 'A..Za..z0..9:;,') !== '') $tokens = 'hidden'; $callback($tokens); exit; } return $ok; } /** * Retrieves a valid token(s) for a particular context. Tokens are separated * by semicolons. */ function csrf_get_tokens() { $has_cookies = !empty($_COOKIE); // $ip implements a composite key, which is sent if the user hasn't sent // any cookies. It may or may not be used, depending on whether or not // the cookies "stick" $secret = csrf_get_secret(); if (!$has_cookies && $secret) { // :TODO: Harden this against proxy-spoofing attacks $IP_ADDRESS = (isset($_SERVER['IP_ADDRESS']) ? $_SERVER['IP_ADDRESS'] : $_SERVER['REMOTE_ADDR']); $ip = ';ip:' . csrf_hash($IP_ADDRESS); } else { $ip = ''; } csrf_start(); // These are "strong" algorithms that don't require per se a secret if ($GLOBALS['csrf']['key']) return 'key:' . csrf_hash($GLOBALS['csrf']['key']) . $ip; if (session_id()) return 'sid:' . csrf_hash(session_id()) . $ip; if ($GLOBALS['csrf']['cookie']) { $val = csrf_generate_secret(); setcookie($GLOBALS['csrf']['cookie'], $val); return 'cookie:' . csrf_hash($val) . $ip; } // These further algorithms require a server-side secret if (!$secret) return 'invalid'; if ($GLOBALS['csrf']['user'] !== false) { return 'user:' . csrf_hash($GLOBALS['csrf']['user']); } if ($GLOBALS['csrf']['allow-ip']) { return ltrim($ip, ';'); } return 'invalid'; } function csrf_flattenpost($data) { $ret = array(); foreach($data as $n => $v) { $ret = array_merge($ret, csrf_flattenpost2(1, $n, $v)); } return $ret; } function csrf_flattenpost2($level, $key, $data) { if(!is_array($data)) return array($key => $data); $ret = array(); foreach($data as $n => $v) { $nk = $level >= 1 ? $key."[$n]" : "[$n]"; $ret = array_merge($ret, csrf_flattenpost2($level+1, $nk, $v)); } return $ret; } /** * @param $tokens is safe for HTML consumption */ function csrf_callback($tokens) { // (yes, $tokens is safe to echo without escaping) header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden'); $data = ''; foreach (csrf_flattenpost($_POST) as $key => $value) { if ($key == $GLOBALS['csrf']['input-name']) continue; $data .= ''; } echo "