Condividi tramite


Prevenzione degli attacchi injection JavaScript (C#)

di Stephen Walther

Impedire attacchi JavaScript Injection e attacchi di scripting tra siti dall'utente. In questa esercitazione Stephen Walther spiega come è possibile sconfiggere facilmente questi tipi di attacchi tramite codifica HTML.

L'obiettivo di questa esercitazione è spiegare come evitare attacchi di inserimento JavaScript nelle applicazioni MVC ASP.NET. Questa esercitazione illustra due approcci per difendere il sito Web da un attacco di inserimento JavaScript. Si apprenderà come evitare attacchi di inserimento JavaScript codificando i dati visualizzati. Si apprenderà anche come evitare attacchi di inserimento JavaScript codificando i dati accettati.

Che cos'è un attacco JavaScript Injection?

Ogni volta che si accetta l'input utente e si redisplay l'input dell'utente, si apre il sito Web agli attacchi di inserimento JavaScript. Esaminiamo un'applicazione concreta aperta agli attacchi di inserimento JavaScript.

Si supponga di aver creato un sito Web di feedback dei clienti (vedere la figura 1). I clienti possono visitare il sito Web e immettere commenti e suggerimenti sulla loro esperienza usando i tuoi prodotti. Quando un cliente invia il feedback, il feedback viene rieseguito nella pagina di feedback.

Sito Web di commenti e suggerimenti dei clienti

Figura 01: Sito Web di feedback dei clienti (Fare clic per visualizzare l'immagine full-size)

Il sito Web di feedback dei clienti usa l'oggetto controller in Elenco 1. Contiene controller due azioni denominate Index() e Create().

Elenco 1 – HomeController.cs

using System;
using System.Web.Mvc;
using CustomerFeedback.Models;

namespace CustomerFeedback.Controllers
{
     [HandleError]
     public class HomeController : Controller
     {
          private FeedbackDataContext db = new FeedbackDataContext();

          public ActionResult Index()
          {
               return View(db.Feedbacks);
          }

          public ActionResult Create(string message)

          {
               // Add feedback
               var newFeedback = new Feedback();
               newFeedback.Message = message;
               newFeedback.EntryDate = DateTime.Now;
               db.Feedbacks.InsertOnSubmit(newFeedback);
               db.SubmitChanges();

               // Redirect
               return RedirectToAction("Index");
          }
     }
}

Il Index() metodo visualizza la Index visualizzazione. Questo metodo passa tutti i commenti dei clienti precedenti alla Index visualizzazione recuperando il feedback dal database (usando una query LINQ to SQL).

Il Create() metodo crea un nuovo elemento Feedback e lo aggiunge al database. Il messaggio immesso dal cliente nel modulo viene passato al Create() metodo nel parametro message. Viene creato un elemento Feedback e il messaggio viene assegnato alla proprietà dell'elemento Message Feedback. L'elemento Feedback viene inviato al database con la chiamata al DataContext.SubmitChanges() metodo. Infine, il visitatore viene reindirizzato alla Index visualizzazione in cui viene visualizzato tutto il feedback.

La visualizzazione è contenuta nell'elenco Index 2.

Presentazione 2 – Index.aspx

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="CustomerFeedback.Views.Home.Index"%>

<%@ Import Namespace="CustomerFeedback.Models" %>

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
     <h1>Customer Feedback</h1>
     <p>
          Please use the following form to enter feedback about our product.
     </p>

     <form method="post" action="/Home/Create">

          <label for="message">Message:</label>
          <br />
          <textarea name="message" cols="50" rows="2"></textarea>
          <br /><br />
          <input type="submit" value="Submit Feedback" />
     </form>

     <% foreach (Feedback feedback in ViewData.Model)
     {%>
          <p>
          <%=feedback.EntryDate.ToShortTimeString()%>
          --
          <%=feedback.Message%>
          </p>
     <% }%>

</asp:Content>

La Index visualizzazione include due sezioni. La sezione superiore contiene il modulo di feedback dei clienti effettivo. La sezione inferiore contiene un oggetto For.. Ogni ciclo che scorre tutti gli elementi di feedback dei clienti precedenti e visualizza le proprietà EntryDate e Message per ogni elemento di feedback.

Il sito Web di feedback dei clienti è un sito Web semplice. Sfortunatamente, il sito Web è aperto agli attacchi di inserimento JavaScript.

Si supponga di immettere il testo seguente nel modulo di feedback del cliente:

<script>alert("Boo!")</script>

Questo testo rappresenta uno script JavaScript che visualizza una finestra di messaggio di avviso. Dopo che qualcuno invia questo script nel modulo di feedback, il messaggio Boo!verrà visualizzato ogni volta che chiunque visita il sito Web di feedback dei clienti in futuro (vedere la figura 2).

JavaScript Injection

Figura 02: JavaScript Injection (Fare clic per visualizzare l'immagine full-size)

Ora, la risposta iniziale agli attacchi di inserimento JavaScript potrebbe essere apatia. Si potrebbe pensare che gli attacchi di inserimento JavaScript siano semplicemente un tipo di attacco di defacemento . Potresti credere che nessuno possa fare niente di veramente male eseguendo un attacco di inserimento JavaScript.

Sfortunatamente, un hacker può fare alcune cose davvero malvagie inserendo JavaScript in un sito Web. È possibile usare un attacco JavaScript injection per eseguire un attacco XSS (Cross-Site Scripting). In un attacco cross-site scripting si rubano informazioni utente riservate e si inviano le informazioni a un altro sito Web.

Ad esempio, un hacker può usare un attacco di inserimento JavaScript per rubare i valori dei cookie del browser da altri utenti. Se le informazioni riservate, ad esempio password, numeri di carta di credito o numeri di sicurezza sociale, vengono archiviate nei cookie del browser, un hacker può usare un attacco di inserimento JavaScript per rubare queste informazioni. In alternativa, se un utente immette informazioni riservate in un campo modulo contenuto in una pagina compromessa con un attacco JavaScript, l'hacker può usare javaScript inserito per acquisire i dati del modulo e inviarli a un altro sito Web.

Si prega di essere spaventati. Prendere seriamente attacchi di inserimento JavaScript e proteggere le informazioni riservate dell'utente. Nelle due sezioni successive vengono illustrate due tecniche che è possibile usare per difendere le applicazioni MVC ASP.NET dagli attacchi di inserimento JavaScript.

Approccio #1: Codifica HTML nella visualizzazione

Un metodo semplice per impedire attacchi di inserimento JavaScript consiste nel codificare HTML tutti i dati immessi dagli utenti del sito Web quando si redisplayno i dati in una visualizzazione. La visualizzazione aggiornata Index nell'elenco 3 segue questo approccio.

Elenco 3 : Index.aspx (codifica HTML)

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="CustomerFeedback.Views.Home.Index"%>

<%@ Import Namespace="CustomerFeedback.Models" %>

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
     <h1>Customer Feedback</h1>
     <p>
          Please use the following form to enter feedback about our product.
     </p>

     <form method="post" action="/Home/Create">
          <label for="message">Message:</label>
          <br />
          <textarea name="message" cols="50" rows="2"></textarea>
          <br /><br />
          <input type="submit" value="Submit Feedback" />

     </form>

     <% foreach (Feedback feedback in ViewData.Model)
     {%>
          <p>
          <%=feedback.EntryDate.ToShortTimeString()%>
          --
          <%=Html.Encode(feedback.Message)%>
          </p>
     <% }%>

</asp:Content>

Si noti che il valore di è codificato HTML prima che feedback.Message il valore venga visualizzato con il codice seguente:

<%=Html.Encode(feedback.Message)%>

Cosa significa codificare html una stringa? Quando si codifica una stringa, i caratteri pericolosi come < e > vengono sostituiti da riferimenti alle entità HTML, ad esempio &lt; e &gt;. Quindi, quando la stringa <script>alert("Boo!")</script> è codificata HTML, viene convertita in &lt;script&gt;alert(&quot;Boo!&quot;)&lt;/script&gt;. La stringa codificata non viene più eseguita come script JavaScript quando viene interpretata da un browser. Si ottiene invece la pagina innocua nella figura 3.

Attacco JavaScript sconfitto

Figura 03: Attacco JavaScript sconfitto (fare clic per visualizzare l'immagine full-size)

Si noti che nella visualizzazione nell'elenco Index 3 viene codificato solo il valore di feedback.Message . Il valore di feedback.EntryDate non è codificato. È sufficiente codificare i dati immessi da un utente. Poiché il valore di EntryDate è stato generato nel controller, non è necessario codificare html questo valore.

Approccio #2: Codifica HTML nel controller

Anziché i dati di codifica HTML quando vengono visualizzati i dati in una visualizzazione, è possibile codificare HTML i dati prima di inviare i dati al database. Questo secondo approccio viene adottato nel caso dell'elenco controller 4.

Elenco 4 : HomeController.cs (codificato HTML)

using System;
using System.Web.Mvc;
using CustomerFeedback.Models;
namespace CustomerFeedback.Controllers
{
     [HandleError]
     public class HomeController : Controller
     {
          private FeedbackDataContext db = new FeedbackDataContext();

          public ActionResult Index()
          {
               return View(db.Feedbacks);
          }

          public ActionResult Create(string message)
          {
               // Add feedback
               var newFeedback = new Feedback();
               newFeedback.Message = Server.HtmlEncode(message);
               newFeedback.EntryDate = DateTime.Now;
               db.Feedbacks.InsertOnSubmit(newFeedback);

               db.SubmitChanges();

               // Redirect
               return RedirectToAction("Index");
          }
     }
}

Si noti che il valore di Message è codificato HTML prima che il valore venga inviato al database all'interno dell'azione Create() . Quando il messaggio viene rieseguito nella visualizzazione, il messaggio è codificato HTML e qualsiasi javaScript inserito nel messaggio non viene eseguito.

In genere, è consigliabile favorire il primo approccio descritto in questa esercitazione su questo secondo approccio. Il problema con questo secondo approccio è che si finisce con i dati codificati HTML nel database. In altre parole, i dati del database sono sporsi con caratteri divertenti.

Perché questo è cattivo? Se è mai necessario visualizzare i dati del database in un elemento diverso da una pagina Web, si avranno problemi. Ad esempio, non è più possibile visualizzare facilmente i dati in un'applicazione Windows Forms.

Riepilogo

Lo scopo di questa esercitazione è stato quello di spaventare la prospettiva di un attacco di inserimento JavaScript. Questa esercitazione ha illustrato due approcci per difendere le applicazioni MVC ASP.NET contro gli attacchi di inserimento JavaScript: è possibile codificaRE HTML i dati inviati dall'utente nella visualizzazione oppure codificare i dati inviati dall'utente nel controller.