CSRF-Schutz: Cross-Site Request Forgery verhindern | Enjyn Gruppe
Hallo Welt
→
→
Hallo Welt
Original Lingva Deutsch
Übersetzung wird vorbereitet...
Dieser Vorgang kann bis zu 60 Sekunden dauern.
Diese Seite wird erstmalig übersetzt und dann für alle Besucher gespeichert.
0%
DE Zurück zu Deutsch
Übersetzung durch Lingva Translate

330 Dokumentationen verfügbar

Wissensdatenbank

CSRF Schutz Implementieren

Zuletzt aktualisiert: 14.07.2026 um 12:30 Uhr

CSRF-Schutz: Cross-Site Request Forgery verhindern

CSRF lässt Angreifer Aktionen im Namen Ihrer Nutzer ausführen. Passwort ändern, Geld überweisen, Account löschen – ohne dass der Nutzer es merkt.

Was ist CSRF?

Ein Angreifer bringt einen eingeloggten Nutzer dazu, unbeabsichtigt eine Aktion auszuführen:

<!-- Auf bösartiger Website -->
<img src="https://bank.com/transfer?to=attacker&amount=10000">

<!-- Oder mit verstecktem Formular -->
<form action="https://bank.com/transfer" method="POST" id="evil">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="10000">
</form>
<script>document.getElementById('evil').submit();</script>

Der Browser sendet automatisch die Session-Cookies mit – die Bank sieht eine authentifizierte Anfrage!

Lösung 1: CSRF-Token

Fügen Sie ein geheimes Token hinzu, das Angreifer nicht kennen können.

PHP Implementation

<?php
// Token generieren und in Session speichern
function generateCsrfToken(): string {
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

// Token validieren
function validateCsrfToken(string $token): bool {
    return isset($_SESSION['csrf_token'])
        && hash_equals($_SESSION['csrf_token'], $token);
}
<!-- Im Formular -->
<form method="POST" action="/transfer">
    <input type="hidden" name="csrf_token" value="<?= generateCsrfToken() ?>">
    <input type="text" name="amount">
    <button type="submit">Überweisen</button>
</form>
<?php
// Bei der Verarbeitung
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!validateCsrfToken($_POST['csrf_token'] ?? '')) {
        http_response_code(403);
        die('CSRF-Token ungültig');
    }

    // Request verarbeiten...
}

Node.js mit Express

const csrf = require('csurf');
const cookieParser = require('cookie-parser');

app.use(cookieParser());
app.use(csrf({ cookie: true }));

// Token an Template übergeben
app.get('/form', (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});

// In EJS Template
<form method="POST">
  <input type="hidden" name="_csrf" value="<%= csrfToken %>">
  <button type="submit">Senden</button>
</form>

AJAX-Requests

// Token aus Meta-Tag lesen
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;

// Mit fetch senden
fetch('/api/action', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify(data)
});

// Oder mit axios
axios.defaults.headers.common['X-CSRF-Token'] = csrfToken;

Lösung 2: SameSite Cookies

Moderne Browser unterstützen das SameSite-Attribut:

// Cookies nicht bei Cross-Site Requests senden
Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly

// Oder etwas lockerer (Links erlaubt, Formulare nicht)
Set-Cookie: session=abc123; SameSite=Lax; Secure; HttpOnly
SameSite Verhalten
Strict Nie bei Cross-Site Requests
Lax Nur bei Top-Level Navigation (Links)
None Immer (erfordert Secure)
<?php
// PHP: Session-Cookie mit SameSite
session_set_cookie_params([
    'lifetime' => 0,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Strict'
]);
session_start();

Lösung 3: Double Submit Cookie

Alternative ohne Server-Session:

// 1. Token in Cookie UND in Request senden
// 2. Server vergleicht beide

// Cookie setzen (JavaScript-lesbar)
document.cookie = "csrf_token=random123; path=/; secure";

// Im Formular
<input type="hidden" name="csrf_token" value="random123">

// Server prüft: Cookie == Form-Wert?

Lösung 4: Origin/Referer Header prüfen

<?php
function checkOrigin(): bool {
    $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
    $referer = $_SERVER['HTTP_REFERER'] ?? '';

    $allowedOrigins = ['https://example.com'];

    // Origin-Header bevorzugen
    if ($origin && in_array($origin, $allowedOrigins)) {
        return true;
    }

    // Fallback auf Referer
    if ($referer) {
        $refererHost = parse_url($referer, PHP_URL_HOST);
        return $refererHost === 'example.com';
    }

    return false;
}

Framework-spezifischer CSRF-Schutz

Laravel

{{-- Blade Template --}}
<form method="POST">
    @csrf
    ...
</form>

// Für AJAX
<meta name="csrf-token" content="{{ csrf_token() }}">

// In JavaScript
$.ajaxSetup({
    headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }
});

Django

{% csrf_token %}

// AJAX
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;

Spring Boot

<input type="hidden"
       name="${_csrf.parameterName}"
       value="${_csrf.token}"/>

Best Practices

💡 Empfehlungen:
  • CSRF-Token für alle state-ändernden Requests
  • SameSite=Strict oder Lax für Session-Cookies
  • Keine GET-Requests für Änderungen
  • Token pro Session oder pro Request
  • Sichere Zufallsgeneratoren verwenden

CSRF-Checkliste

  • ☐ CSRF-Token in allen Formularen
  • ☐ Token bei AJAX-Requests senden
  • ☐ SameSite-Attribut für Cookies
  • ☐ Token serverseitig validieren
  • ☐ Keine state-Änderungen via GET

Weitere Informationen

Texterstellung mit KI-Unterstützung

Enjix Beta

Enjyn AI Agent

Hallo 👋 Ich bin Enjix — wie kann ich dir helfen?
LLMs können Fehler machen. Ihre Nachrichten werden an Google Gemini weitergeleitet.
120