Elucubrato da saibal
Addì 22 marzo 2013
Rivisitazione della tecnica “honeypot” per moduli antispam senza captcha – UPDATE
Esempio n° 1
È la soluzione base. Volutamente, per semplicità d’uso, non utilizza cookie, sessioni o database per salvare o rendere random alcuni dati. Su siti non troppo “in vista” dovrebbe fornire una discreta protezione purchè si inserisca almeno un controllo antiflooding.
Vediamo il codice da inserire in testa alla pagina del modulo per creare un paio di variabili che ci serviranno (vedremo perchè e come):
1 2 3 4 5 6
<?php /* * Filename: antispam-form1.php */ $time = time(); ?>
Utilizziamo qualche linea di javascript (jQuery richiesto) nell’head della pagina:
1 2 3 4 5 6 7 8 9
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript"> <!-- $(document).ready(function() { $('#myinput').attr("autocomplete","off"); }); //--> </script>
il form, invece, è così costruito:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
<form id="form_<?php echo $time; ?>" action="result1.php" method="post"> <input type="hidden" name="formtime" value="<?php echo $time; ?>" /> <fieldset> <legend>Guestbook Form:</legend> <div class="class_<?php echo $time; ?>"> <label for="subject">Subject:</label> <input id="subject" name="subject" type="text" size="30" /> </div> <div class="class_<?php echo $time; ?>"> <label for="email">Email:</label> <input id="email" name="email" type="text" size="30" /> </div> <div class="class_<?php echo $time; ?> special-container"> <p>attenzione! lasciare vuoto questo campo</p> <input id="myinput" name="name" type="text" /> <p>attenzione! lasciare vuoto questo campo</p> </div> <div class="class_<?php echo $time; ?>"> <label for="message">Message:</label> <textarea id="message" name="message" rows="10" cols="15"></textarea> </div> <input type="submit" value="Invia" /> </fieldset> </form>
Vediamo nel dettaglio la struttura della pagina.
Con “time()” otteniamo la data di caricamento del modulo (in secondi). Il valore di $time è quindi utilizzato per rendere univoco, ad ogni caricamento, l’id del form e le classi dei vari elementi. Abbiamo introdotto il prefisso “form_” e “class_” perchè, secondo le specifiche w3c, un id o una classe non possono iniziare con un numero. Infine, se non realmente necessario, eliminiamo l’attributo name.
Creare un oggetto univoco ad ogni richiesta rende più difficile ad un bot indentificare gli elementi. È solo il primo passo per creare qualche ostacolo.
1
<input type="hidden" name="formtime" value="<?php echo $time; ?>" />
Nel campo nascosto “formtime” salviamo la data di caricamento della pagina. Ci servirà per il controllo antiflooding.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<div class="class_<?php echo $time; ?>"> <label for="subject">Subject:</label> <input id="subject" name="subject" type="text" size="30" /> </div> <div class="class_<?php echo $time; ?>"> <label for="email">Email:</label> <input id="email" name="email" type="text" size="30" /> </div> <div class="class_<?php echo $time; ?>"> <label for="message">Message:</label> <textarea id="message" name="message" rows="10" cols="15"></textarea> </div>
Strutturate il modulo secondo le vostre esigenze (ho usato campi in inglese solo a scopo dimostrativo). Volutamente sono stati inseriti degli elementi contenitori (div) con classe “class_<?php echo $time; ?>”. L’obiettivo è rendere abbastanza simile l’intera struttura del form con quella del campo “honeypot”.
1 2 3 4 5
<div class="class_<?php echo $time; ?> special-container"> <p>attenzione! lasciare vuoto questo campo</p> <input id="myinput" name="name" type="text" /> <p>attenzione! lasciare vuoto questo campo</p> </div>
La trappola vera e propria, il campo invisibile in grado di attirare il bot. Notiamo subito che l’elemento è contenuto in un div nascosto attraverso fogli di stile; la classe “special-container” non è altro che:
1
.special-container { display: none; }
Questi accorgimenti dovrebbero rendere più difficile al software capire quali campi siano nascosti e quali no. In più, per complicare ulteriormente le cose, la classe css fondamentale dovrebbe essere inserita in un file esterno in modo che non sia deducibile da una semplice analisi del codice sorgente.
Sebbene l’elemento invisibile si chiami “name” ho notato, dai log ottenuti su siti di prova, che il nome del campo è assolutamente indifferente; “name” non è tanto meglio di “pippo” o di “pluto”. Ciò che invece fa differenza è il tipo di input: da preferirne assolutamente uno di tipo “text” o una “textarea“.
Il messaggio di avviso per gli utenti umani è utile nei rari casi in cui l’utente abbia i css disabilitati (nel 2012?) o, più verosimilmente, siano saltati i fogli di stile per un qualsiasi errore tecnico.
In testa alla pagina abbiamo utilizzato jQuery per disabilitare l’autocomplete sul campo “honeypot”.
1
$('#myinput').attr("autocomplete","off");
Questa caratterista è necessaria perchè bisogna tener conto di quei browser che hanno attiva la funzionalità di autofill. In alcuni casi, infatti, potrebbe essere riempito il campo invisibile in buona fede e senza che l’utente se ne sia reso conto. È stato utilizzato javascript per due motivi:
- “autocomplete=off” è un attributo valido solo per html5 (non esiste in xhtml)
- ancora una volta: utilizzare javascript rende più difficile la vita al bot che dovrebbero avere attivo un parser per capire di che campo si tratti
bell’articolo! complimenti!!!
l’ho provato e funziona bene come tecnica