Nel Web, la comunicazione e lo scambio di dati tra client (browser) e server (Web server) avviene secondo le specifiche del protocollo HTTP: il browser che voglia richiedere una pagina HTML al server, apre un socket verso l'IP di questo (e generalmente verso la porta 80) ed invia dati che soddisfano ai dettami del protocollo HTTP. Il server risponde inviando, sempre incapsulato in alcuni header (righe) di controllo propri dell'HTTP, la pagina HTML+JavaScript (puro testo).
Porterò ora un esempio di codice che simuli il comportamento di un browser in PHP, scaricando la pagina Web HTML http://www.php.net/docs.php:
<?php
$server_url = "www.php.net";
$pagina_url = "/docs.php";
$plain_response = "";
$fp = fsockopen($server_url, 80);
fputs($fp, "GET ".$pagina_url." HTTP/1.1rn");
fputs($fp, "Accept: text/htmlrn");
fputs($fp, "Host: ".$server_url."rn");
fputs($fp, "Cache-Control: max-age=10000rn");
fputs($fp, "Connection: Closernrn");
while (!feof($fp)) $plain_response .= fgets($fp);
fclose($fp);
echo $plain_response;
?>
Le righe di testo inviate al Web server sono quindi:
GET /docs.php HTTP/1.1
Accept: text/html
Host: www.php.net
Cache-Control: max-age=10000
Connection: Close
L'ultima riga deve essere vuota.
La risposta del server sarà del tipo: ($plain_response)
HTTP/1.1 200 OK
Date: Mon, 30 May 2005 08:38:16 GMT
Server: Apache/1.3.26 (Unix) mod_gzip/1.3.26.1a PHP/4.3.3-dev
X-Powered-By: PHP/4.3.3-dev
Content-language: en
Set-Cookie: COUNTRY=ITA%2C80.67.115.42; expires=Mon, 06-Jun-05 08:38:16 GMT; path=/; domain=.php.net
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html;charset=ISO-8859-1
2071
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>PHP: Documentation</title>
<style type="text/css">
@import url("http://static.php.net/www.php.net/styles/site.css");
</style>
<link rel="shortcut icon" href="http://static.php.net/www.php.net/favicon.ico" />
<script type="text/javascript" src="http://static.php.net/userprefs.js"></script>
<base href="http://www.php.net/docs.php" />
</head>
<body onload="runOnLoad();">
[... etc ...]
</body>
</html>
0
Notiamo il codice HTML quale payload del protocollo HTTP.
Le eventuali immagini collegate alla pagina HTML sono puntate, come noto, dal tag <img>.
Nell'interpretare ognuno di tali tag, il browser invia, al fine di visualizzarne il contenuto, altre semplici richieste HTTP al server opportuno per recuperare l'immagine:
GET /immagine.jpg HTTP/1.1
Il medesimo discorso vale per dati binari di ogni tipo e quindi per i tag src
, iframe
e così via.
Ciò premesso, gli attacchi di tipo Cross Site Request Forgeries (o CSRF) vengono portati a termine sostituendo, all'interno del tag HTML <img>
e simili, una particolare stringa - una qualsiasi query string - che ad esempio che punti ad una pagina Web con dati parametri in GET: il browser tratterà questa esattamente come la richiesta per una nuova pagina HTML, quale l'avessimo scritta noi nella barra degli indirizzi. Vedremo di seguito come questo possa costituire un pericolo.
Modificare i tag <img>
è più facile di quanto si creda: come sappiamo, in ogni forum è infatti possibile inserire immagini - spesso in realtà si usa per l'uopo il tag [img]
. Comunque sia, in un eventuale forum "amatoriale" l'exploit è praticamente scontato.
Altro possibile veicolo per iniezioni di CSRF sono proprio le vulnerabilità XSS poc'anzi viste.