Pemalsuan Permintaan Silang Tapak (CSRF) ialah kerentanan keselamatan web yang membenarkan penyerang memperdaya pengguna yang disahkan supaya melaksanakan tindakan yang tidak diingini pada tapak web yang mereka log masuk pada masa ini. Serangan itu berfungsi dengan mengeksploitasi kepercayaan yang dimiliki tapak web dalam penyemak imbas pengguna.
Ini adalah kaedah yang paling biasa. Begini cara untuk melaksanakannya:
// In your session initialization (e.g., at login) session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // In your form function generateFormWithCSRFToken() { return '<form method="POST" action="/submit"> <input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '"> <!-- rest of your form fields --> <input type="submit" value="Submit"> </form>'; } // In your form processing function validateCSRFToken() { if (!isset($_POST['csrf_token']) || !isset($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { die('CSRF token validation failed'); } return true; }
Kaedah ini menggunakan permintaan AJAX dengan pengepala tersuai:
// PHP Backend session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // Validate the token if ($_SERVER['REQUEST_METHOD'] === 'POST') { $headers = getallheaders(); if (!isset($headers['X-CSRF-Token']) || !hash_equals($_SESSION['csrf_token'], $headers['X-CSRF-Token'])) { http_response_code(403); die('CSRF token validation failed'); } } // JavaScript Frontend const csrfToken = '<?php echo $_SESSION["csrf_token"]; ?>'; fetch('/api/endpoint', { method: 'POST', headers: { 'X-CSRF-Token': csrfToken, 'Content-Type': 'application/json' }, body: JSON.stringify(data) });
Kaedah ini melibatkan penghantaran token sebagai kuki dan sebagai parameter permintaan:
// Set both cookie and session token session_start(); $token = bin2hex(random_bytes(32)); $_SESSION['csrf_token'] = $token; setcookie('csrf_token', $token, [ 'httponly' => true, 'secure' => true, 'samesite' => 'Strict' ]); // Validation function function validateDoubleSubmitToken() { if (!isset($_COOKIE['csrf_token']) || !isset($_POST['csrf_token']) || !isset($_SESSION['csrf_token'])) { return false; } return hash_equals($_COOKIE['csrf_token'], $_POST['csrf_token']) && hash_equals($_SESSION['csrf_token'], $_POST['csrf_token']); }
Aplikasi moden juga boleh menggunakan atribut kuki SameSite sebagai lapisan perlindungan tambahan:
// Set cookie with SameSite attribute session_start(); session_set_cookie_params([ 'lifetime' => 0, 'path' => '/', 'domain' => $_SERVER['HTTP_HOST'], 'secure' => true, 'httponly' => true, 'samesite' => 'Strict' ]);
function generateSecureToken($length = 32) { return bin2hex(random_bytes($length)); }
function validateToken($userToken, $storedToken) { if (empty($userToken) || empty($storedToken)) { return false; } return hash_equals($storedToken, $userToken); }
class CSRFProtection { public static function getTokenField() { return sprintf( '<input type="hidden" name="csrf_token" value="%s">', htmlspecialchars($_SESSION['csrf_token']) ); } }
Banyak rangka kerja PHP menyediakan perlindungan CSRF terbina dalam:
// In your session initialization (e.g., at login) session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // In your form function generateFormWithCSRFToken() { return '<form method="POST" action="/submit"> <input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '"> <!-- rest of your form fields --> <input type="submit" value="Submit"> </form>'; } // In your form processing function validateCSRFToken() { if (!isset($_POST['csrf_token']) || !isset($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { die('CSRF token validation failed'); } return true; }
// PHP Backend session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // Validate the token if ($_SERVER['REQUEST_METHOD'] === 'POST') { $headers = getallheaders(); if (!isset($headers['X-CSRF-Token']) || !hash_equals($_SESSION['csrf_token'], $headers['X-CSRF-Token'])) { http_response_code(403); die('CSRF token validation failed'); } } // JavaScript Frontend const csrfToken = '<?php echo $_SESSION["csrf_token"]; ?>'; fetch('/api/endpoint', { method: 'POST', headers: { 'X-CSRF-Token': csrfToken, 'Content-Type': 'application/json' }, body: JSON.stringify(data) });
Perlindungan CSRF adalah penting untuk keselamatan aplikasi web. Walaupun terdapat pelbagai pendekatan untuk melaksanakan perlindungan CSRF, pendekatan berasaskan token menggunakan medan borang tersembunyi kekal sebagai kaedah yang paling banyak digunakan dan boleh dipercayai. Ingat untuk menggabungkan kaedah perlindungan yang berbeza untuk keselamatan yang dipertingkatkan dan sentiasa ikuti amalan terbaik keselamatan apabila melaksanakan perlindungan CSRF dalam aplikasi PHP anda.
Ingat bahawa perlindungan CSRF harus menjadi sebahagian daripada strategi keselamatan yang lebih luas yang merangkumi pengurusan sesi yang betul, pengendalian kuki selamat dan pengesahan input.
Atas ialah kandungan terperinci Perlindungan CSRF dalam PHP. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!