สำหรับรหัสความปลอดภัยโปรดอย่าสร้างโทเค็นของคุณด้วยวิธีนี้: $token = md5(uniqid(rand(), TRUE));
ลองสิ่งนี้:
การสร้างโทเค็น CSRF
PHP 7
session_start();
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
$token = $_SESSION['token'];
Sidenote: หนึ่งในโครงการโอเพ่นซอร์สของนายจ้างของฉันคือความคิดริเริ่มในการ backport random_bytes()
และrandom_int()
ในโครงการ PHP 5 มัน MIT ได้รับอนุญาตและมีอยู่บน Github และนักแต่งเพลงที่เป็นparagonie / random_compat
PHP 5.3+ (หรือ ext-mcrypt)
session_start();
if (empty($_SESSION['token'])) {
if (function_exists('mcrypt_create_iv')) {
$_SESSION['token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
} else {
$_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32));
}
}
$token = $_SESSION['token'];
การตรวจสอบโทเค็น CSRF
อย่าเพิ่งใช้==
หรือแม้กระทั่ง===
ใช้hash_equals()
(PHP 5.6+ เท่านั้น แต่ใช้ได้กับเวอร์ชันก่อนหน้าที่มีไลบรารีที่เข้ากันได้กับแฮช )
if (!empty($_POST['token'])) {
if (hash_equals($_SESSION['token'], $_POST['token'])) {
} else {
}
}
ก้าวต่อไปด้วย Per-Form Token
คุณสามารถ จำกัด โทเค็นเพิ่มเติมเพื่อให้ใช้ได้เฉพาะในรูปแบบเฉพาะโดยใช้ hash_hmac()
ราชสกุลเพียงสามารถใช้ได้สำหรับรูปแบบเฉพาะโดยใช้ HMAC เป็นฟังก์ชันแฮชที่มีคีย์โดยเฉพาะซึ่งปลอดภัยต่อการใช้งานแม้จะมีฟังก์ชันแฮชที่อ่อนแอกว่า (เช่น MD5) อย่างไรก็ตามขอแนะนำให้ใช้ฟังก์ชันแฮชตระกูล SHA-2 แทน
ขั้นแรกให้สร้างโทเค็นที่สองเพื่อใช้เป็นคีย์ HMAC จากนั้นใช้ตรรกะเช่นนี้เพื่อแสดงผล:
<input type="hidden" name="token" value="<?php
echo hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
?>" />
จากนั้นใช้การดำเนินการที่สอดคล้องกันเมื่อตรวจสอบโทเค็น:
$calc = hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
if (hash_equals($calc, $_POST['token'])) {
}
$_SESSION['second_token']
ราชสกุลที่สร้างขึ้นสำหรับรูปแบบหนึ่งไม่สามารถนำกลับมาใช้ในบริบทอื่นโดยไม่ทราบว่าสิ่งสำคัญคือคุณต้องใช้โทเค็นแยกต่างหากเป็นคีย์ HMAC ไม่ใช่โทเค็นที่คุณเพิ่งวางลงบนเพจ
โบนัส: Hybrid Approach + Twig Integration
ใครก็ตามที่ใช้เครื่องมือสร้างเทมเพลต Twigจะได้รับประโยชน์จากกลยุทธ์คู่ที่เรียบง่ายโดยการเพิ่มตัวกรองนี้ในสภาพแวดล้อม Twig:
$twigEnv->addFunction(
new \Twig_SimpleFunction(
'form_token',
function($lock_to = null) {
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
if (empty($_SESSION['token2'])) {
$_SESSION['token2'] = random_bytes(32);
}
if (empty($lock_to)) {
return $_SESSION['token'];
}
return hash_hmac('sha256', $lock_to, $_SESSION['token2']);
}
)
);
ด้วยฟังก์ชั่น Twig นี้คุณสามารถใช้โทเค็นเอนกประสงค์ทั้งสองแบบดังนี้:
<input type="hidden" name="token" value="{{ form_token() }}" />
หรือตัวแปรที่ถูกล็อค:
<input type="hidden" name="token" value="{{ form_token('/my_form.php') }}" />
Twig เกี่ยวข้องกับการแสดงเทมเพลตเท่านั้น คุณยังต้องตรวจสอบโทเค็นอย่างถูกต้อง ในความคิดของฉันกลยุทธ์ Twig ให้ความยืดหยุ่นและความเรียบง่ายมากขึ้นในขณะที่ยังคงรักษาความเป็นไปได้เพื่อความปลอดภัยสูงสุด
โทเค็น CSRF แบบใช้ครั้งเดียว
หากคุณมีข้อกำหนดด้านความปลอดภัยว่าโทเค็น CSRF แต่ละรายการได้รับอนุญาตให้ใช้งานได้เพียงครั้งเดียวกลยุทธ์ที่ง่ายที่สุดจะสร้างใหม่หลังจากการตรวจสอบความถูกต้องสำเร็จแต่ละครั้ง อย่างไรก็ตามการทำเช่นนี้จะทำให้โทเค็นก่อนหน้าทุกรายการไม่ถูกต้องซึ่งไม่สามารถใช้ร่วมกับผู้ที่เรียกดูหลายแท็บพร้อมกันได้
Paragon Initiative Enterprises ดูแลห้องสมุดต่อต้าน CSRFสำหรับกรณีมุมเหล่านี้ ใช้งานได้กับโทเค็นแบบใช้ครั้งเดียวต่อรูปแบบโดยเฉพาะ เมื่อโทเค็นถูกเก็บไว้เพียงพอในข้อมูลเซสชัน (การกำหนดค่าเริ่มต้น: 65535) จะหมุนเวียนโทเค็นที่เก่าที่สุดที่ไม่ได้แลกออกมาก่อน
token_time
ใช้ทำอะไร?