Ako zabrániť útokom CSRF (Cross Site Request Forgery) v PHP

Tento článok vás naučí, ako zabrániť útoku CSRF (Cross Site Request Forgery) vo webovej aplikácii PHP tým, že pri každej požiadavke zahrniete náhodný token alebo použijete náhodný názov pre každé pole formulára. Útok CSRF (Cross Site Request Forgery) využíva zraniteľnosť webovej aplikácie, pri ktorej obeť neúmyselne spustí vo svojom prehliadači skript, ktorý využíva jej prihlásenú reláciu na konkrétnej lokalite. Útoky CSRF možno vykonať prostredníctvom požiadaviek GET alebo POST.

Časť 1 z 5:Prehľad metód

Pochopenie týchto dvoch metód vám pomôže zabrániť útokom CSRF na vaše požiadavky GET a POST:

  • Zahrnutie náhodného tokenu s každou požiadavkou. Toto je jedinečný reťazec, ktorý sa generuje pre každú reláciu. Vygenerujeme token a potom ho zahrnieme do každého formulára ako skrytý vstup. Systém potom skontroluje, či je formulár platný, porovnaním tokenu s tokenom uloženým v premennej relácie používateľa. Útočník nebude môcť vygenerovať požiadavku bez znalosti hodnoty tokenu.
  • Použitie náhodného názvu pre každé pole formulára. Hodnota náhodného názvu pre každé pole je uložená v premennej relácie. Po odoslaní formulára systém vygeneruje novú náhodnú hodnotu. Aby bol útočník úspešný, musel by uhádnuť tieto náhodné názvy formulárov.
    • Napríklad požiadavka, ktorá kedysi vyzerala takto:
    • Teraz bude vyzerať takto:

Druhá časť z 5:Vytvorenie súboru triedy CSRF

Vytvoriť csrf.trieda.php. Toto je súbor, ktorý bude obsahovať všetky funkcie, ktoré sa budú používať na zabránenie útokom CSRF.

<?php
class csrf {

Uloženie súboru.

  • Všetok kód v častiach 2 a 3 bude pridaný na koniec tohto súboru.

Časť 3 z 5:Pridanie náhodného tokenu

Vytvorte get_token_id() funkcia. Táto funkcia načíta ID tokenu z relácie používateľa a ak ešte nebol vytvorený, vygeneruje náhodný token.

public function get_token_id() {
if(isset($_SESSION['token_id'])) {
return $_SESSION['token_id'];
} else {
$token_id = $this->random(10);
$_SESSION['token_id'] = $token_id;
return $token_id;

Vytvorenie get_token() funkciu. Táto funkcia načíta hodnotu tokenu, alebo ak nebola vygenerovaná, vygeneruje hodnotu tokenu.

public function get_token() {
if(isset($_SESSION['token_value'])) {
return $_SESSION['token_value'];
} else {
$token = hash('sha256', $this->random(500));
$_SESSION['token_value'] = $token;
return $token;

Vytvorenie check_valid() funkcia. Táto funkcia určuje, či sú ID tokenu a hodnota tokenu platné. Toto sa vykoná porovnaním hodnôt požiadavky GET alebo POST s hodnotami uloženými v premennej SESSION používateľa.

verejná funkcia check_valid($method) {
if($method == 'post' || $method == 'get') {
$post = $_POST;
$get = $_GET;
if(isset(${$method}[$this->get_token_id()]) && (${$method}[$this->get_token_id()] == $this->get_token()) {
return true;
} else {
return false;
} else {
return false;

Časť 4 z 5:Generovanie náhodného názvu pre každé pole formulára

Vytvorte form_names() funkcia. Táto funkcia generuje náhodné názvy polí formulára.

public function form_names($names, $regenerate) {
$values = array();
foreach ($names as $n) {
if($regenerate == true) {
unset($_SESSION[$n]);
$s = isset($_SESSION[$n]) ? $_SESSION[$n] : $this->random(10);
$_SESSION[$n] = $s;
$values[$n] = $s;
return $values;

Vytvoriť random funkcia. Táto funkcia generuje náhodný reťazec pomocou náhodného súboru Linuxu na vytvorenie väčšej entropie.

private function random($len) {
if (function_exists('openssl_random_pseudo_bytes') {
$byteLen = intval(($len / 2) + 1);
$return = substr(bin2hex(openssl_random_pseudo_bytes($byteLen)), 0, $len);
} elseif (@is_readable('/dev/urandom') {
$f=fopen('/dev/urandom', 'r');
$urandom=fread($f, $len);
fclose($f);
$return = '';
if (empty($return)) {
for ($i=0;$i<$len;++$i) {
if (!isset($urandom)) {
if ($i%2==0) {
mt_srand(time()%2147 * 1000000 + (double)microtime() * 1000000);
$rand=48+mt_rand()%64;
} else {
$rand=48+ord($urandom[$i])%64;
if ($rand>57)
$rand+=7;
if ($rand>90)
$rand+=6;
if ($rand==123) $rand=52;
if ($rand==124) $rand=53;
$return.=chr($rand);
return $return;

Zatvoriť triedu csrf zátvorka.

}

Zatvorte csrf.trieda.php súbor.

Časť 5 z 5:Používanie súboru triedy CSRF

  • Pridanie súboru triedy CSRF do formulára POST. Kód na obrázku ukazuje, ako pridať súbor triedy CSRF do formulára POST s cieľom zabrániť útoku CSRF.

    <?php
    session_start();
    include 'csrf.trieda.php";
    $csrf = new csrf();
    // Vygenerujte token Id a Valid
    $token_id = $csrf->get_token_id();
    $token_value = $csrf->get_token($token_id);
    // Generovanie náhodných názvov formulárov
    $form_names = $csrf->form_names(array('user', 'password'), false);
    if(isset($_POST[$form_names['user']], $_POST[$form_names['password']]) {
    // Kontrola, či sú id tokenu a hodnota tokenu platné.
    if($csrf->check_valid('post')) {
    // Získajte premenné formulára.
    $user = $_POST[$form_names['user']];
    $password = $_POST[$form_names['password']];
    // Sem patrí funkcia formulára
    // Regenerujte novú náhodnú hodnotu pre formulár.
    $form_names = $csrf->form_names(array('user', 'password'), true);
    ?>
    <form action="index.php" method="post">
    <input type="hidden" name="<?= $token_id; ?>" value="<?= $token_value; ?>" />
    <input type="text" name="<?= $form_names['user']; ?>" /><br/>
    <input type="text" name="<?= $form_names['password']; ?>" />
    <input type="submit" value="Login"/>
    </form>