DNS dinamico fai-da-te senza servizi di terze parti

Rimpiazzare il proprio servizio di DNS dinamico con una coppia di script PHP e bash.

Esistono moltissimi servizi online anche gratuiti per il DNS dinamico quali DynDNS o NoIP. Questi servizi permettono l’associazione del propro indirizzo IP dinamico ad un nome DNS statico. Grazie ad essi è possibile raggiungere i servizi web installati dietro le proprie ADSL casalinghe (opportunamente nattate) senza dover ricordare e prendere nota dell’indirizzo IP pubblico che il provider di volta in volta ci fornisce.

Avevo un account su DynDNS per gestire da remoto il mio disco di backup ReadyNAS ma purtroppo dopo molto tempo il servizio è stato revocato e messo a pagamento. A tal punto, avendo già un dominio web PHP+MySQL (questo blog per l’appunto) ho deciso di implementarvi sopra un semplice servizio di traduzione IP in modo da raggiungere di nuovo il disco di backup.

Si è trattato semplicemente di realizzare una pagina web PHP che fornisce un redirect automatico (redirect HTML) al proprio indirizzo IP pubblico. L’indirizzo IP pubblico è memorizzato online in un file di testo ip.txt. E’ chiaro che tale indirizzo cambia con regolarità (al termine del lease-time impostato dal provider o ad ogni riavvio del modem ADSL) e quindi deve esistere un meccanismo per aggiornare tale file con il nuovo indirizzo. Un piccolo script bash che gira localmente sul ReadyNAS provvede ad aggiornare periodicamente il file remoto tramite una semplice richiesta HTTP GET.

In sostanza si tratta di realizzare due software distinti:

  1. ipremote.php: pagina PHP remota sul proprio dominio web che effettua il redirect all’indirizzo IP di casa
  2. ipupdater.sh: script bash locale (dietro ADSL) che ad intervalli regolari notifica la pagina web inviando il nuovo indirizzo IP

1) Pagina PHP (ipremote.php)

Molto semplicemente assolve alla duplice funzione di 1) redirect automatico e 2) aggiornamento del file ip.txt da parte dello script bash locale. Per accedere come redirect basta fornire la password corretta (in questo caso 123456) tramite una semplice richiesta GET: la pagina legge l’indirizzo IP pubblico corrente dal file e crea l’HTML per il redirect a quell’indirizzo. Per accedere in modalità aggiornamento (script bash presumibilmente) basta fornire, sempre in GET,  la password e il nuovo indirizzo IP: la pagina salverà l’indizzo IP specificato nel file di testo.

Ecco il codice:


<?php

$file = "ip.txt";

if(isset($_GET['newip']) == true && isset($_GET['pass']) == true)
{
   $ip = $_GET['newip'];
   $pass = $_GET['pass'];

   if($pass == "123456")
   {
      // update IP address
      file_put_contents($file, $ip);
   }
   else
   {
      echo "wrong password";
   }
}
else if(isset($_GET['pass']) == true)
{
   $pass = $_GET['pass'];

   if($pass == "123456")
   {
      // get IP address
      $ip = file_get_contents($file);
      echo '<html>';
      echo '<head>';
      echo '<meta http-equiv="refresh" content="0; url=http://'.$ip.'" />';
      echo '</head>';
      echo '<body>';
      echo '</html>';
   }
   else
   {
      echo "wrong password";
   }
}

?>

2) Script bash locale (ipupdater.sh)

Lo script bash viene eseguito periodicamente grazie a cron (ebbene si, il ReadyNAS è un embedded Linux a tutti gli effetti) e provvede a rilevare l’indirizzo pubblico corrente e a notificarlo alla pagina web PHP remota. La regola cron può essere impostata su una volta al minuto, una volta all’ora o quello che si vuole: più il rate di notifica è alto più bassa sarà la probabilità di trovare la pagina web momentaneamente disallineata col vero indirizzo IP.

Ecco lo script:

#!/bin/bash
ip=$(curl -s icanhazip.com)
password="123456"
url="http://www.mysite.it/ipremote.php?newip=$ip&pass=$password"
wget -qO- $url &> /dev/null

Lo script valorizza la variabile $ip con l’IP pubblico corrente. A tal file viene utilizzato il servizio web icanhazip.com che molto semplicemente restituisce l’indirizzo corrente.
Viene quindi composta la stringa URL con la richiesta GET di aggiornamento IP verso la pagina ipremote.php. www.mysite.it è il proprio dominio web, dove risiede ipremote.php.
Infine viene mandata la richiesta HTTP GET tramite wget ovviamente disabilitando opportunamente l’output su file e su console (a noi non interessa).

Come si usa

Accedere al ReadyNAS locale diventa ora banale: basta collegarsi all’indirizzo http://www.mysite.it/ipremote.php?pass=123456 per ottenere il redirect.
Ovvimente il sistema funziona non solo per accedere a dischi di rete, ma tutto quello che avete deciso di esporre nella vostra rete LAN (pannello di gestione remota del modem ADSL, VNC server, programmi vari etc..).

Perchè la password?

E’ chiaro che solo lo script bash locale deve essere in grado di aggiornare l’indirizzo altrimenti potreste ritrovarvi con un redirect ad un IP impostato da terzi. Anche il semplice redirect deve essere protetto da password, più che altro per questioni di privacy: conviene che solo voi possiate raggiungere i servizi della vostra rete LAN (protetti anch’essi da password, ovviamente).

Conclusioni

Vantaggi del sistema? Innanzitutto non occorre registrarsi e fare affidamento a servizi di terze parti (DynDNS, NoIP etc..). Il sistema non soffre dei ritardi di propagazione tipici del DNS per cui il nuovo IP pubblico è prontamente rilevato e aggiornato (basta settare un rate di aggiornamento ragionevolmente breve, tipo 5 minuti). Con un pò di fortuna è possibile embeddare lo script bash direttamente nel modem ADSL; è sufficiente che il modem si appoggi su una qualche distro Linux e abbia il demone cron installato.

Esistono alcuni contro però: la password fissa è soggetta ad attacchi di tipo replay-attack. Converrebbe implementare o un rolling code (ma introduce la possibilità di disallineamento) o meglio ancora uno schema più raffinato di tipo challenge-response.
Altro problema è che occore avere un dominio web PHP funzionante dove appoggiare la pagina ipremote.php.

Intercettazione traffico HTTPS e recupero dati sensibili

E’ possibile recuperare username e password trasmesse in HTTPS? In alcuni casi si. In pratica si tratta del recupero dei dati sensibili trasmessi da altri client della rete locale (credenziali di login tipo facebook, gmail, home banking e chi più ne ha più ne metta). Il trucchetto è abbastanza vecchio e collaudato; oltre a mostrare come eseguirlo correttamente vedremo  le contromisure (e qui ci tengo particolarmente) che finalmente sono state adottate dalla maggior parte dei web server: purtroppo non tutti sono stati aggiornati e moltissimi soffrono ancora di questo tipo di exploit  (siamo nel 2014!).

HTTPS da solo non basta, serve anche la testa! 🙂

Come funziona

L’attacco si definisce propriamente come un MITM (Man in the Middle) nel quale andremo ad utilizzare alcuni specifici tool:

  • SSLStrip
  • Arpspoof (parte integrante del pacchetto dSniff)
  • distro Linux KALI (il nuovo nome della vecchia BackTrack)

http://www.thoughtcrime.org/software/sslstrip/

http://en.wikipedia.org/wiki/DSniff

Durante l’attacco viene temporaneamente rimossa la protezione SSL impostando in modo trasparente l’intero traffico del client vittima in normali sessioni HTTP (invece di HTTPS). Questo permette la cattura e lettura dei dati trasmessi dalla macchina target al server e viceversa.  L’attacco funziona perche’ l’attuale infrastruttura PKI di protezione del web non impone l’uso dell’ HTTPS per tutta la sessione di navigazione dell’utente: si può tranquillamente richiedere HTTP per alcuni elementi delle pagine web visitate (immagini ad esempio…), poi passare ad HTTPS per altri elementi (form di login…), poi di nuovo ripassare ad HTTP e cosi’ via.

https2

Utilizzando il tool SSLStrip e’ possibile forzare le parti in comunicazione (server e client target) ad utilizzare sempre ed esclusivamente HTTP invece della versione sicura HTTPS. Facendo passare questo traffico attraverso la nostra macchina (da qui il man in the middle) possiamo collezionare e leggere lo stream di dati trasmessi (in chiaro!).

https

Un po’ di background…

HTTPS e’ il protocollo standard di protezione del traffico in internet. Viene utilizzato per garantire  trasferimenti riservati di dati nel web. Funziona aggiungendo un livello di crittografia (SSL, Secure Socket Layer) al normale traffico HTTP.

Normalmente il traffico HTTPS puo’ essere intercettato ma non decodificato perche’ cifrato. Il traffico HTTP invece puo’ essere sia intercettato che letto e decodificato (essendo ovviamente in chiaro).

I siti web utilizzano HTTPS quando l’utente deve fornire le proprie credenziali di accesso al sito stesso oppure inviare altri dati sensibili ma possono anche utilizzarlo per tutta la durata della navigazione (come fa GMail, servizi di posta in genere, quasi tutte le online banking e molti altri…).

Questi servizi web non impongono HTTPS e il browser è libero di collegarsi in semplice HTTP.

Esecuzione dell’exploit

La prima fase consiste nel “mettersi in mezzo”, ossia modificare il routing di rete affichè tutto il traffico della nostra vittima passi non direttamente al gateway ma venga redirezionato a noi. In soldoni ci impersonifichiamo come gateway della rete wifi (o cablata), prendiamo tutto il traffico generato dal client vittima e lo passiamo al vero gateway; facciamo anche il contrario: tutto il traffico del gateway verso di noi lo passiamo al client vittma. Ci mettiamo letteralmente in mezzo al canale di comunicazione tra client vittima e gateway.

Per far questo prendiamo la nostra distro KALI Linux (io ho utilizzato una macchina virtuale, va bene lo stesso), ci colleghiamo alla rete, otteniamo l’indirizzo IP ed abilitamo l’IP forwarding:

echo 1 > /proc/sys/net/ipv4/ip_forward"

ipforward_enable

L’IP forwarding va abilitato affinchè i pacchetti possano passare attraverso la nostra macchina in modo trasparente.

A questo punto aggiungiamo una regola al firewall iptables che ci permetterà di acquisire il traffico del client vittima verso di noi:

iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 12345

iptbles_rule

Il client vittima naviga in rete normalmente e questa regola del firewall ci permetterà di acquisire tutto il suo traffico su porta 80 e redirigerlo localmente sulla porta 12345. In ascolto sulla 12345 metteremo SSLStrip che provvederà a modificare le richieste originali di connessione HTTPS prodotte dal client vittima in semplici richieste HTTP.

Occorre ora convincere il client vittima che siamo noi il vero access point e non quello col quale sta comunicando. Per far questo andremo ad alterare le tabelle di routing ARP della rete wifi, in gergo faremo un ARP poisoning (o ARP spoofing) che potremmo tradurre in “avvelenamento della cache ARP” 🙂 .

In pratica iniziamo ad iniettare una gran quantità di pacchetti ARP nella rete; questi pacchetti comunicano agli altri client della rete che il nostro indirizzo MAC è quello del gateway. In questo modo costringiamo il client vittima a passare da noi prima di uscire su internet. Questa informazione errata può essere inviata ad un singolo client di rete (la vittima designata) oppure mandata in broadcast a tutti i partecipanti.

L’arpspoofing è possibile in quanto il protocollo ARP non prevede autenticazione: è possibile comunicare la verità (“io non sono il gateway”) o semplicemente iniettare informazione errata (“io sono il gateway”).

Apriamo una nuova console ed avviamo arpspoof:

arpspoof -i eth0 10.0.0.101 10.0.0.1

10.0.0.101 è il client vittima (il mio pc 🙂 ), 10.0.0.1 il gateway ufficiale (spesso l’AP della rete wifi)

arpspoof_in_action

fatto ciò mettiamo in ascolto SSLStrip sulla porta 12345 e lasciamo che logghi tutto il traffico cifrato del client vittima verso l’esterno.
Con Arpspoof che lavora in background, apriamo una nuova console ed avviamo SSLStrip:

sslstrip -l 12345

di default SSLStrip catturerà solo il traffico SSL POST (quindi solo richieste POST sotto HTTPS) ma possiamo anche configurarlo per ricevere anche tutto il traffico SSL o tutto il traffico HTTP/HTTPS.

sslstrip_runningA questo punto non ci resta che passare al client vittima, navigare in un sito “protetto” da HTTPS e provare ad esempio ad accedere al sito con le nostre credenziali.

Allo scopo mostrerò come recuperare le credenziali in HTTPS da un noto sito italiano. Questo sito non è stato ancora messo completamente in sicurezza e l’exploit è ancora valido. Speriamo ovviamente che venga sistemato il prima possibile.

Andiamo alla login del sito:

poste_loginColleghiamoci con le nostre credenziali. La richiesta arriverà prima ad SSLStrip (siamo in una configurazione MITM, quindi tutte le richiste passano dalla distro Kali Linux) che provvederà a trasformare la richiesta di connessione HTTPS in una HTTP normale. SSLStrip logga su file di testo tutta la transazione, compresi i dati di login.

A questo punto ritorniamo sulla distro ed apriamo il file di log di SSLStrip (ssltrip.log). Troveremo la richiesta POST che il client ha effettuato verso il sito. Le credenziali sono leggibili in chiaro:

password_highlight

Fortunatamente l’exploit non funziona su una WAN, occorre che il client target sia nella propria rete locale.

E quindi?

E’ stato da poco introdotto (da poco per modo di dire,  nel 2012) l’HTTP Strict Transport Security o HTST

http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security

Questo meccanismo impone l’uso di HTTPS per tutta la durata di navigazione del sito. Il browser semplicemente si rifiuta di connettersi al sito tramite il semplice HTTP. La policy, per poter funzionare correttamente, deve essere condivisa ed accettata sia dal server remoto che dal browser. Qui una rapida descrizione:

https://scotthelme.co.uk/hsts-the-missing-link-in-tls/

https://www.eff.org/deeplinks/2014/02/websites-hsts

Ad oggi molti siti internet si sono adeguati tra i quali GMail, Paypal e Twitter. Molti altri, come ad esempio Facebook stentano ad implementarla (la versione mobile è scoperta) e sono quindi ancora vulnerabili. Come dicevo anche i browser devono essere compatibili con HTST, non tutti lo sono e alcuni solo in parte come ad esempio Internet Explorer di Microsoft.

Alcune soluzioni per prevenire l’exploit:

https://serverfault.com/questions/417173/enable-http-strict-transport-security-hsts-in-iis-7

http://www.debian-administration.org/article/662/Enabling_HTTP_Strict_Transport_Security_on_debian_servers