Un server web dopo aver ricevuto un pacchetto "http request" fornisce la pagina richiesta e si dimentica del client. In alcuni casi, invece, il server web ha bisogno di ricordare le azioni del client. È il caso di un sito e-commerce, o un'area riservata dove l'accesso ad ogni pagina non deve costringere a ripetere il login. In generale si richiede di mantenere una memoria delle azioni dell'utente, quando questi può navigare tra varie pagine e, in ognuna di queste, può fare delle scelte.
Il protocollo http consiste in pacchetti di tipo http request, inviati dal browser al server web, e pacchetti di tipo http response, inviati dal server web al browser.
Un pacchetto di tipo http request è formato da tre parti:
metodo
header
dati
La sezione dati può contenere le informazioni inviate dal client al server con il metodo POST.
Un pacchetto di tipo http response è formato da tre parti:
linea di stato
header
documento
Il server comunica il cookie al client, inserendo una linea setcookie: nella sezione header del pacchetto di risposta. Per questo motivo i cookie devono essere inviati dal server al client prima della pagina web. Se lo script lato server invia il cookie quando è stata già eseguita un'istruzione "echo", "print" o sono stati già inviati i tag, viene segnalato un errore.
Il browser del client allega il cookie alla sua richiesta inserendo una linea cookie: nel campo header.
Nell'esercizio proposto si simula, parzialmente, un negozio on-line. Un utente accede alla pagina iniziale, sceglie un reparto del negozio di suo interesse, effettua delle scelte e passa ad un altro reparto.
I cookie sono file di testo che la pagina sul server web invia al client, allo scopo di delegare al browser il compito di mantenere la memoria della sessione di connessione. Il server web continua a dimenticare le scelte dell'utente, sarà il browser a ricordarle, rispedendo il cookie al server.
Creare una cartella in cui salvare i file di questa sezione del sito, denominarla cookie.
<?php
if (!isset($_COOKIE["totale"]))
$totale=0;
else
$totale = $_COOKIE["totale"];
setcookie("totale", $totale, time()+3600, "/cookie/","localhost");
?>
<html>
<head>
</head>
<body>
<h1>Scegli il reparto:</h1>
<?php
echo "<p>totale acquisti: ".$totale."</p>";
?>
<ul>
<li><a href="abbigliamento.php">abbigliamento</a></li>
<li><a href="telefonia.php">telefonia</a></li>
<li><a href="vacanze.php">vacanze</a></li>
<li><a href="arredamento.php">arredamento</a></li>
</ul>
<a href="annulla.php">annulla gli acquisti</a>
</body>
</html>
<?php
$totale = $_COOKIE["totale"];
if (isset($_GET["fine"])) {
setcookie("totale", $totale, time()+3600, "/cookie/index.php","localhost");
header("location:index.php");
}
if (isset($_GET["costo"])) {
$totale += $_GET["costo"];
}
setcookie("totale", $totale, time()+3600, "/cookie/","localhost");
?>
<html>
<head></head>
<body>
<h1>Scegli tra i seguenti articoli</h1>
<?php
echo "spesa totale: ".$totale;
?>
<ul>
<li>calzini 0,50 Euro <a href="abbigliamento.php?costo=0.5">lo voglio</a></li>
</ul>
<p><a href="abbigliamento.php?fine=1">torna</a> alla pagina iniziale</p>
</body>
</html>
<?php
$totale = $_COOKIE["totale"];
if (isset($_GET["fine"])) {
setcookie("totale", $totale, time()+3600, "/cookie/index.php", "localhost");
header("location:index.php");
}
if (isset($_GET["costo"])) {
$totale += $_GET["costo"];
}
setcookie("totale", $totale, time()+3600, "/cookie/", "localhost");
?>
<html>
<head></head>
<body>
<h1>Scegli tra i seguenti articoli</h1>
<?php
echo "spesa totale: ".$totale;
?>
<ul>
<li>cover iPhone 2 Euro <a href="telefonia.php?costo=2">lo voglio</a></li>
</ul>
<p><a href="telefonia.php?fine=1">torna</a> alla pagina iniziale</p>
</body>
</html>
<?php
$totale = $_COOKIE["totale"];
if (isset($_GET["fine"])) {
setcookie("totale", $totale, time()+3600, "/cookie/index.php", "localhost");
header("location:index.php");
}
if (isset($_GET["costo"])) {
$totale += $_GET["costo"];
}
setcookie("totale", $totale, time()+3600, "/cookie/", "localhost");
?>
<html>
<head></head>
<body>
<h1>Scegli tra i seguenti articoli</h1>
<?php
echo "spesa totale: ".$totale;
?>
<ul>
<li>1 settimana in hotel 500 Euro <a href="vacanze.php?costo=500">lo voglio</a></li>
</ul>
<p><a href="vacanze.php?fine=1">torna</a> alla pagina iniziale</p>
</body>
</html>
<?php
$totale = $_COOKIE["totale"];
if (isset($_GET["fine"])) {
setcookie("totale", $totale, time()+3600, "/cookie/index.php", "localhost");
header("location:index.php");
}
if (isset($_GET["costo"])) {
$totale += $_GET["costo"];
}
setcookie("totale", $totale, time()+3600, "/cookie/", "localhost");
?>
<html>
<head></head>
<body>
<h1>Scegli tra i seguenti articoli</h1>
<?php
echo "spesa totale: ".$totale;
?>
<ul>
<li>sedia 50 Euro <a href="arredamento.php?costo=50">lo voglio</a></li>
</ul>
<p><a href="arredamento.php?fine=1">torna</a> alla pagina iniziale</p>
</body>
</html>
Verificare il funzionamento dei cookie.
Per questo caso, il cookie deve avere una durata di validità oppure al termine della sessione deve essere cancellato, altrimenti quando l'utente si collegherà nuovamente al sito, invierà l'ultimo cookie memorizzato sul suo computer.
<?php
setcookie("totale", "0", time()+3600, "/cookie/index.php", "localhost", 0);
header("location:index.php");
?>
In questo esempio si aggiunge la lista degli articoli acquistati.
<?php
if (!isset($_COOKIE["totale"])) {
$totale=0;
$articoli = "Hai preso:-";
}
else {
$totale = $_COOKIE["totale"];
$articoli = $_COOKIE["articoli"];
}
setcookie("totale", $totale, time()+3600, "/cookie/","localhost");
setcookie("articoli", $articoli, time()+3600, "/cookie/","localhost");
?>
<html>
<head>
</head>
<body>
<h1>Scegli il reparto</h1>
<?php
echo "<p>totale acquisti: ".$totale."</p>";
echo "articoli scelti: ".$articoli;
$elenco = explode("-", $articoli);
foreach ($elenco as $valore) echo "<br />:".$valore;
?>
<ul>
<li><a href="abbigliamento.php">abbigliamento</a></li>
<li><a href="telefonia.php">telefonia</a></li>
<li><a href="vacanze.php">vacanze</a></li>
<li><a href="arredamento.php">arredamento</a></li>
</ul>
<a href="annulla.php">annulla gli acquisti</a>
</body>
</html>
Per aggiungere più variabili nello stesso cookie, si concatena ciascuna variabile in una stringa, terminandola con un carattere convenzionale che servirà come separatore. La funzione explode() del php estrae ciascuna stringa preceduta dal carattere scelto (in questo esempio si è scelto il segno -) e la inserisce in un array.
<?php
$totale = $_COOKIE["totale"];
$articoli = $_COOKIE["articoli"];
if (isset($_GET["fine"])) {
setcookie("totale", $totale, time()+3600, "/cookie/index.php", "localhost");
setcookie("articoli", $articoli, time()+3600, "/cookie/index.php", "localhost");
header("location:index.php");
}
if (isset($_GET["costo"])) {
$totale += $_GET["costo"];
$articoli .= $_GET["articolo"]."-";
}
setcookie("totale", $totale, time()+3600, "/cookie/", "localhost");
setcookie("articoli", $articoli, time()+3600, "/cookie/", "localhost");
?>
<html>
<head></head>
<body>
<h1>Scegli tra i seguenti articoli:</h1>
<?php
echo "spesa totale: ".$totale;
?>
<ul>
<li>calzini 0,50 Euro <a href="abbigliamento.php?costo=0.5">lo voglio</a></li>
<li>cravatta 1.20 Euro <a href="abbigliamento.php?costo=1.20&articolo=cravatta">la prendo</a></li>
</ul>
<p><a href="abbigliamento.php?fine=1">torna</a> alla pagina iniziale</p>
</body>
</html>
Modificare gli altri tre file aggiungendo le stesse modifiche apportate al file precedente.
<?php
setcookie("totale", "0", time()+3600, "/cookie/index.php", "localhost", 0);
setcookie("articoli", "-", time()+3600, "/cookie/index.php", "localhost", 0);
header("location:index.php");
?>
Un intruso cerca una pagina in cui viene proposto un form in cui sia presente una casella di testo che lo script lato server legge e poi, in una nuova pagina, ne mostra il contenuto. L'intruso inserisce in questa casella di testo uno script che verrà eseguito dal browser del client. Se esiste questa possibilità l'intruso può accedere a informazioni riservate.
In altri casi, l'attaccante potrebbe inserire un codice che viene memorizzato dal server (ad esempio un forum) e quindi verrà eseguito dal browser degli utenti che leggono la pagina.
Per ipotesi, in una delle pagine relative ai reparti del negozio viene richiesto di inserire l'indirizzo di consegna, che poi verrà mostrato nella pagina index.php.
<!-- prova Cross Site Scripting -->
<p>Indirizzo di consegna:</p>
<form method="post" action="index.php">
<input type="text" name="script" />
<input type="submit" />
</form>
<!-- Fine prova Cross Site Scripting -->
Alla fine del file index.php inserire uno script php che stampa l'indirizzo di consegna:
<p>Indirizzo di consegna: <?php echo $_POST["script"]; ?></p>
L'intruso verifica la vulnerabilità della pagina inserendo uno script innocuo, ad esempio:
<script>alert("attacco")</script>
Se il browser mostra il messaggio, allora non ci sono limiti alle possibilità di violare la riservatezza dei dati. Ma il server è impostato per rifiutare i caratteri di delimitazione delle stringhe, e sostituisce tutti i caratteri " con \". L'intruso allora prova a sostituire gli apici con la sequenza speciale ":
<script>alert("attacco")</script>
Se anche in questo caso lo script viene rifiutato, esiste ancora un'altra possibilità: usare il metodo fromCharCode della classe String, che trasforma i codici decimali dei caratteri nella loro rappresentazione ASCII.
La stringa da inserire è
<script>alert(String.fromCharCode(97,116,116,97,99,99,111,32,88,83,83))</script>
per inviare un'immagine inserire il seguente codice html:
<img src="figura.png" />Questi esempi non costituiscono alcun danno per il server, perchè l'intruso riceve solo dei messaggi sul suo browser. Ma a questo punto l'intruso può ad esempio conoscere i dati contenuti nelle variabili di sessione e sfruttarle per acquisire privilegi di amministrazione. Ad esempio:
<script>document.write(document.cookie)</script>
Per altri esempi di attacchi di tipo cross site script esistono numerosi esempi sul web, uno dei quali è: questo.