CAPITOLO 5 – PROGETTO PROTOTIPO
5.3 SICUREZZA DEGLI ACCESSI
5.3.4 Procedura di autenticazione
Il processo di autenticazione passa attraverso una serie di chiamate alle tabelle illustrate nel paragrafo precedente. La prima parte del processo prevede, previa verifica della presenza dell’utente associato al Codice Fiscale inserito, la generazione della password e l’invio della stessa al numero telefonico prelevato dalla tabella utente tramite l’esecuzione di una query di selezione. A tale scopo, l’oggetto CallableStatement permette di effettuare interrogazioni alla base dati in linguaggio SQL, attraverso la connessione creata secondo le modalità esposte. I dati restituiti saranno recuperati dall’oggetto java.sql.ResultSet. Il ResultSet quindi raccoglie i dati richiesti all’interno dello Statement e li inserisce in una struttura dati opportuna, mentre Il metodo getString(“NomeColonna”) restituisce il valore correntemente puntato dal cursore next() della colonna specificata come parametro.
CallableStatement cstmt = connection.prepareCall(“Query per la selezione del paziente”); cstmt.setString(1, username);
ResultSet rs = cstmt.executeQuery(); rs.next();
NumTel = rs.getString("TELEFONO");
Se il ResultSet è vuoto significa che il Codice Fiscale inserito non è associato a nessun utente presente nella struttura. In caso contrario si procede con la generazione di un numero pseudocasuale tramite algoritmo PRNG, che andrà a costituire la chiave segreta dell’algoritmo OTP.
SecureRandom secureRandomGenerator = SecureRandom.getInstance("SHA1PRNG"); String seed = Long.toString(Math.abs(secureRandomGenerator.nextLong())); OTP = SHA_Hashing(generateTOTP(seed, steps, "8","HmacSHA512"));
Il codice JDBC è in grado di invocare la Stored-Procedure per l’operazione di UPDATE/INSERT, utilizzando l’oggetto di tipo CallableStatement.
cstmt = connection.prepareCall("{call UPSERT_OTP(?,?,?,?)}"); cstmt.setString(1, username); cstmt.setString(2, OTP); cstmt.setString(3, utcTime); cstmt.setString(4, TimeOFF); cstmt.executeUpdate();
I parametri passati in ingresso alla procedura sono il Codice Fiscale dell’utente (che rappresenta la chiave primaria della tabella OTP), la OTP codificata con algoritmo Hash, il timestamp corrente e la data/ora di scadenza della password. Arrivati a questo punto, la password generata viene inviata all’utente tramite SMS. Senza scendere troppo nel dettaglio, ciò avviene sfruttando un servizio precedentemente implementato dalla Fondazione; per usufruirne e sufficiente inserire un record nella tabella SMS di uno schema accessibile in remoto.
String Messaggio = "Servizio autenticazione FTGM@home. La tua password di accesso monouso è "+OTPchiaro+" e scadrà "+TimeOFF;
CallableStatement cstmt = connection.prepareCall(“Procedura di insert nella tabella SMS”); cstmt.setObject(1, NumTel);
cstmt.setString(2, Messaggio);
Una procedura analizza la tabella con intervalli di 5 minuti e provvede ad inviare i messaggi, al numero indicato nel campo TELEFONO, per i record che presentano il campo flag impostato a false (che viene commutato a true non appena il messaggio è stata spedito con esito positivo). Per verificare che il numero presente nel sistema sia di un cellulare e non di un telefono fisso vengono controllati, dopo aver eliminato eventuali caratteri e spazi superflui, sia la lunghezza che il primo carattere che lo costituisce.
//Elimino spazi e punteggiatura
NumTel = NumTel.replaceAll("[ \\p{Punct}]", ""); //Controllo il prefisso
String FirstChar = Character.toString(NumTel.charAt(0)); if(!FirstChar.matches("3")){
return “Numero non adatto”; }
//Continua con la procedura . . .
Infatti, sulla base della Delibera no. 9/03/CIR del 3 luglio 2003 (Piano di numerazione nel settore delle telecomunicazioni e disciplina attuativa), in Italia è possibile distinguere i numeri telefonici sulla base dei loro prefissi facendo riferimento alla seguente casistica:
iniziale "0-": numeri fissi per l'Italia (compresi San Marino e Città del Vaticano);
SOLUZIONE ALTERNATIVA PER L’INVIO DI NOTIFICHE ALL’UTENTE
Durante l’analisi della letteratura, alla ricerca di sistemi per l’invio di notifiche all’utente, una soluzione molto interessante è stata quella offerta dal servizio mOTP. Si tratta di una Open API che si presenta come un’alternativa alle One Time Password basate sull’invio di SMS. Creata dagli sviluppatori Telco, mOTP rappresenta una soluzione sicura e scalabile per la verifica telefonica dell’utente, ed offre un approccio diverso rimpiazzando il servizio SMS con una OTP fornita all’utente tramite ID di una chiamata persa utilizzando la tecnica del Caller ID Spoofing; in questo modo si riesce ad implementare un’autenticazione a due fattori abbattendo i costi del servizio ed eliminando eventuali ritardi ed ostacoli. mOTP è un progetto aperto, fondato da un gruppo di imprenditori ed esperti che esercitano da anni nell’industria delle telecomunicazioni. Attualmente il servizio è attivo in più di 200 paesi nel mondo, ed il funzionamento si compone dei seguenti step:
1. L’utente da autenticare inserisce il suo numero di telefono;
2. L’OTP viene consegnato all'utente tramite ID di una chiamata persa; 3. L'utente immette le informazioni ricevute;
4. Sulla base della corrispondenza tra le informazioni presenti nel sistema e quelle inserite dall'utente, l'accesso è consentito o meno.
L'approccio MOTP ha vantaggi significativi, come elencato di seguito:
Basso Costo: la OTP viene recapitata all’utente tramite una semplice chiamata persa, quindi viene eliminato il costo degli SMS;
Sicurezza: la OTP viene consegnato direttamente al dispositivo dell'utente;
Velocità ed Affidabilità: qualsiasi operatore telefonico nel mondo dà priorità alle chiamate rispetto che agli SMS. Quindi mOTP ha più probabilità di essere consegnato al destinatario più velocemente e con maggiori garanzie di successo rispetto ad un'implementazione che fa uso degli SMS.
Questa implementazione presenta delle buone potenzialità, tuttavia nel nostro caso non poteva essere utilizzata dato che è richiesto l’appoggio ad un servizio esterno, e ciò può rappresentare un problema in termini di sicurezza dei dati trasmessi.
Con queste considerazioni si conclude anche la parte di generazione ed invio della password. Nella seconda parte del processo di autenticazione invece, il metodo implementato richiede l’inserimento da parte dell’utente della OTP ricevuta tramite SMS. I dati inseriti saranno confrontati con quelli presenti nella tabella delle OTP e, a seconda dell’esito della ricerca, l’accesso dell’utente verrà autorizzato o meno. Se nella tabella delle OTP non è presente alcun record associato al paziente, la procedura non può andare avanti dato che significa aver by-passato la prima parte del processo e che quindi non è stata generata alcuna password e non è presente nessuna richiesta di accesso al servizio da parte di quell’utente.
CallableStatement cstmt = connection.prepareCall(“Query selezione password associata all’utente”); cstmt.setString(1, username); ResultSet rs = cstmt.executeQuery(); OTP = rs.getString("OTP"); DataONstr = rs.getString("DATA_ATTIVAZIONE"); DataOFFstr = rs.getString("DATA_SCADENZA");
Le condizioni che regolano l’autenticazione consistono per prima cosa in un confronto tra due stringhe, che rappresentano rispettivamente l’Hash generato e quello contenuto nel server. Se il confronto è corretto viene verificato anche che la password inserita non abbia superato il suo tempo di validità.
if(SHA_Hashing(OTPSMS).equals(OTP)){
if(DataIN.compareTo(DataON) > 0 && DataIN.compareTo(DataOFF) < 0){ …LOGIN effettuato con SUCCESSO…
} else {
…LOGIN FALLITO, Password scaduta…
}
} else {
…LOGIN FALLITO, Password errata… }
Se l’autenticazione va a buon fine, viene eliminato il record corrispondente a quella richiesta di accesso, rendendo così impossibile riutilizzare nuovamente la stessa password.
st.executeUpdate("DELETE FROM PASSWORD WHERE COD_PAZIENTE = '"+ username +"'");