לדלג לתוכן

הגנה מפני מתקפות CSRF (Cross-Site Request Forgery)

מבוא

חולשת CSRF (Cross-Site Request Forgery) היא מתקפה שבה תוקף מנצל את אימות המשתמש כדי לבצע פעולות זדוניות בשמו. המתקפה מתרחשת כאשר המשתמש מחובר לאתר לגיטימי, אך נשלחת בקשה זדונית דרך דף חיצוני.

לדוגמה, אם משתמש מחובר לחשבון הבנק שלו, תוקף יכול לגרום לו ללחוץ על קישור זדוני שישלח בקשה לביצוע העברת כספים – ללא ידיעתו.


כיצד להגן מפני CSRF?

1. שימוש ב-CSRF Tokens

📌 כיצד זה עובד?

  • השרת מייצר טוקן ייחודי לכל משתמש ומוסיף אותו לטפסים.

  • כאשר המשתמש שולח בקשה, השרת בודק שהטוקן תואם.

  • אם הטוקן חסר או שגוי, הבקשה נחסמת.

📌 דוגמה ב-PHP:

session_start();
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));

בטופס HTML:

<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">

ובבדיקה ב-PHP:

if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    die("CSRF detected!");
}

מונע משליחת בקשות ללא טוקן תקין.


2. שימוש ב-SameSite Cookies

📌 כיצד זה עובד?

  • דפדפן שולח את ה-Cookie רק אם הבקשה מגיעה מהאתר עצמו.

  • חוסם שליחת עוגיות דרך דפים חיצוניים.

📌 הגדרה ב-PHP:

setcookie("session", $sessionId, [
    'Secure' => true,
    'HttpOnly' => true,
    'SameSite' => 'Strict'
]);

כך שעכשיו הדפדפן של המשתמש ישלח את העוגיה רק אם הדף שרוצה לשלוח את העוגיה הוא אותו הדף, ודפים אחרים לא יוכלו להשתמש בעוגיות.

מונע שליחת עוגיות דרך דומיינים זדוניים.


3. שימוש ב-Secure Cookies

📌 כיצד זה עובד?

  • דפדפן שולח את ה-Cookie רק אם החיבור מאובטח (HTTPS).

  • מונע גניבת Session דרך HTTP רגיל.

📌 הגדרה ב-PHP:

setcookie("auth", $token, [
    'Secure' => true,
    'HttpOnly' => true
]);

מגן על ה-Cookie מפני הסנפה מתוקף שנמצא ברשת עם הלקוח.


4. הגבלת CORS (Cross-Origin Resource Sharing)

מנגנון CORS (Cross-Origin Resource Sharing) הוא מנגנון אבטחה בדפדפנים שמגביל בקשות HTTP חוצות-מקור (cross-origin) בין דומיינים שונים. הוא פועל באמצעות headers מיוחדים שמגדירים אילו דומיינים מורשים לגשת למשאבים בשרת.

בגדול cors מונע את זה שאתר מסוים שרץ אצלי בדפדפן יוכל לשלוח בקשה לאתר אחר.
ואם אני רוצה שאנשים יוכלו לגשת לאתר שלי מאתרים אחרים, אני צריך לציין זאת בheader מיוחד בתשובת http שלי.

📌 כיצד זה עובד?
לפני שאנחנו מבצעים בקשה כלשהי, הדפדפן שולח בקשה לאותו עמוד רק עם options כmethod ועם header-ים שמציינים את סוג הבקשה שאנחנו רוצים לבצע

OPTIONS /resource HTTP/1.1
Origin: https://external-site.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

והשרת מחזיר איזה סוג בקשות מאושרות, כגון- איזה methods, מאיזה דומיין, וכו.
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://trusted-site.com
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: X-Custom-Header

הדפדפן יוציא את הבקשה רק אם היא מאושרת לפי הheader-ים שקיבל מהשרת.

יישום CORS ב- PHP

דוגמה בסיסית:

<?php
$allowed_origins = [
    'https://mydomain.com',
    'https://app.mydomain.com',
    'https://partner-site.com'
];

$origin = $_SERVER['HTTP_ORIGIN'] ?? '';

if (in_array($origin, $allowed_origins)) {
    header("Access-Control-Allow-Origin: $origin");
    header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
    header("Access-Control-Allow-Headers: Content-Type, Authorization");
}
?>

1. הגבלת CORS ב-.htaccess

ניתן גם להוסיף cors לכל הבקשות באמצעות שינוי htaccess בapache

<IfModule mod_headers.c>
    SetEnvIf Origin "^(https?://(.*\.)?(mydomain|trusted)\.com)$" CORS_ALLOW_ORIGIN=$1
    Header set Access-Control-Allow-Origin "%{CORS_ALLOW_ORIGIN}e" env=CORS_ALLOW_ORIGIN
    Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
    Header set Access-Control-Allow-Headers "Content-Type, Authorization"
    Header set Access-Control-Allow-Credentials "true"
</IfModule>

2. הגנה על API ב-PHP

<?php
// api.php
$allowed = [
    'https://frontend.mydomain.com',
    'https://mobile-app.com'
];

$origin = $_SERVER['HTTP_ORIGIN'] ?? '';

if (!in_array($origin, $allowed)) {
    http_response_code(403);
    die('Access Forbidden');
}

header("Access-Control-Allow-Origin: $origin");
header('Access-Control-Allow-Credentials: true');

// API logic here...
?>

כך שכל בקשה שתגיע לא מהאתר, תיחסם.

קורה הרבה באתרים שהcors ממומש בmiddleware, (קוד שאילו מגיעות הבקשות לפני שמגיעות לשרת הbackend)
כך שכל בקשה שאמורה להגיע ל/api יוסף לה cors.

<?php
// middleware.php
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

if (strpos($path, '/api/') === 0) {
    $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
    if ($origin === 'https://trusted.com') {
        header("Access-Control-Allow-Origin: $origin");
    }
}
?>

סיכום

🔴 CSRF הוא איום רציני, אך ניתן למנוע אותו בעזרת מספר צעדים:

  • ✅ שימוש ב-CSRF Tokens לאימות בקשות.

  • ✅ הגדרת SameSite Cookies למניעת שימוש לרעה בעוגיות.

  • ✅ שימוש ב-Secure Cookies למניעת גניבת מידע.

  • ✅ הגבלת CORS כדי למנוע בקשות חיצוניות לא מורשות.

💡 שילוב מספר הגנות יחד מספק אבטחה מקסימלית נגד CSRF!