Domenica, 17 Febbraio 2019 18:52

Captcha e Immagini generate da PHP

Scritto da

Uno degli aspetti di sicurezza di cui non ci rendiamo conto, è che con linguaggi come Python e simili è molto facile automatizzare delle operazioni con cicli infiniti sui siti web, come riempire delle form di registrazione in automatico per creare utenti fasulli, cliccar in automatico su pubblicità per trarre profitti, piuttosto che provare degli accessi su login con attacchi a forza bruta. Ecco perché in giro per il web ci imbattiamo spesso nei captcha, piccoli indovinelli da risolvere per dimostrare all'applicativo web che stiamo usando che siamo umani.

Come funziona

Soluzione 0
Prendo una immagine con il testo e la immergo come tutte le altre all'interno di una pagina HTML. con il classico tag img. Posso metterne più di una? No, l'html non contiene elementi dinamici di programmazione. Quindi è un fallimento: al secondo tentativo posso forzare il captcha.
 
Soluzione 1
Uso Javascript o JQuery per randomizzare l'immagine. Ottimo, ci danno una chance in più, ma sono linguaggi lato client. Un attaccante può sempre scoprire come funzionano semplicemente scaricando il codice e con la console del browser ingannare la pagina in men che non si dica. Occorre agire lato server, dove l'attaccante non può vedere il codice sorgente ma solo subirne il risultato sotto forma di pagina html. Il JavaScript è utile per fare alcuni controlli lato client, fare un po' di grafica, ma la sicurezza, lo abbiamo visto con le sql injection, la possiamo gestire solo lato server.
 
Soluzione 2
L'idea è quella di avere centinaia di immagini salvate sul disco del server web. Ogni immagine contiene un testo alfanumerico. Se ne prende una a caso, si da in pasto al browser del client e se ne chiede la validazione dall'utente riempendo un form che preleviamo e controlliamo col PHP. Un po' farraginoso ma fattibile. Inconveniente? Dover aver salvate sul server centinaia di immagini con spreco di spazio e dover gestire comunque una tabella sul db o un vettore nel codice che associa al titolo dell'immagine un relativo codice da verificare. Non possiamo usare il nome direttamente, l'utente ci aggirerebbe in un lampo! E allora perché non le facciamo generare al php lato server l'immagine che ci serve? Magari generando una sequenza di caratteri prima, creando l'immagine con tali caratteri e spedirla quindi al client. Poche cose da fare ma tanta robustezza e praticamente un quantitativo di captcha infinito a costo di spazio ed elaborazione zero. Vediamo come si fa!   Assicuriamoci che però sul server dove testiamo il codice siano installate le librerie grafiche GD. Se state testando tutto su linux, per installarle basta il comando:

 sudo apt-get install php7.3-gd

 o 

 sudo apt-get install php-gd

che vi suggerirà il pacchetto corretto in base alla vostra versione di PHP. Se state usando un ambiente simulato tipo XAMP o WAMP, scaricate il file DLL php_gd2.dll da https://libgd.github.io/ ed inseritelo nella cartella estensioni per poi aggiungere o scommentare la riga nel file php.ini

extension=php_gd2.dll

Il primo script è molto semplice ma contiene una anomalia a cui non siamo abituati. Creiamo una pagina html con il seguente codice. Io la chiamo banalmente captcha.html

<!DOCTYPE html>
<html lang="it">
<head>
	<title>Un esempio di CAPTCHA</title>
</head>
<body>
<h1>Immagini generate da PHP</h1>
<p>Rispondi al captcha inserendo la scritta nel campo</p>
<img src="/captcha.php" alt="risolvi il captcha" />
<form name="captchaform" action="validatecaptcha.php" method="post">
<input type="text" name="captcha" id="captcha">
<input type="submit" value="Invia">
</form>
</body>
</html>

La anomalia che dicevamo è subito evidente: dove dovrebbe comparire l'indirizzo e il nome del file dell'immagine abbiamo adesso il link ad uno script php! Possiamo però intuire che questo script abbia la funzione di creare l'immagine e restituirla al rispettivo tag img che lo graficherà.

Vediamo allora cosa c'è nel nostro script captcha.php.

<?php
//creiamo un riquadro per la nostra immagine
 $immagine = imagecreatetruecolor(110, 50);

//scelgo un colore per il testo con i tre valori r g b (violetto qui)
$coloretesto = imagecolorallocate($immagine, 233, 14, 91);

//scrivo un numero casuale
$numerorandom = rand();
//salviamoci in una sessione il numero scelto così da poterlo verificare dopo
session_start();
$_SESSION['numerorandom'] = $numerorandom;
//echo $_SESSION['numerorandom'];

//8 è il font, gli altri due parametri sono la x e la y da cui parte il disegno
imagestring($immagine, 8, 7, 5,  $numerorandom, $coloretesto);

//restituisco la tipologia immagine come risorsa
 header("Content-Type: image/png");
 imagepng($immagine);


?>

 Se lo script vi da errore, probabilmente sul vostro server Apache/Wampp non è installata la libreria php_gd.dll o analago in linux come spiegato ad inizio articolo. Conviene contattare il sistemista del server o provvedere da voi sulla vostra piattaforma nel file php.ini

Ci manca da vedere il file che controlla il valore immesso dall'utente e quello che abbiamo salvato in sessione. Un semplice esercizio di stile direi. Saltiamo deliberatamente un po' di controlli per semplificare lo script validatecaptcha.php

<?php
session_start();

if (isset($_SESSION["numerorandom"]))
{
  if ($_SESSION["numerorandom"] == $_POST['captcha'])
    echo "OK, captcha valido";
  else
    echo "Captcha non valido! Torna indietro e ritenta";
}
else
  echo "qualcosa è andato storto, contatta il webmaster"
  
?>

 Se tutto va bene, abbiamo il nostro test captcha. Ovviamente è tutto migliorabile, ma per cominciare un semplice test è più che sufficiente. Considera che sistemi di captcha ormai sono ampiamente studiati e resi complessi per ogni necessità. Si possono trovare online diverse varianti al nostro esempio puramente didattico.

 

Letto 331 volte
Prof. Alfredo Centinaro

Docente di "Scienze e tecnologie informatiche", "Tecnologie e progettazione di sistemi informatici", "Sistemi e Reti" presso IIS Alessandrini-Marino (Teramo), consulente e sviluppatore web. Ha collaborato per anni come sviluppatore presso MHT - Treviso, assistente Sistemi ed elaborazione dell'informazione in UniTE Corso di laurea in Scienze del turismo culturale, tutor presso Telecom Italia Learning Services (L'Aquila)

Joomla SEF URLs by Artio