Case study: automatizzare le richieste POST e GET per falsare il risultato di un sondaggio via web

“I sondaggi riflettono un’opinione creata dai media”
Pascal Bruckner

Mi perdoneranno gli amici del Corriere di Siena se prendo ad esempio, per questo case study, il loro sondaggio sul voto che i cittadini danno all’Amministrazione Comunale Senese per il 2016. Tuttavia, in questo freddo, piovoso e noioso pomeriggio di inizio gennaio, ho deciso di divertirmi a guardare come avevano, tecnicamente parlando, realizzato il sondaggio in oggetto. Ed è stato sufficiente un browser Chromium (versione libera del celeberrimo Google Chrome) e poche righe di codice in Python per scoprire come falsarne i risultati.

Niente di illegale, sia chiaro, poiché è stato sufficiente replicare la medesima chiamata -legittima- che il browser di ogni utente compie quando esprime il suo voto: basta guardare, con il Page Inspect, quali sono i parametri e replicare il tutto quante volte lo si desidera.

Ogni analisi inizia seguendo la procedura e guardando cosa avviene “dietro la facciata”. In questo caso non troviamo il tradizionale form (<form.. >) ma dei “pulsanti” che richiamano una azione asincrona (ajax) in caso di click su di essi (evento onClick). La funzione javascript effettua una chiamata all’URL http://corrieredisiena.corr.it/widget/sondaggio/risposte.jsp con due parametri GET, idsondaggio e idvoto, contenenti rispettivamente l’identificativo univoco del sondaggio e della selezione da parte dell’utente. In questo caso, l’ID del sondaggio è 241457 mentre l’ID del voto cambia da 8302 per il “3” al 8297 per l’ “8”.

Pertanto, per registrare un voto “3” sarà chiamato l’URL http://corrieredisiena.corr.it/widget/sondaggio/risposte.jsp?idsondaggio=241457&idvoto=8302 mentre per il voto “8” l’URL sarà http://corrieredisiena.corr.it/widget/sondaggio/risposte.jsp?idsondaggio=241457&idvoto=8297. Tuttavia, per evitare votazioni multiple da parte di un utente, lo script invia un cookie al browser con nome “sondaggioco-[id sondaggio]=voted” e scadenza dopo 30 giorni: se un utente tenta di votare nuovamente con il medesimo browser, il sistema verifica se il cookie esiste e, in caso affermativo, impedisce un nuovo voto (la verifica, pertanto, avviene dal lato client). Protezione che potrà essere adeguata per gli utenti normali ma certo non per chi ha qualche conoscenza in più: anche senza essere maghi del web, basta cancellare i cookie (o avviare una sessione di “Navigazione anonima”) per votare quante volte si desidera.

In ogni sondaggio, ovviamente, vince l’opzione che ottiene più voti. Pertanto, se voglio far vincere una certa opzione, o passo la serata a votare e cancellare cookie o automatizzo grazie ai tanti sistemi già ampiamente disponibili. In questo esempio, di sole 3 righe, ho scelto di usare il linguaggio Python e la libreria urllib, già presente nella distribuzione di default:

#!/bin/env python

import urllib
params = urllib.urlencode({'idsondaggio': 241457, 'idvoto': [xxxx]})
f = urllib.urlopen("http://corrieredisiena.corr.it/widget/sondaggio/risposte.jsp?%s" % params)
print f.read()

Il vantaggio del Python è, come dice il suo motto, “batteries included”: contiene al suo interno un gran numero di librerie pronte all’uso per soddisfare le nostre esigenze. La libreria urllib (e la successiva urllib2 per Python 3) può emulare le richieste http di un qualsiasi browser. Nella riga dell’esempio sopra, la funzione urlopen della libreria urllib fa proprio questo: è un browser che visita la pagina indicata come primo argomento.

Le righe di codice Python sopra indicate “emulano” una votazione. Non essendoci, inoltre, alcun controllo sui cookie, viene agevolmente bypassato il semplice controllo per evitare votazioni multiple: ogni chiamata a questo codice è un voto perfettamente valido sul sistema. Tuttavia quello descritto non è un sistema infallibile: gli amministratori del sito possono verificare facilmente votazioni multiple con un controllo dell’IP da cui provengono le richieste HTTP, ed annullarle. Anche per questo, tuttavia, c’è una soluzione abbastanza facile: usare proxy per le richieste, così da mascherare il reale IP da cui provengono e simulando votazioni da location multiple.

Le righe di codice sopra descritte possono essere così migliorate per usare proxy multipli:

import urllib 

web_proxies = ['http://proxy1.example.com:1234',
               'http://proxy2.example.com:1234',
               'http://proxy3.example.com:1234']

params = urllib.urlencode({'idsondaggio': 241457, 'idvoto': [xxxx]})

for proxy in web_proxies:
    print "Trying HTTP proxy %s" % proxy
    try:
        f = urllib.urlopen("http://corrieredisiena.corr.it/widget/sondaggio/risposte.jsp?%s" % params, proxies={'http': proxy})
        print f.read()
    except:
        print "Failed. Trying next proxy in 5 seconds"
        time.sleep(5)
dove trovo proxy da utilizzare ? Sul web ci sono liste aggiornate in tempo reale su proxy anonimi da utilizzare. Provate a cercarle…

Possibili soluzioni ? Beh, potrebbe essere introdotto un sistema di autenticazione sociale, dove si chiede all’utente di autenticarsi via Facebook (o Google o Twitter o altro sistema OAuth) prima di poter esprimere il proprio voto. Oppure una verifica via SMS o e-mail, tanto per citare due sistemi abbastanza usati e diffusi. Anche il semplice uso di un captcha può bloccare sistemi di votazione automatica, senza aggravare l’utente dell’onere di autenticarsi o verificare il proprio cellulare.

Sia chiaro che questo articolo ha solamente uno scopo divulgativo, cercando di evidenziare come un semplice “gioco” come un sondaggio via web possa essere influenzato senza particolari conoscenze o capacità. E’ un esempio banale di come il tema della sicurezza informatica, nel nostro Paese sempre sottovalutato, sia in realtà molto importante: falle di questo tipo sono trascurabili per un sondaggio web su un quotidiano locale ma prioritarie su sistemi informativi governativi o su piattaforme ben più cruciali. Giusto per informazione, il blog di Anonymous Italia contiene una lunga lista di esempi sul tema.

Per finire, spero di esservi stato di aiuto nel comprendere ancora di più come funziona il web “dietro” lo schermo e rimango, come al solito, a disposizione per eventuali domande o informazioni.

 

 

Michele Pinassi

Nato a Siena nel 1978, dopo aver conseguito il diploma in "Elettronica e Telecomunicazioni" e la laurea in "Storia, Tradizione e Innovazione", attualmente è Responsabile del Sistema telefonico di Ateneo presso l'Università degli Studi di Siena ed esperto di sicurezza informatica nello staff del DPO. Utilizza quasi esclusivamente software libero.

Potrebbero interessarti anche...

Rispondi

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.

%d blogger hanno fatto clic su Mi Piace per questo: