tags: reflected_xss


La Reflected XXS è un tipo di vulnerabilità XSS in cui uno script dannoso viene riflesso nel browser dell’utente, spesso tramite un URL creato ad arte o tramite l’invio di un modulo. Si consideri una query di ricerca contenente <script>alert(document.cookie)</script> molti utenti non sarebbero sospettosi di un URL del genere, anche se lo guardassero da vicino. Se elaborato da un’applicazione web vulnerabile, verrà eseguito nel contesto del browser dell’utente. In questo innocuo esempio, visualizza il cookie in una casella di avviso. Ovviamente, un aggressore vuole ottenere di più che visualizzare il cookie come avviso all’utente. Tuttavia, affinché un attacco del genere sia possibile, abbiamo bisogno di un’applicazione vulnerabile.

Sebbene scoprire tali vulnerabilità non sia sempre facile, risolverle è semplice. L’input dell’utente, ad esempio <script>alert('XSS')</script> dovrebbe essere santizzato o codificato in HTML in &lt;script&gt;alert('XSS')&lt;/script&gt;.

Nelle sottosezioni seguenti, forniamo esempi di codice vulnerabile nei seguenti linguaggi e framework:

  • PHP
  • JavaScript (Node.js)
  • Python (Flask)
  • C# (ASP.NET

PHP

Il seguente codice mostra un codice php vulnerabile ad una Reflected XSS:

<?php
$search_query = $_GET['q'];
echo "<p>You searched for: $search_query</p>";
?>

$_GET è un array PHP contenente valori dalla stringa di query URL. Inoltre, $_GET['q'] si riferisce al parametro della stringa di query q. Ad esempio, in http://shop.thm/search.php?q=table`$_GET['q'] ha il valore di table. la vulnerabilità è causata dal valore di ricerca visualizzato nella pagina dei risultati senza sanificazione. Pertanto, un aggressore può aggiungere uno script dannoso all’URL, sapendo che verrebbe eseguito. Ad esempio, come prova di concetto, può essere testato il seguente http://shop.thm/search.php?q= e se il sito è vulnerabile, apparirà una finestra di avviso che mostra i cookie dell’utente.`

Un esempio di codice sanitizzato è il seguente

<?php
$search_query = $_GET['q'];
$escaped_search_query = htmlspecialchars($search_query);
echo "<p>You searched for: $escaped_search_query</p>";
?>

La funzione PHP htmlspecialchars() converte i caratteri speciali in entità HTML. I caratteri <, >, &, ”, ’ vengono sostituiti di default per impedire l’esecuzione degli script nell’input. Puoi leggere la sua documentazione qui.

Javascript (Node.js)

Il seguente frammento di codice Node.js è vulnerabile ad una Reflected XSS:

const express = require('express');
const app = express();
 
app.get('/search', function(req, res) {
    var searchTerm = req.query.q;
    res.send('You searched for: ' + searchTerm);
});
 
app.listen(80);

Il frammento di codice sopra riportato usa Express, un framework di applicazioni web popolare per Node.js. Il req.query.q estrarrà il valore di q. Ad esempio, in http://shop.thm/search?q=tablereq.query.q ha il valore di table Infine, la risposta viene generata aggiungendo il termine di ricerca fornito dall’utente a “You searched for:“. Poiché il valore viene preso dall’utente e inserito nell’HTML della risposta senza sanificazione o escape, è facile aggiungere una query dannosa. Come prova di concetto, possiamo testare il seguente URL:http://shop.thm/search?q=<script>alert(document.cookie)</script> e se il sito è vulnerabile, apparirà una finestra di avviso che mostra il cookie dell’utente.

Un codice sanitizzato è il seguente:

const express = require('express');
const sanitizeHtml = require('sanitize-html');
 
const app = express();
 
app.get('/search', function(req, res) {
    const searchTerm = req.query.q;
    const sanitizedSearchTerm = sanitizeHtml(searchTerm);
    res.send('You searched for: ' + sanitizedSearchTerm);
});
 
app.listen(80);

La soluzione si ottiene utilizzando sanitizeHtml() dalla libreria sanitize-html. Questa funzione rimuove elementi e attributi non sicuri. Ciò include la rimozione di tag script, tra gli altri elementi che potrebbero essere utilizzati per scopi dannosi. Puoi leggere la sua documentazione qui Un altro approccio sarebbe quello di utilizzare la funzione escapeHtml() invece della funzione sanitizeHtml(). Come indica il nome, la funzione escapeHtml() mira a eseguire l’escape di caratteri come <, >, &, ” e ‘. Puoi controllare la sua homepage qui.

Python (Flask)

Consideriamo la seguente semplice applicazione Flask:

from flask import Flask, request
 
app = Flask(__name__)
 
@app.route("/search")
def home():
    query = request.args.get("q")
    return f"You searched for: {query}!"
 
if __name__ == "__main__":
    app.run(debug=True)

In questo codice request.args.get() viene utilizzato per accedere ai parametri della stringa di query dall’URL della richiesta. Infatti, request.args contiene tutti i parametri della stringa di query in un oggetto simile a un dizionario. Ad esempio, in http://shop.thm/search?q=tablerequest.args.get("q") ha valore table. Poiché il valore viene preso dall’utente e inserito nell’HTML di risposta senza sanificazione o escape, è facile aggiungere una query dannosa. Come prova di concetto, possiamo testare il seguente URL:http://shop.thm/search?q=<script>alert(document.cookie)</script> e se il sito è vulnerabile, apparirà una finestra di avviso che mostra il cookie dell’utente.

Un codice sanitizzato è il seguente:

from flask import Flask, request
from html import escape
 
app = Flask(__name__)
 
@app.route("/search")
def home():
    query = request.args.get("q")
    escaped_query = escape(query)
    return f"You searched for: {escaped_query}!"
 
if __name__ == "__main__":
    app.run(debug=True)

La modifica principale è che l’input dell’utente ora viene sottoposto a escape usando la funzione escape() del modulo html. Nota che la funzione html.escape() in Flask è in realtà un alias per markupsafe.escape(). Entrambe provengono dalla libreria Werkzeug e hanno lo stesso scopo: eseguire l’escape di caratteri non sicuri nelle stringhe. Questa funzione converte caratteri come <, >, ”, ’ in entità HTML sottoposte a escape, disarmando qualsiasi codice dannoso inserito dall’utente.

ASP.NET

Ecco come si presenta un codice vulnerabile in C#

public void Page_Load(object sender, EventArgs e)
{
    var userInput = Request.QueryString["q"];
    Response.Write("User Input: " + userInput);
}

Il codice sopra utilizza Request.QueryString, che restituisce una raccolta di chiavi e valori di stringa associati. Nell’esempio sopra, siamo interessati al valore associato alla chiave q e lo salviamo nella variabile userInput. Infine, la risposta viene creata aggiungendo userInput a un’altra stringa.

Codice sanitizzato

using System.Web;
 
public void Page_Load(object sender, EventArgs e)
{
    var userInput = Request.QueryString["q"];
    var encodedInput = HttpUtility.HtmlEncode(userInput);
    Response.Write("User Input: " + encodedInput);
}

Ancora una volta, la soluzione sta nel codificare l’input dell’utente in stringhe HTML-safe. ASP.NET C# fornisce il metodo HttpUtility.HtmlEncode(), che converte vari caratteri, come <, > e &, nella rispettiva codifica dell’entità HTML.