Skip to content

Latest commit

 

History

History
67 lines (42 loc) · 5.31 KB

File metadata and controls

67 lines (42 loc) · 5.31 KB

4.3 Межсайтовый скриптинг

Для совершенствования взаимодействия с пользователем современные сайты содержат все больше динамического контента, что означает, что мы должны предоставлять информацию динамически в зависимости от поведения каждого пользователя. К сожалению, существует такое явление как "межсайтовый скриптинг" (известный как "XSS"), с помощью которого осуществляются постоянные атаки на динамические сайты, в то время как сайты со статическим содержимым этим атакам не подвержены.

Злоумышленники посылают на сайты, подверженные межсайтовому скриптингу, скрипты на JavaScript, VBScript, ActiveX или Flash. Если скрипт удачно вторгся на сайт, пользовательская информация может быть похищена, а сайт наполнен спамом. Злоумышленники могут также изменить настройки пользователя на те, которые захотят.

Если Вы хотите предотвратить этот тип атаки, Вам нужно комбинировать два следующих подхода:

  • Проверка всех данных, идущих от пользователя, о чем мы поговорили в предыдущей главе.
  • Обработка всех данных, посылаемых клиенту, для того, чтобы предотвратить запуск опасных скриптов в браузере.

Итак, как нам осуществить эти два пункта в Go? К счастью, пакет html/template имеет в своем распоряжении несколько полезных функций, чтобы обезопасить данные:

  • func HTMLEscape(w io.Writer, b []byte) отправляет в w версию b с заменой потенциально опасных символов на их escape-последовательности.
  • func HTMLEscapeString(s string) string возвращает версию s с заменой потенциально опасных символов на их escape-последовательности.
  • func HTMLEscaper(args ...interface{}) string формирует строку из множества аргументов с заменой потенциально опасных символов на escape-последовательности.

Давайте изменим пример из раздела 4.1:

fmt.Println("Имя пользователя:", template.HTMLEscapeString(r.Form.Get("username"))) // печатает на стороне сервера
fmt.Println("Пароль:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // отправляет клиенту

Если кто-то попробует ввести в поле для ввода имени пользователя <script>alert()</script>, мы увидим следующую картину в браузере:

Рисунок 4.3 JavaScript после обработки escape-последовательностью

Функции пакета html/template помогут Вам заменить все теги HTML на их безопасные аналоги. Но что, если Вам нужно передать в браузер <script>alert()</script>? В этом случае нужно использовать пакет text/template:

import "text/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Привет, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('Вы попались!')</script>")

Вывод:

Привет, <script>alert('Вы попались!')</script>!

Или можно использовать тип template.HTML. Содержимое переменной типа template.HTML не изменяется с учетом escape-последовательностей:

import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Привет, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", template.HTML("<script>alert('Вы попались!')</script>"))

Вывод:

Привет, <script>alert('Вы попались!')</script>!

Еще один пример эскейпинга:

import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Привет, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('Вы попались!')</script>")

Вывод:

Привет, &lt;script&gt;alert(&#39;Вы попались!&#39;)&lt;/script&gt;!

Ссылки