Come Prevenire Attacchi Cross Site Request Forgery (CSRF) in PHP

In questo Articolo:Descrizione dei MetodiCreare il File csrf.class.phpProteggere le Pagine con csrf.class.php

Un attacco di Cross Site Request Forgery (CSRF) è un tipo di vulnerabilità da applicazione web dove la vittima esegue involontariamente uno script nel browser che si avvale della sessione di connessione a un particolare sito. Gli attacchi CSRF possono essere eseguiti su richieste GET o POST. Questo articolo ti mostrerà come evitare gli attacchi CSRF sulle tue applicazioni web.

1
Descrizione dei Metodi

Utilizzeremo due metodi per evitare gli attacchi CSRF sulle tue richieste GET e POST.


Il primo è includere un token casuale con ogni richiesta, che è una stringa univoca generata per ogni sessione. Generiamo il token e poi lo includiamo in ogni modulo come input nascosto. Il sistema controlla se il modulo è valido confrontando il token con quello memorizzato nella variabile di sessione degli utenti. Questo significa che un utente malintenzionato, affinché possa generare una richiesta, deve conoscere il valore del token.


Il secondo metodo consiste nell'utilizzare il nome casuale per ogni campo del modulo. Il valore del nome casuale per ogni campo è memorizzato in una variabile di sessione e, dopo che il modulo è stato presentato, il sistema genera un nuovo valore casuale. Questo significa che, perché un attacco funzioni, l'attaccante dovrebbe indovinare questi nomi casuali di moduli.


Ad esempio una richiesta che una volta si presentava così:

ora sarà simile a questa:

2
Creare il File csrf.class.php

Questo è il file main che contiene tutte le funzioni che verranno utilizzate per prevenire gli attacchi CSRF.

  1. 1
    Crea csrf.class.php. Inizia creando il file con il contenuto sottostante e salvandolo:

    <?php
    class csrf {
    
    Tutto il codice in questa sezione della guida verrà aggiunto alla fine di questo file.
  2. 2
    Crea la funzione get_token_id() Function.
    Questa funzione prende l'id token dalla sessione utenti, se non ne è già stato creato uno, dopo di che genera un token casuale.

    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;
    }
    }
    
  3. 3
    Crea la funzione get_token() Function.
    Questa funzione ottiene il valore del token, se non è già stato creato, dopo di che ne genera uno.

    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;
    }
    
    }
    
  4. 4
    Crea la funzione check_valid() Function.
    Questa funzione è utilizzata per controllare se l'id token e il valore del token sono validi. Lo fa controllando i valori della richiesta GET o POST con i valori memorizzati nella variabile della sessione utenti.

    public function 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;
    }
    }
    
  5. 5
    Crea la funzione form_names() Function.
    Questa è la seconda difesa di cui si parla in questo articolo contro l’attacco CSRF. Questa funzione genera nomi casuali per i campi del modulo.

    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;
    }
    
  6. 6
    Crea la funzione random() Function.
    Questa funzione genera una stringa casuale utilizzando il file Random di Linux per aumentare l’entropia.

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


  7. 7
    Chiudi la parentesi della Class.
    Questo chiuderà la classe csrf.

    }
    
    Ora puoi chiudere il file csrf.class.php perché abbiamo finito di modificarlo.

3
Proteggere le Pagine con csrf.class.php

Questi passaggi ti mostreranno come utilizzare la classe CSRF per prevenire gli attacchi CSRF.

  1. 1
    Proteggi un modulo POST.
    Il codice riportato di seguito illustra come implementare la classe csrf su un modulo.

    <?php
    session_start();
    include 'csrf.class.php';
    $csrf = new csrf();
    // Genera Token Id e lo convalida
    $token_id = $csrf->get_token_id();
    $token_value = $csrf->get_token($token_id);
    // Genera nomi casuali per i moduli
    $form_names = $csrf-> form_names (array ('utente', 'password'), false);
    if(isset($_POST[$form_names['user']], $_POST[$form_names['password']])) {
    // Controlla se Token Id e Token Value sono validi.
    if($csrf->check_valid('post')) {
    	// Prende il modulo Variables.
    	$user = $_POST[$form_names['user']];
    	$password = $_POST[$form_names['password']];
    			// Il Modulo Function va qui
    }
    // Rigenera un nuovo valore casuale per il modulo.
    $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>
    

Informazioni sull'Articolo

wikiHow è una "wiki"; questo significa che molti dei nostri articoli sono il risultato della collaborazione di più autori. Per creare questo articolo, autori volontari hanno collaborato apportando nel tempo delle modifiche per migliorarlo.

Categorie: Programmazione | Internet

In altre lingue:

English: Prevent Cross Site Request Forgery (CSRF) Attacks in PHP, Español: evitar ataques CSRF (falsificación de petición en sitios cruzados) con PHP, Русский: защититься от атак с использованием межсайтовой подделки запроса (CSRF) в php, Português: Prevenir Ataques CSRF em PHP

Questa pagina è stata letta 3 693 volte.
Hai trovato utile questo articolo?