Aktuális helyzet: PHP2Shell. Két kritikus PHP-rés (CVSS 9,2) lehetővé teszi kártékony kód futtatását bejelentkezés nélkül. Javítások 2026. 10. 21. óta.Mi a teendő most →

CSRF-védelem PHP-alkalmazásokban

Hogyan előzik meg a fejlesztők a Cross-Site Request Forgeryt PHP-alkalmazásokban: tokenek minden módosító kéréshez, eredetellenőrzés a fejlécben és SameSite sütik további rétegként.

Állapot 5 perc olvasási időBiztonságos fejlesztés

Röviden: A CSRF-et PHP-ban úgy előzi meg, hogy minden olyan kérésnek, amely valamit módosít, egy titkos, a sessionhöz kötött tokent kell magával hoznia, amelyet a szerver oldalán a hash_equals() függvénnyel ellenőriz. Emellett ellenőrzi az Origin vagy a Sec-Fetch-Site fejlécet, és a session-sütiket SameSite beállítással látja el. A GET-kérések soha nem módosíthatnak adatot, és a bejelentkezési űrlapnak is védelem kell.

Egy kattintás, amelyet senki sem vesz észre

Egy munkatársnő be van jelentkezve a webshop backendjébe, és egy második lapon megnyit egy idegen oldalt. Ez az oldal a háttérben űrlapot küld a backendnek, például egy e-mail-cím módosításához vagy egy fiók létrehozásához. A böngésző automatikusan hozzáfűzi a session-sütit. Az alkalmazás számára a kérés úgy néz ki, mint bármelyik másik a saját csapatból.

Ez a Cross-Site Request Forgery, röviden CSRF: egy kérés, amelyet a bejelentkezett felhasználó tudtán kívül küld egy olyan alkalmazásnak, amelyben megbízik. A támadó nem látja a választ, de nincs is rá szüksége. Elég, hogy a művelet végrehajtódik.

A CSRF nem szerepel a címlapokon, mint a PHP2Shell, de a saját fejlesztésű PHP-alkalmazásokban gyakori megállapítás. Az olyan keretrendszerek, mint a Symfony és a Laravel, védelmet hoznak magukkal; a rések ott főleg ott keletkeznek, ahol egyes útvonalaknál kikapcsolták. A keretrendszer nélküli saját fejlesztéseknél gyakran nincs is.

CSRF PHP-ban: mely kéréseket kell védeni

Védelmet igényel minden olyan kérés, amely állapotot változtat: mentés, törlés, rendelés, jogok kiosztása, beállítások módosítása, fájlok feltöltése, kijelentkezés. Az olvasó hívások nem igényelnek tokent, amíg valóban csak olvasnak.

Ebből következik az első szabály: Nincs módosítás GET-tel. Az olyan linkeket, mint a loeschen.php?id=…, idegen oldalak különösen könnyen kiválthatják, például egy beágyazott képen keresztül. A módosító műveletek POST, PUT, PATCH vagy DELETE metódusba valók.

A második szabály: A bejelentkezést is védeni kell. Az úgynevezett login-CSRF esetén az áldozatot észrevétlenül a támadó egy fiókjába léptetik be. Ha ott fizetési adatokat vagy dokumentumokat ad meg, azok a támadóhoz kerülnek. A bejelentkezési űrlapban lévő token és a sikeres bejelentkezés utáni új session-azonosító ezt megakadályozza.

A synchronizer token minta PHP-ban

A munkamenetekkel dolgozó klasszikus alkalmazásokhoz az OWASP a synchronizer token mintát ajánlja: a szerver véletlenszerű tokent generál, elmenti a sessionben, és minden módosító űrlapban visszavárja. Fontos, hogy a tokent az űrlapban vagy egy saját fejlécben küldjék el, nem sütiben.

<?php
declare(strict_types=1);

function csrfToken(): string
{
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

function csrfPruefen(): void
{
    $gesendet = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
    if (!is_string($gesendet) || !hash_equals(csrfToken(), $gesendet)) {
        http_response_code(403);
        exit('Anfrage abgelehnt.');
    }
}

if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
    csrfPruefen();
}
?>
<form method="post" action="/konto/email">
    <input type="hidden" name="csrf_token"
           value="<?= htmlspecialchars(csrfToken(), ENT_QUOTES, 'UTF-8') ?>">
    <!-- további mezők -->
</form>

A hash_equals() állandó időben hasonlít, így a válaszidő semmit sem árul el a helyes értékről. A bejelentkezés után a session-azonosítót újítsa meg a session_regenerate_id(true) függvénnyel, és hozzon létre új tokent. Hogy a random_bytes() miért a helyes forrás, és mely függvények alkalmatlanok, azt a Biztonságos véletlenszámok és tokenek PHP-ban magyarázza el.

A legtöbb alkalmazásnál elég egy token sessionönként. Az űrlaponkénti vagy kérésenkénti tokenek kissé növelik a védelmet, de gondokat okoznak több nyitott lapnál és a vissza gombnál. A váltás gyakoriságánál fontosabb, hogy a token soha ne jelenjen meg URL-ekben, ahol naplókba, a böngészőelőzményekbe és a Referrer-adatokon keresztül idegen oldalakhoz kerülhet.

A munkamenet nélküli, állapotmentes alkalmazásokhoz az OWASP alternatívaként az aláírt double-submit sütit említi: egy tokent, amelyet HMAC köt a munkamenethez. Az egyszerű, aláíratlan változatot kifejezetten nem ajánlja.

Második réteg: Origin, Sec-Fetch-Site és SameSite

A modern böngészők a kéréseknél információt küldenek az eredetükről. Az Origin fejléc megnevezi a hívó oldalt, a Sec-Fetch-Site pedig megmondja, hogy a kérés ugyanarról az oldalról (same-origin), egy rokon oldalról (same-site) vagy egy idegenről (cross-site) származik-e. Ebből egyszerű kiegészítő ellenőrzés építhető:

<?php
$erlaubteHerkunft = 'https://www.example.de';
$fetchSite = $_SERVER['HTTP_SEC_FETCH_SITE'] ?? null;
$origin    = $_SERVER['HTTP_ORIGIN'] ?? null;

$verdaechtig = ($fetchSite !== null && $fetchSite !== 'same-origin')
    || ($fetchSite === null && $origin !== null && $origin !== $erlaubteHerkunft);

if ($_SERVER['REQUEST_METHOD'] !== 'GET' && $verdaechtig) {
    http_response_code(403);
    exit;
}

Az OWASP itt két pontot hangsúlyoz: az eredetet teljes egészében kell összehasonlítani, hogy a hasonlóan hangzó domainek ne csússzanak át, és egy hiányzó fejléc vagy a null érték nem számíthat saját eredetnek. Mivel a régebbi böngészők nem mindig küldik el a fejléceket, a token marad a fő védelem.

A harmadik réteg a SameSite beállítású session-sütik. A PHP a session.cookie_samesite beállítást a 7.3-as verzió óta támogatja, az alapértelmezett érték üres. Állítson be legalább Lax értéket, tisztán backendeknél gyakran a Strict is lehetséges. A többi süti-beállítást a A sessionök biztonságossá tétele PHP-ban útmutató írja le.

Ha CMS-t használ, az többnyire saját eszközöket hoz magával. A WordPress például úgynevezett noncekkal dolgozik, amelyeket a bővítmények olyan függvényekkel építenek be, mint a wp_nonce_field() és a check_admin_referer(). A gyakorlatban a rések főleg azokban a bővítményekben keletkeznek, amelyek egyes műveleteknél elfelejtik ezeket az ellenőrzéseket. Ezért különösen a saját írású vagy kevéssé elterjedt bővítményeket ellenőrizze.

A más domainekről a böngészőből használt interfészeknél emellett a CORS-konfiguráció dönt. Ha a szerver minden kérő eredetet engedélyezettként ad vissza, és közben sütiket is megenged, maga iktatja ki a böngésző védelmét. Az OWASP azt ajánlja, hogy a CORS-t csak kifejezetten megbízható eredetekre nyissák meg; az összes aldomain átalánydíjas engedélyezése akkor válik problémává, ha valamelyik idegen kézbe kerül.

Ellenőrzőlista meglévő alkalmazásokhoz

Gyarapodott projekteknél a szisztematikus átvizsgálás segít:

  1. Felvenni az összes útvonalat és szkriptet, amely adatot módosít, az Ajax-végpontokat és a fájlfeltöltéseket is.
  2. Ellenőrizni, hogy használnak-e hozzá GET-et, és átállítani POST-ra vagy megfelelő metódusokra.
  3. Minden módosító útvonalnál bizonyítani, hogy tokent ellenőriznek; a keretrendszer kivételeit célzottan keresni.
  4. A bejelentkezést, a kijelentkezést és a jelszómódosítást külön tesztelni.
  5. A session.cookie_samesite beállítást és az eredetellenőrzést kiegészíteni.
  6. Megszüntetni az XSS-réseket, mert a beinjektált kód bármely tokent elolvashat. Az eljárást a Cross-site scripting megelőzése PHP-ban írja le.
Fontos

Az a CSRF-védelem, amelyet csak a frontenden JavaScripttel ellenőriznek, hatástalan. Az ellenőrzésnek a szerveren kell megtörténnie, mielőtt a művelet végrehajtódik.

Hogyan segít konkrétan a PHP SOS?

  • Felmérjük a PHP-alkalmazása összes módosító útvonalát, és ellenőrizzük, hol hiányzik vagy van kikapcsolva a token.
  • Központi ellenőrzési pontot építünk be ahelyett, hogy a tokenellenőrzéseket sok szkriptre szórnánk szét.
  • Kiegészítjük az eredetellenőrzést és a SameSite-beállításokat anélkül, hogy a fizetési vagy bejelentkezési folyamatokat zavarnánk.
  • Az átállítás után újra tesztelünk, és dokumentáljuk az eredményeket.

Az alkalmazás teljes körű ellenőrzését a biztonsági audit és penetrációs teszt szolgáltatás írja le.

Gyakori kérdések

Elég a SameSite=Lax CSRF-védelemként?

Nem. Az OWASP szerint a SameSite sütik további réteget jelentenek, nem pótlást. A Lax a sütiket továbbra is elküldi a normál, GET-tel történő oldalmegnyitásoknál, és ugyanazon weboldal aldomainjeiről érkező támadásokat nem fedi le.

Kell CSRF-token a JSON-API-khoz?

Ha az API sütikkel hitelesít, igen, vagy ezzel egyenértékű ellenőrzés. Alternatíva a saját kérés-fejlécek használata, amelyeket a böngészők idegen oldalaknál csak CORS-előellenőrzés után engednek meg. Ilyenkor a CORS-engedélybe viszont csak kifejezetten megbízható eredetek kerülhetnek.

A bejelentkezési űrlapot is védeni kell?

Igen. A login-CSRF esetén az áldozatot észrevétlenül egy idegen fiókba léptetik be, és ott a saját adatait adja meg. A bejelentkezési űrlapban lévő token és a bejelentkezés utáni új session ezt megakadályozza.

Véd a CSRF-védelem az XSS ellen is?

Fordítva: egy XSS-rés minden CSRF-védelmet kijátszik, mert a beinjektált kód az oldal nevében érvényes tokeneket olvashat és küldhet el. Mindkét sebezhetőséget külön kell megszüntetni.

Források

Azonnali kapcsolat

Minden óra számít. Írjon nekünk most.

Ismertesse röviden a rendszert, a PHP-verziót és a megfigyelését. Jelentkezünk, tisztázzuk a helyzetet, és távolról dolgozunk, amíg az incidens le nem zárul és dokumentálva nem lesz.

Azonnali segítség