Tarayıcı, isteği kim başlatmış olursa olsun, alan adınıza giden her istekte çerezlerinizi de yollar. Yani başka bir sitedeki bir sayfa, sizin sitenize gönderim yapan bir form barındırabilir; ziyaretçiniz oturum açmışsa istek kimliği doğrulanmış olarak varır ve kayıtlarınızda tümüyle meşru görünür.
Neler yapabilir
- Bir e-posta adresini değiştirip ardından yeni adrese parola sıfırlama isteyebilir.
- Sipariş verebilir, bir şey aktarabilir, bir şey silebilir.
- Sitenizin bir POST ve bir oturumla yaptığı her şeyi.
Jeton
Oturumda saklanan ve formda yinelenen rastgele bir değer. Başka bir sitedeki sayfa sizin oturumunuzu okuyamaz, dolayısıyla o değeri bilemez.
// when rendering the form
$_SESSION["csrf"] = $_SESSION["csrf"] ?? bin2hex(random_bytes(32));
?>
<input type="hidden" name="csrf" value="<?= htmlspecialchars($_SESSION['csrf']) ?>">
// when handling it
if (!hash_equals($_SESSION["csrf"] ?? "", $_POST["csrf"] ?? "")) {
http_response_code(400); exit;
}
== ile değil, hash_equals ile karşılaştırın. Düz karşılaştırma ilk farklı karakterde durur ve harcadığı süre, jetonun ne kadarının doğru olduğunu sızdırır.
Ve çerez özniteliği
session.cookie_samesite = Lax
SameSite=Lax, tarayıcıya siteler arası bir POST'ta çerezi hiç göndermemesini söyler; böylece bu saldırı sınıfı kodunuz görmeden durdurulur. Bu bir ikinci katmandır, yedek değil: yalnızca tarayıcının güncel ve uslu olduğu yerde korur.
GET hiçbir şeyi değiştirmemeli
Bir şeyi silen bağlantı, olmayı bekleyen bir CSRF'tir — daha da kötüsü, bir tarayıcı robotu ya da bağlantı önizlemesi onu kendiliğinden tetikler. Durumu değiştiren her şey, jetonlu bir POST'tur.
Bir çatı bunu yerleşik ve açık getirir. Bir şeyin çalışması için tek bir uç noktada kapattıysanız, bakmanız gereken uç nokta tam olarak odur.