Tag: https

  • HTTPS e le applicazioni di terze parti: attenzione!

    “È sufficiente usare HTTPS per essere sicuri: protegge la comunicazione cifrando il traffico e usando certificati validati da CA riconosciute”.

    SBAGLIATO. Spesso si sente pronunciare questa frase, ma non è del tutto vero: ho recentemente letto con molta attenzione un paper presentato alla conferenza CCS 2012, una conferenza dedicata alla Computer Security. Il paper ha un titolo curioso: “The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software“.

    Si parla di HTTPS/SSL in contesti in cui è richiesta una comunicazione cifrata tra due sistemi (trasmissione di dati sensibili); distinguiamo due tecnologie lato end-user per accedere a sistemi HTTPS: un browser (accediamo, per esempio, ad un sito di e-commerce e facciamo il checkout in modalità protetta) oppure un’applicazione 3rd party (per esempio, lo stesso sito di e-commerce tramite un’app dedicata a smartphone/tablets).

    Bene: i browser non sono in discussione e non risentono dei problemi presentati nel paper. Invece, le libraries SSL (due nomi su tutti: OpenSSL e JSSE) che solitamente vengono utilizzate nei back-end o utilizzate dagli sviluppatori per costruire applicazioni che accedono a risorse tramite HTTPS soffrono di alcuni problemi che rendono l’intera comunicazione vulnerabile a diversi tipi di attacchi, come il famoso man-in-the-middle. In breve, il problema principale è il processo di validazione dei certificati SSL (solitamente: si risale la chain fino alla root CA). Se lato client non viene effettivamente fatta la validazione del certificato presentato dal server, il client è una facile preda! Questa non-validazione è causata da molteplici fattori:

    • pigrizia dei developers che, nell’utilizzare queste librerie, disabilitano controlli fondamentali durante la fase di sviluppo (perché si usano dei certificati self-signed) che poi dovrebbero essere riabilitati al go-live. Ma così non accade;
    • utilizzo sbagliato delle API che settano impostazioni non congruenti (setto il check per la verifica del certificato ma poi non ricordo/non so/non è specificato che devo leggere un’ulteriore return code per verificare se la validazione è andata a buon fine).

    Nel paper sono presenti alcuni esempi interessanti con tanto di codice reverse engineered.

    Quali sono i rimedi?

    • Come sviluppatori: configurare correttamente i parametri di validazione SSL della libreria che si usa, controllando anche i valori di ritorno della validazione se devono essere richiamati tramite un’ulteriore chiamata alle API della library utilizzata
    • Come sviluppatori: fare sempre un testing utilizzando certificati SSL non verificati.

    La lettura del paper è davvero molto interessante ed è vivamente consigliata per tutti quelli che hanno a che fare con lo sviluppo di applicazioni 3rd party che accedono a risorse esposte tramite HTTPS/SSL.

  • Python: scriviamo un HTTPS downloader simile a wget (con urllib2, optparse e getpass)

    Per ragioni di semplicità di utilizzo e immediatezza (e anche per imparare qualcosa di nuovo), la settimana scorsa ho dovuto scrivere un downloader da linea di comando simile a GNU wget, ma con alcuni requisiti personalizzati:

    • l’accesso alla pagina di download è protetto da userid e password (autenticazione HTTPDigestAuth);
    • il protocollo di accesso è HTTPS;
    • una volta ottenuto l’accesso, è necessario fare il GET di alcuni files ben particolari e crearli su hard disk.

    Per realizzare questo wget-like in Python, usiamo il modulo urllib2 che ci permette di accedere a risorse esterne tramite i protocolli più svariati. Per aprire una connessione HTTPS e autenticarci correttamente usiamo i seguenti statement:

        passman.add_password(None, url, username, password)
        authhandler = urllib2.HTTPDigestAuthHandler(passman)
        opener = urllib2.build_opener(authhandler)
    

    Affinché la gestione delle varie opzioni sia più semplice possibile, usiamo anche il modulo optparse (che permette di passare le opzioni al programma in modo simile alle utility GNU):

    parser = optparse.OptionParser()
    parser.add_option("-u", "–username")
    parser.add_option("-d", "–date")
    parser.add_option("-t", "–target", default="logs")
    options, arguments = parser.parse_args()
    

    Visto che dovremo gestire anche l’autenticazione tramite username e password, la scelta di passare la password come argomento del programma è una scelta non ottimale: una semplice ricerca nella history della shell utilizzata potrebbe permettere ad un attaccante di risalire alla password. Per questo ci viene incontro il pacchetto getpass che, in modo simile ai programmi UNIX che si rispettino, chiede interattivamente la password (senza stamparla, ovviamente!). Per richiedere l’inserimento della password all’utente è sufficiente:

    password = getpass.getpass()
    

    Torniamo ora all’inizio: abbiamo ottenuto dall’utente username (passato come argomento) e password (richiesta interattivamente): ora possiamo aprire una connessione verso l’hostname di riferimento e richiedere il download del file (salvando su file lo stream del file in ricezione tramite i metodi standard di Python):

    passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
    passman.add_password(None, url, options.username, password)
    authhandler = urllib2.HTTPDigestAuthHandler(passman)
    opener = urllib2.build_opener(authhandler)
    download = opener.open(file)
    logging.debug('downloading %s ...' % file)
    fo = open(options.target + os.sep + targetFileName, 'w')
    fo.write(download.read())
    fo.close()
    

    Abbiamo quindi ottenuto un semplice downloader di file scritto in Python, molto più semplice di wget ma al tempo stesso molto più customizzabile.

  • Twitter via HTTPS: da abilitare!

    Dopo aver fatto la segnalazione per quanto riguarda Facebook, segnalo che anche Twitter ha aggiunto un’opzione per usufruire del servizio via HTTPS: è sufficiente visualizzare i settings e poi selezionare l’opzione HTTPS. Ovviamente io consiglio di abilitare l’opzione per i “soliti” motivi di sicurezza e privacy.

  • Facebook e la navigazione HTTPS da abilitare

    Mi sono accorto che Facebook offre un’opzione molto utile e assolutamente da abilitare. Infatti, sotto Account > Impostazioni Account > Protezione dell’Account troviamo un’opzione per abilitare la navigazione HTTPS quando possibile.

     

    Io l’ho abilitata subito, per proteggermi da sniffer indiscreti durante la mia navigazione su Facebook, e consiglio di abilitarla anche a voi. Personalmente, ho sempre percepito la necessità di un’opzione del genere: il login in plain HTTP presente su Facebook mi ha sempre lasciato un po’ perplesso.

  • Ubuntu: Apache2 con certificati self-signed e senza password all’avvio

    Recentemente mi è capitato di dover installare apache [in particolare, apache2] su una macchina Ubuntu. In particolare, mi è stato chiesto di installare la versione con ssl, ovvero che implementa il protocollo cifrato https.

    Apache2+ssl richiede l’utilizzo di un certificato firmato da un’autorità [es. Thawte, Verisign, etc.]. Se non vogliamo pagare una CA per ottenere un certificato firmato, possiamo generare un certificato firmato da noi stessi. Tuttavia, seguendo molte delle guide che si trovano in rete, apache viene installato con l’opzione ssl ma ogni volta che viene avviato richiede la password per l’utilizzo del certificato.

    Per questo riporterò qui una guida passo-passo che fa in modo che Apache2 non richieda la password per l’utilizzo del certificato: questa procedura è consigliata solamente se l’utilizzo è volto al testing o allo sviluppo. Qualsiasi altro uso è sconsigliato [richiedere una password per l’utilizzo del certificato è più che normale].

    • Abilitate il modulo ssl per apache2: sudo a2enmod ssl
    • Generiamo il certificato: cd /tmp; sudo openssl req -new > new.cert.csr
    • Vi verranno chieste delle informazioni a scopo puramente informativo e che compariranno nel certificato. Riempite le varie informazioni come credete
    • Ed ora una serie di comandi per generare tutti i file richiesti dai certificati: sudo openssl rsa -in privkey.pem -out new.cert.key
      sudo openssl x509 -in new.cert.csr -out new.cert.cert -req -signkey new.cert.key -days 1825
      sudo cp new.cert.cert /etc/ssl/certs/server.crt
      sudo cp new.cert.key /etc/ssl/private/server.key
    • Ora abilitiamo l’utilizzo dei certificati appena generati:sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/ssl
    • Modificate il file /etc/apache2/sites-available/default con il vostro editor preferito, ad esempio vi: sudo vi /etc/apache2/sites-available/default e cambiate le seguenti linee:
      Cambiare da…A…
      NameVirtualHost: *NameVirtualHost: *:80
      <VirtualHost *><VirtualHost *:80>
    • Modificate ora il file /etc/apache2/sites-available/ssl sempre con il vostro editor preferito e cambiate le seguenti linee:
      Cambiare da…A…
      NameVirtualHost: *NameVirtualHost: *:443
      <VirtualHost *><VirtualHost *>

      Dopo la linea che contiene DocumentRoot, aggiungete le seguenti righe:

      SSLEngine on
      SSLOptions +StrictRequire
      SSLCertificateFile /etc/ssl/certs/server.crt
      SSLCertificateKeyFile /etc/ssl/private/server.key
      
    • Ora date il seguente comando per abilitare l’utilizzo dei certificati in apache2: sudo a2ensite ssl
    • Infine riavviate Apache2 e finalmente non chiederà più la password del certificato: sudo /etc/init.d/apache2 restart

    Nota: se avete problemi controllate che il vostro file /etc/hosts sia fatto in questo modo:

    127.0.0.1 localhost localhost.localdomain {il vostro hostname}
    127.0.1.1 {il vostro hostname}
    {IP statico se ne avete uno} {DNS fully qualified se ne avete uno}