Предотвращение атак, осуществляемых путем внедрения кода JavaScript (VB)

Стивен Уолтер (Stephen Walther)

Предотвращение атак путем внедрения кода JavaScript и межсайтовых сценариев. В этом руководстве Стивен Уолтер объясняет, как можно легко победить эти типы атак, кодируя содержимое в ФОРМАТЕ HTML.

Цель этого руководства — объяснить, как можно предотвратить атаки путем внедрения кода JavaScript в приложениях ASP.NET MVC. В этом руководстве рассматриваются два подхода к защите веб-сайта от атак путем внедрения кода JavaScript. Вы узнаете, как предотвратить атаки путем внедрения кода JavaScript путем кодирования отображаемых данных. Вы также узнаете, как предотвратить атаки путем внедрения кода JavaScript путем кодирования принимаемых данных.

Что такое атака путем внедрения кода JavaScript?

Всякий раз, когда вы принимаете введенные пользователем данные и повторно воспроизводите введенные пользователем данные, вы открываете свой веб-сайт для атак путем внедрения кода JavaScript. Давайте рассмотрим конкретное приложение, открытое для атак путем внедрения кода JavaScript.

Представьте, что вы создали веб-сайт отзывов клиентов (см. рис. 1). Клиенты могут посетить веб-сайт и ввести отзывы о своем опыте использования ваших продуктов. Когда клиент отправляет свой отзыв, он повторно отображается на странице отзывов.

Веб-сайт отзывов клиентов

Рис. 01. Веб-сайт отзывов клиентов (щелкните для просмотра полноразмерного изображения)

На веб-сайте отзывов клиентов используется в листинге controller 1. Содержит controller два действия с именами Index() и Create().

Листинг 1 — HomeController.vb

Public Class HomeController
     Inherits System.Web.Mvc.Controller

     Private db As New FeedbackDataContext()

     Function Index()
          Return View(db.Feedbacks)
     End Function

     Function Create(ByVal message As String)
          ' Add feedback
          Dim newFeedback As New Feedback()
          newFeedback.Message = Server.HtmlEncode(message)

          newFeedback.EntryDate = DateTime.Now
          db.Feedbacks.InsertOnSubmit(newFeedback)
          db.SubmitChanges()

          ' Redirect
          Return RedirectToAction("Index")
     End Function

End Class

Метод Index() отображает Index представление. Этот метод передает все предыдущие отзывы клиентов в Index представление путем получения обратной связи из базы данных (с помощью запроса LINQ to SQL).

Метод Create() создает новый элемент Feedback и добавляет его в базу данных. Сообщение, введенное клиентом в форме, передается методу Create() в параметре message. Создается элемент "Отзыв", и сообщение назначается свойству элемента Message Feedback. Элемент Feedback отправляется в базу данных с DataContext.SubmitChanges() помощью вызова метода . Наконец, посетитель перенаправляется обратно в Index представление, где отображаются все отзывы.

Представление Index содержится в листинге 2.

Листинг 2 — Index.aspx

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="CustomerFeedback.Index"%>

<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>

     <% For Each feedback As CustomerFeedback.Feedback In ViewData.Model%>
          <p>

          <%=feedback.EntryDate.ToShortTimeString()%>
          --
          <%=feedback.Message%>
          </p>
     <% Next %>

</asp:Content>

Представление Index состоит из двух разделов. В верхней части содержится фактическая форма обратной связи с клиентами. В нижнем разделе содержится элемент For.. Каждый цикл, который перебирает все предыдущие элементы отзывов клиентов и отображает свойства EntryDate и Message для каждого элемента обратной связи.

Веб-сайт отзывов клиентов — это простой веб-сайт. К сожалению, веб-сайт открыт для атак путем внедрения кода JavaScript.

Представьте, что вы вводите следующий текст в форму обратной связи клиента:

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

Этот текст представляет скрипт JavaScript, который отображает окно оповещения. После того как кто-то отправит этот скрипт в форму обратной связи, появится сообщение Boo!будет отображаться каждый раз, когда кто-либо заходит на веб-сайт отзывов клиентов в будущем (см. рис. 2).

Внедрение Кода JavaScript

Рис. 02. Внедрение Кода JavaScript (щелкните для просмотра полноразмерного изображения)

Теперь ваш первоначальный ответ на атаки путем внедрения кода JavaScript может быть апатией. Вы можете подумать, что атаки путем внедрения кода JavaScript — это просто тип атаки дефайсмента . Вы можете поверить, что никто не может сделать ничего действительно плохого, совершив атаку путем внедрения кода JavaScript.

К сожалению, хакер может сделать некоторые действительно, действительно плохие вещи, внедряя JavaScript на веб-сайт. Вы можете использовать атаку путем внедрения кода JavaScript для выполнения атаки межсайтовых сценариев (XSS). При атаке меж site-scripting вы похищаете конфиденциальные сведения о пользователях и отправляете их на другой веб-сайт.

Например, злоумышленник может использовать атаку путем внедрения кода JavaScript для кражи значений файлов cookie браузера у других пользователей. Если конфиденциальная информация, например пароли, номера кредитов карта или номера социального страхования, хранится в файлах cookie браузера, злоумышленник может использовать атаку путем внедрения Кода JavaScript, чтобы украсть эту информацию. Или, если пользователь вводит конфиденциальную информацию в поле формы, содержащееся на странице, которая была скомпрометирована атакой На JavaScript, злоумышленник может использовать внедренный Код JavaScript, чтобы захватить данные формы и отправить их на другой веб-сайт.

Пожалуйста, бойтесь. Серьезно относитесь к атакам путем внедрения кода JavaScript и защитите конфиденциальную информацию пользователя. В следующих двух разделах мы обсудим два метода, которые можно использовать для защиты ASP.NET приложений MVC от атак путем внедрения кода JavaScript.

Подход 1. Кодирование HTML в представлении

Одним из простых способов предотвращения атак путем внедрения кода JavaScript является кодирование html любых данных, введенных пользователями веб-сайта при повторном воспроизведении данных в представлении. Обновленное Index представление в листинге 3 соответствует этому подходу.

Листинг 3 . Index.aspx (в кодировке HTML)

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="CustomerFeedback.Index"%>

<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>

     <% For Each feedback As CustomerFeedback.Feedback In ViewData.Model%>
          <p>
          <%=feedback.EntryDate.ToShortTimeString()%>
          --
          <%=Html.Encode(feedback.Message)%>

          </p>
     <% Next %>

</asp:Content>

Обратите внимание, что значение feedback.Message закодировано в ФОРМАТЕ HTML перед отображением значения с помощью следующего кода:

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

Что означает кодирование строки в ФОРМАТЕ HTML? При кодировании строки в HTML опасные символы, такие как < и > , заменяются ссылками на сущности HTML, такие как &lt; и &gt;. Поэтому при кодировании строки <script>alert("Boo!")</script> в формате HTML она преобразуется в &lt;script&gt;alert(&quot;Boo!&quot;)&lt;/script&gt;. Закодированная строка больше не выполняется как скрипт JavaScript при интерпретации браузером. Вместо этого вы получите безвредную страницу на рис. 3.

Неудачная атака JavaScript

Рис. 03. Неудачная атака JavaScript (щелкните, чтобы просмотреть полноразмерное изображение)

Обратите внимание, что в представлении Index в листинге 3 кодируется только значение feedback.Message . Значение feedback.EntryDate не закодировано. Вам нужно только кодировать данные, введенные пользователем. Так как значение EntryDate было создано в контроллере, вам не нужно кодировать это значение в ФОРМАТЕ HTML.

Подход 2. Кодирование HTML в контроллере

Вместо кодирования данных HTML при отображении данных в представлении можно кодировать данные в ФОРМАТЕ HTML непосредственно перед отправкой данных в базу данных. Второй подход используется в случае с в листинге controller 4.

Листинг 4 . HomeController.cs (в кодировке HTML)

Public Class HomeController
     Inherits System.Web.Mvc.Controller

     Private db As New FeedbackDataContext()

     Function Index()
          Return View(db.Feedbacks)
     End Function

     Function Create(ByVal message As String)
          ' Add feedback
          Dim newFeedback As New Feedback()
          newFeedback.Message = Server.HtmlEncode(message)
          newFeedback.EntryDate = DateTime.Now
          db.Feedbacks.InsertOnSubmit(newFeedback)
          db.SubmitChanges()

          ' Redirect
          Return RedirectToAction("Index")
     End Function

End Class

Обратите внимание, что перед отправкой значения в базу данных в действии значение Message закодировано в Create() ФОРМАТЕ HTML. При повторном воспроизведении сообщения в представлении оно закодировано в ФОРМАТЕ HTML, а любой Код JavaScript, внедренный в сообщение, не выполняется.

Как правило, следует использовать первый подход, рассматриваемый в этом руководстве, а не этот второй подход. Проблема второго подхода заключается в том, что в базе данных в конечном итоге будут данные в кодировке HTML. Иными словами, данные вашей базы данных загрязняются смешными символами.

Почему это плохо? Если вам когда-либо потребуется отобразить данные базы данных не на веб-странице, у вас возникнут проблемы. Например, вы больше не можете легко отображать данные в приложении Windows Forms.

Итоги

Цель этого руководства — напугать вас перспективой атаки путем внедрения кода JavaScript. В этом руководстве рассматриваются два подхода к защите приложений ASP.NET MVC от атак путем внедрения кода JavaScript: вы можете кодировать данные, отправленные пользователем, в представлении в ФОРМАТЕ HTML, или кодировать данные, отправленные пользователем в контроллере.