Alcuni mesi fa, cercando l’orario di un ufficio nel mio comune, ho notato che (quasi tutti) i siti comunali seguono un pattern comune, ossia:
www.nomedelcomune.provincia.it
eccetto per i capoluoghi di provincia e altri siti che vogliono fare gli alternativi e hanno domini completamente differenti. Mi è cosi venuto in mente che avrei potuto scansionare con nmap tutti i siti dei comuni d’italia, analizzare statisticamente i dati con R e pubblicarne i risultati.
Disclaimer: La scansione da me effettuata non ha interagito con nessun dominio e non ha provocato nessun disagio. Sebbene avessi potuto aumentarne l’intensità e cercare vulnerabilità o testarne le debolezze, ho preferito rimanere “leggero”.
La lista dei domini non è ovviamente disponibile in formato testo, divisa per regione e/o provincia. Per averla ho quindi scaricato la lista dei comuni dal sito Istat e creato uno script che ottenesse il nome di ogni sito senza doverlo fare a mano.
I comuni d’Italia sono, ad oggi, 7983, quelli che ho ottenuto sono invece 7161, visto che durante la scansione alcuni non erano raggiungibili o erano offline.
Dopo aver ottenuto la lista completa, ho eseguito il noto programma nmap per ottenere i dati che volevo. Il comando utilizzato è:
nmap -sV -p 80,443 -O --script ssl-heartbleed --script http-enum --script-args 'http-enum.category="cms"' --script banner -iL Regione -oX Regione.xml
dove:
Finita la scansione, ho ottenuto così un file .xml, da cui ho potuto estrarre i dati che mi interessavano.
Con una ricerca in Internet non ho trovato parser che facessero al caso mio, per cui ho optato per la creazione di un parser che mi permettesse di ottenere specifiche informazioni dal file ottenuto con nmap, oltre a rivelarne di altre. Ho deciso di scrivere il parser in Java per due motivi principali:
Il programma riceve in input un file .xml e stampa i seguenti dati:
Il file ottenuto è stato caricato su R eseguendo su di esso una serie di comandi, inseriti nello spoiler per chi volesse capire meglio i grafici
args<-commandArgs(TRUE)
Regione<-read.delim(args[1],sep=",",na.string=c("",NA))
cat(file=paste(args[1],".txt"),"Numero di siti: ", nrow(Regione),sep="\n")
cat("Su ",sum(table(Regione$Ip)),"host ci sono ",length(unique(Regione$Ip))," indirizzi IP unici e il massimo possiede ",max(table(Regione$Ip))," siti \n",file=paste(args[1],"output"), append=TRUE)
png(paste(args[1],"1Hosting.png"), units="in", width=11, height=8.5, res=300)
op <- par(mar = c(0,17,4,2) + 0.1)
barplot(sort(prop.table(table(Regione$Hosting))*100),horiz=TRUE,las=1,space=1,col=rainbow(length(table(Regione$Hosting))),names=paste(names(sort(prop.table(table(Regione$Hosting))*100)),"-",signif(sort(prop.table(table(Regione$Hosting))*100),2),"%"),main=paste("Hosting utilizzato su",sum(table(Regione$Hosting)),"host"),axes=FALSE)
percentlabelsSIS pielabelsSIS png(paste(args[1],"2SistemiOP.png"), width=700, height=700, res=75)
pie(prop.table(table(Regione$Sistema)),main=paste("Sistemi operativi su",sum(table(Regione$Sistema)),"host"),col=rainbow(length(table(Regione$Sistema))),labels=pielabelsSIS)
legend("topright",legend=levels(Regione$Sistema),cex=0.8,fill=rainbow(length(table(Regione$Sistema))))
png(paste(args[1],"3VersioniWindows.png"),width=700, height=500, res=75)
barplot(table(Regione[Regione$Sistema=="windows","Anno"]),col=rainbow(length(table(Regione$Anno))),main=paste("Versioni di Windows su",sum(table(Regione[Regione$Sistema=="windows","Anno"])),"host"),ylab="Numero di host",xlab="Anno")
png(paste(args[1],"4VersioniLinux.png"), width=700, height=500, res=75)
barplot(table(droplevels(sort(Regione[Regione$Sistema=="linux","Versione"]))),main=paste("Versioni di linux su",sum(table(droplevels(Regione[Regione$Sistema=="linux","Versione"]))),"host"),col=rainbow(length(table(Regione$Versione))),xlab="Versione",ylab="Numero di host")
percentlabelsCMS pielabelsCMS png(paste(args[1],"5CMS.png"),width=700, height=700, res=75)
pie(prop.table(table(Regione$Cms)),main=paste("Tipi di Cms di",sum(table(Regione$Cms)),"host"),col=rainbow(length(table(Regione$Cms))),labels=pielabelsCMS)
legend("topright",legend=levels(Regione$Cms),cex=0.8,fill=rainbow(length(table(Regione$Cms))))
percentlabelsSER80 pielabelsSER80 png(paste(args[1],"6TipidiServer80.png"), width=700, height=700, res=75)
pie(prop.table(table(Regione$Server80)),main=paste("Tipologie di Server [porta 80] su",sum(table(Regione$Server80)),"host"),col=rainbow(length(table(Regione$Server80))),labels=pielabelsSER80)
legend("topright",legend=levels(Regione$Server80),cex=0.8,fill=rainbow(length(table(Regione$Server80))))
png(paste(args[1],"7MaxServer80Versioni.png"),width=700, height=500, res=75)
barplot(table(droplevels(Regione[Regione$Server80==Regione[sum(table(Regione$Server80)),"Server80"],"Versione80"])),main=paste("Versioni di",Regione[sum(table(Regione$Server80)),"Server80"],"su",sum(table(droplevels(Regione[Regione$Server80==Regione[sum(table(Regione$Server80)),"Server80"],"Versione80"]))), "host") ,col=rainbow(length(table(Regione$Versione80))),xlab="Versione server",ylab="Numero di host")
percentlabelsSER443 pielabelsSER443 png(paste(args[1],"8TipidiServer443.png"), width=700, height=700, res=75)
pie(prop.table(table(Regione$Server443)),main=paste("Tipologie di Server [porta 443] su",sum(table(Regione$Server443)),"host"),col=rainbow(length(table(Regione$Server443))),labels=pielabelsSER443)
legend("topright",legend=levels(Regione$Server443),cex=0.8,fill=rainbow(length(table(Regione$Server443))))
percentlabelsSSL pielabelsSSL png(paste(args[1],"9SSL.png"), width=700, height=700, res=75)
pie(prop.table(table(Regione$SSL)),main=paste("Presenza di SSL su",sum(table(Regione$SSL)),"host"),col=rainbow(length(table(Regione$SSL))),labels=pielabelsSSL)
legend("topright",legend=levels(Regione$SSL),cex=0.8,fill=rainbow(length(table(Regione$SSL))))
percentlabelsHEA pielabelsHEA png(paste(args[1],"10Heartbleed.png"), width=700, height=500, res=75)
barplot(prop.table(table(Regione[Regione$SSL=="true","Heartbleed"]))*100,main=paste("Presenza vulnerabilità ad Heartbleed su",sum(table(Regione[Regione$SSL=="true","Heartbleed"])),"host"),col=rev(rainbow(length(table(Regione[Regione$SSL=="true","Heartbleed"])))))
legend("topright",legend=paste(pielabelsHEA," ",levels(Regione[Regione$SSL=="true","Heartbleed"])),cex=0.8,fill=rev(rainbow(length(table(Regione[Regione$SSL=="true","Heartbleed"])))))
Ecco i risultati ottenuti, prima per Regione, ed infine per tutta l’Italia.
Disclaimer2
Questa analisi non pretende di essere perfetta, anzi. Per quanto possa aver controllato e debuggato molte volte, qualche errore può sfuggire, specialmente con un software come nmap.
Sono dovuto giungere ad alcuni compromessi per ottenere questi dati:
Nel caso aveste idee per migliorare la scansione, sono disponibile, come sempre, attraverso la pagina Contatti.
Numero di comuni: 303
Numero di host analizzati: 274
Dettagli su indirizzi IP: Su 274 host ci sono 148 indirizzi IP unici. Uno di essi possiede 65 siti.
Numero di comuni: 74
Numero di host analizzati: 74
Dettagli su indirizzi IP: Su 74 host ci sono 27 indirizzi IP unici. Uno di essi possiede 15 siti
Numero di comuni: 131
Numero di host analizzati: 127
Dettagli su indirizzi IP: Su 127 host ci sono 3 indirizzi IP unici. Uno di essi possiede 33 siti
Numero di comuni: 409
Numero di host analizzati: 381
Dettagli su indirizzi IP: Su 381 host ci sono 70 indirizzi IP unici. Uno di essi possiede 289 siti
Numero di comuni: 550
Numero di host analizzati: 523
Dettagli su indirizzi IP: Su 523 host ci sono 232 indirizzi IP unici. Uno di essi possiede 124 siti
Numero di comuni: 335
Numero di host analizzati: 311
Dettagli su indirizzi IP: Su 311 host ci sono 133 indirizzi IP unici. Uno di essi possiede 35 siti
Numero di comuni: 216
Numero di host analizzati: 208
Dettagli su indirizzi IP: Su 208 host ci sono 26 indirizzi IP unici. Uno di essi possiede 160 siti
Numero di comuni: 378
Numero di host analizzati: 361
Dettagli su indirizzi IP: Su 361 host ci sono 212 indirizzi IP unici. Uno di essi possiede 39 siti
Numero di comuni: 235
Numero di host analizzati: 198
Dettagli su indirizzi IP: Su 198 host ci sono 116 indirizzi IP unici. Uno di essi possiede 35 siti
Numero di comuni: 1526
Numero di host analizzati: 1393
Dettagli su indirizzi IP: Su 1393 host ci sono 352 indirizzi IP unici. Uno di essi possiede 334 siti
Numero di comuni: 173
Numero di host analizzati: 172
Dettagli su indirizzi IP: Su172 host ci sono 66 indirizzi IP unici. Uno di essi possiede 73 siti
Numero di comuni: 136
Numero di host analizzati: 112
Dettagli su indirizzi IP: Su 112 host ci sono 41 indirizzi IP unici. Uno di essi possiede 63 siti
Numero di comuni: 1202
Numero di host analizzati: 903
Dettagli su indirizzi IP: Su 903 host ci sono 245 indirizzi IP unici. Uno di essi possiede 301 siti
Numero di comuni: 258
Numero di host analizzati: 251
Dettagli su indirizzi IP: Su 251 host ci sono 108 indirizzi IP unici. Uno di essi possiede 51 siti
Numero di comuni: 377
Numero di host analizzati: 364
Dettagli su indirizzi IP: Su 364 host ci sono 143 indirizzi IP unici. Uno di essi possiede 86 siti
Numero di comuni: 390
Numero di host analizzati: 371
Dettagli su indirizzi IP: Su 371 host ci sono 275 indirizzi IP unici. Uno di essi possiede 22 siti
Numero di comuni: 280
Numero di host analizzati: 280
Dettagli su indirizzi IP: Su 231 host ci sono 129 indirizzi IP unici. Uno di essi possiede 13 siti
Numero di comuni: 274
Numero di host analizzati: 273
Dettagli su indirizzi IP: Su 273 host ci sono 31 indirizzi IP unici. Uno di essi possiede 121 siti
Numero di comuni: 92
Numero di host analizzati: 74
Dettagli su indirizzi IP: Su 74 host ci sono 44 indirizzi IP unici. Uno di essi possiede 19 siti
Numero di comuni: 561
Numero di host analizzati: 560
Dettagli su indirizzi IP: Su 560 host ci sono 167 indirizzi IP unici. Uno di essi possiede 111 siti
Come ultima analisi, ho unito tutti i dati rilevati in un unico file, per avere un’immagine completa della situazione tecnologica dei siti dei comuni di tutta Italia.
Numero di comuni: 7983
Numero di host analizzati: 7161
Dettagli su indirizzi IP: Su 7161 host ci sono 2083 indirizzi IP unici. Uno di essi possiede 779 siti
I sistemi Windows rilevati sono stati in totale 1975. Da essi, ho ottenuto da 1781 host l’anno. In particolare:
In modo più preciso, le versioni di Linux sono:
In modo più preciso, abbiamo:
Su 7161 host, 4700 non possiedono certificato SSL.
Sugli host possedenti certificato SSL, 675 sono vulnerabili ad Heartbleed.
Sebbene l'Agid (Agenzia per l’Italia Digitale) mostri con fervore i numeri dell’avanzamento della crescita digitale in Italia, l’immagine che ne viene fuori con questa ricerca non è propriamente rosea.
Prima di giungere a conclusioni affrettate, vorrei fare un piccolo appunto:
Un’ottima iniziativa, segnalatomi da De Petra Giulio, è quella di ComunWeb, piattaforma che mira ad unire e gestire più comuni, rendendo più semplici le operazioni. Probabilmente sarebbe il modo migliore per gestire tutti i siti dei comuni d’Italia, cercando di centralizzare e mantenere più siti sotto un’unica gestione.
I dati negativi più rilevanti che ho notato sono:
Probabilmente l’anno prossimo eseguirò un’altra scansione, cercando di rilevare le differenze e osservare se la situazione sarà migliorata oppure no.