This commit is contained in:
Slava Zgordan
2015-09-28 12:11:47 +02:00
parent e9dc2f8db7
commit bcf9adf155

68
ru/04.3.md Normal file
View File

@@ -0,0 +1,68 @@
# 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>`, мы увидим следующую картину в браузере:
![](images/4.3.escape.png?raw=true)
Рисунок 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;!
## Ссылки
- [Содержание](preface.md)
- Предыдущий раздел: [Проверка введенных данных](04.2.md)
- Следующий раздел: [Дублирование отправки](04.4.md)