Praegune olukord: PHP2Shell. Kaks kriitilist PHP turvaauku (CVSS 9,2) lubavad kahjulikku koodi ilma sisselogimata. Paigad alates 21.10.2026.Mida nüüd teha →

CSRF-kaitse PHP-rakendustes

Kuidas arendajad hoiavad PHP-rakendustes ära Cross-Site Request Forgery: tokenid igale muutvale päringule, päritolu kontroll päises ja SameSite-küpsised lisakihina.

Seis Lugemisaeg 5 minTurvaline arendus

Lühidalt: CSRF-i hoiate PHP-s ära nii, et iga päring, mis midagi muudab, peab kaasa tooma salajase, sessiooniga seotud tokeni, mida kontrollite serveris funktsiooniga hash_equals(). Lisaks kontrollite päiseid Origin või Sec-Fetch-Site ning seate sessiooniküpsised väärtusega SameSite. GET-päringud ei tohi kunagi andmeid muuta ja ka sisselogimisvorm vajab kaitset.

Klõps, mida keegi ei märka

Töötaja on poe taustasüsteemi sisse logitud ja avab teises vahekaardis võõra lehe. See leht saadab taustal taustasüsteemile vormi, näiteks e-posti aadressi muutmiseks või konto loomiseks. Brauser lisab sessiooniküpsise automaatselt. Rakenduse jaoks näeb päring välja nagu iga teine oma meeskonnalt.

See on Cross-Site Request Forgery, lühidalt CSRF: päring, mille sisselogitud kasutaja saadab teadmatult rakendusele, mida ta usaldab. Ründaja ei näe vastust, kuid ta ei vaja seda ka. Piisab sellest, et toiming sooritatakse.

CSRF ei ole pealkirjades nagu PHP2Shell, kuid on ise arendatud PHP-rakendustes sage leid. Raamistikud, nagu Symfony ja Laravel, toovad kaasa kaitse; augud tekivad seal eelkõige siis, kui see on üksikute marsruutide jaoks välja lülitatud. Raamistikuta omaarendustel puudub see sageli üldse.

CSRF PHP-s: milliseid päringuid tuleb kaitsta

Kaitset vajavad kõik päringud, mis muudavad olekut: salvestamine, kustutamine, tellimine, õiguste andmine, sätete muutmine, failide üleslaadimine, väljalogimine. Lugevad päringud tokenit ei vaja, kui nad tõesti ainult loevad.

Siit tuleneb esimene reegel: Ei mingeid muudatusi GET-iga. Lingid, nagu loeschen.php?id=…, on võõrastelt lehtedelt eriti kergesti vallandatavad, näiteks põimitud pildi kaudu. Muutvad toimingud kuuluvad POST-i, PUT-i, PATCH-i või DELETE-i.

Teine reegel: Kaitske ka sisselogimist. Niinimetatud sisselogimis-CSRF-i puhul logitakse ohver märkamatult ründaja kontole. Kui ta sisestab seal maksete andmeid või dokumente, jõuavad need ründajani. Token sisselogimisvormis ja uus sessiooni-ID pärast edukat sisselogimist hoiavad seda ära.

Sünkroniseerimistokeni muster PHP-s

Klassikaliste rakenduste jaoks sessioonidega soovitab OWASP sünkroniseerimistokeni mustrit: server loob juhusliku tokeni, salvestab selle sessiooni ja ootab seda igas muutvas vormis tagasi. Oluline on, et token saadetakse kaasa vormis või eraldi päises, mitte küpsises.

<?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') ?>">
    <!-- muud väljad -->
</form>

hash_equals() võrdleb konstantse ajaga, nii et vastuseaeg ei reeda õiget väärtust. Pärast sisselogimist peaksite sessiooni-ID funktsiooniga session_regenerate_id(true) uuendama ja looma uue tokeni. Miks random_bytes() on õige allikas ja millised funktsioonid on sobimatud, selgitab Turvalised juhuarvud ja tokenid PHP-s.

Üks token sessiooni kohta piisab enamiku rakenduste jaoks. Tokenid vormi või päringu kohta suurendavad kaitset veidi, kuid toovad probleeme mitme avatud vahekaardi ja tagasinupuga. Olulisem kui vahetamise sagedus on, et token ei ilmuks kunagi URL-idesse, kus see võib jõuda logidesse, brauseri ajalukku ja viitajateabes võõrastele lehtedele.

Sessioonita olekuvabade rakenduste jaoks nimetab OWASP alternatiivina allkirjastatud kahekordse esitamise küpsist (double-submit cookie): token, mis on HMAC-iga seotud seansiga. Lihtsat, allkirjastamata varianti ei soovitata selgesõnaliselt.

Teine kiht: Origin, Sec-Fetch-Site ja SameSite

Kaasaegsed brauserid saadavad päringute juures teavet oma päritolu kohta. Päis Origin nimetab kutsuva lehe, Sec-Fetch-Site ütleb, kas päring pärineb samalt lehelt (same-origin), seotud lehelt (same-site) või võõralt lehelt (cross-site). Sellest saab ehitada lihtsa lisakontrolli:

<?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;
}

OWASP rõhutab seejuures kahte punkti: päritolu tuleb võrrelda täielikult, et sarnase kõlaga domeenid läbi ei lipsaks, ja puuduv päis või väärtus null ei tohi lugeda oma päritoluks. Kuna vanemad brauserid ei saada päiseid alati, jääb põhikaitseks token.

Kolmas kiht on sessiooniküpsised väärtusega SameSite. PHP toetab session.cookie_samesite alates versioonist 7.3, vaikeväärtus on tühi. Seadke vähemalt Lax, puhaste taustasüsteemide jaoks on Strict sageli võimalik. Muud küpsisesätted kirjeldab juhend Sessioonide kaitsmine PHP-s.

Kui kasutate sisuhaldussüsteemi, toob see tavaliselt kaasa omad tööriistad. WordPress töötab näiteks niinimetatud noncede'ga, mida pistikprogrammid kasutavad funktsioonide, nagu wp_nonce_field() ja check_admin_referer(), kaudu. Augud tekivad praktikas eelkõige laiendustes, mis unustavad sellised kontrollid üksikute toimingute juures. Kontrollige seetõttu eriti ise kirjutatud või vähelevinud pistikprogramme.

Liideste puhul, mida brauserid kasutavad teistelt domeenidelt, otsustab lisaks CORS-i konfiguratsioon. Kui server tagastab iga päringu esitaja päritolu lubatuna ja lubab samal ajal küpsiseid, tühistab ta brauseri kaitse ise. OWASP soovitab avada CORS-i ainult selgesõnaliselt usaldusväärsetele päritoludele; kõigi alamdomeenide üldine lubamine muutub probleemiks, niipea kui üks neist satub võõraste kätte.

Kontrollnimekiri olemasolevatele rakendustele

Kasvanud projektide puhul aitab süstemaatiline läbivaatus:

  1. Koguge kõik marsruudid ja skriptid, mis andmeid muudavad, ka Ajax-lõpp-punktid ja failide üleslaadimised.
  2. Kontrollige, kas selleks kasutatakse GET-i, ja viige üle POST-ile või sobivatele meetoditele.
  3. Tõendage iga muutva marsruudi kohta, et tokenit kontrollitakse; otsige raamistikus sihipäraselt erandeid.
  4. Testige sisselogimist, väljalogimist ja parooli muutmist eraldi.
  5. Täiendage session.cookie_samesite ja päritolu kontrolliga.
  6. Kõrvaldage XSS-augud, sest sissetoodud kood saab lugeda iga tokenit. Lähenemise kirjeldab Cross-Site-Scripting'u vältimine PHP-s.
Oluline

CSRF-kaitse, mida kontrollitakse ainult esiosas JavaScriptiga, on mõjutu. Kontroll peab toimuma serveris, enne kui toiming sooritatakse.

Kuidas PHP SOS konkreetselt aitab?

  • Me kaardistame teie PHP-rakenduse kõik muutvad marsruudid ja kontrollime, kus token puudub või on välja lülitatud.
  • Me ehitame sisse keskse kontrollpunkti, selle asemel et jaotada tokenikontrolle paljude skriptide vahel.
  • Me täiendame päritolu kontrolli ja SameSite-sätteid, ilma et maksete või sisselogimise protsessid häiriksid.
  • Me testime pärast ümberseadmist uuesti ja dokumenteerime tulemused.

Teie rakenduse täieliku kontrolli kirjeldab teenus Turvaaudit ja läbitungimistest.

Korduma kippuvad küsimused

Kas SameSite=Lax piisab CSRF-kaitseks?

Ei. SameSite-küpsised on OWASP-i andmetel lisakiht, mitte asendus. Lax saadab küpsised endiselt tavaliste lehepäringute puhul GET-iga ning sama veebisaidi alamdomeenidelt tulevaid rünnakuid see ei kata.

Kas JSON-API-d vajavad CSRF-tokenit?

Kui API autendib küpsistega, siis jah või samaväärset kontrolli. Alternatiiv on oma päringupäised, mida brauserid lubavad võõrastelt lehtedelt ainult CORS-i eelkontrolli järel. Siis tohib CORS-i lubamine aga sisaldada ainult selgesõnaliselt usaldusväärseid päritolusid.

Kas ka sisselogimisvorm tuleb kaitsta?

Jah. Sisselogimis-CSRF-i puhul logitakse ohver märkamatult võõrasse kontosse ja ta sisestab seal oma andmeid. Token sisselogimisvormis ja uus sessioon pärast sisselogimist hoiavad seda ära.

Kas CSRF-kaitse kaitseb ka XSS-i eest?

Vastupidi: XSS-auk tühistab iga CSRF-kaitse, sest sissetoodud kood saab lehe nimel kehtivaid tokeneid lugeda ja kaasa saata. Mõlemad nõrkused tuleb kõrvaldada eraldi.

Allikad

Kohene kontakt

Iga tund loeb. Kirjutage meile kohe.

Kirjeldage lühidalt süsteemi, PHP versiooni ja tähelepanekut. Võtame teiega ühendust, selgitame olukorra välja ja töötame kaugtööna, kuni intsident on lõpetatud ja dokumenteeritud.

Kohene abi