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

Статья подготовлена по материалам внутреннего митапа по информационной безопасности.

Я работаю на проектах в финансовой сфере, где постоянно ужесточаются требования к безопасности. У меня есть возможность проходить различные курсы на эту тему, в том числе бесплатно (за счет работодателя). Когда анализирую полученную на них информацию, радуюсь, что работаю во фронтенде. 90% атак связаны именно с бэкендом - т.е. защиту можно обеспечить только настройкой на “той” стороне. Ребятам с бэка нужно знать очень много всего, поскольку споткнуться можно на каждом шаге.

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

Что такое OWASP или типы уязвимостей

Но начну я издалека - с источников информации об уязвимостях. Основной для меня - OWASP.

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

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

OWASP - Open Web Application Security Project (руководство - https://owasp.org/www-project-web-security-testing-guide/).

На самом деле сайт OWASP - огромная кладовая без дна. Туда достаточно нырнуть и остановиться уже невозможно. И чем дальше идешь, тем больше убеждаешься, что ничего не знаешь про безопасность. Кажется, что с изучением даже одной атаки не закончить.

Помимо OWASP можно обращать внимание на:

Лично мне OWASP кажется не очень удобным. Он не перерабатывается, а актуализируется через расширение - список только увеличивается, а отдельные элементы этого списка укрупняются. Например, XSS (Cross-Site Scripting) раньше был отдельным пунктом списка, а сейчас входит в более крупную категорию Injection. Однако штука эта популярная и на собеседованиях меня просили рассказать что-то именно на базе OWASP. А вот про другие проекты никогда не спрашивали.

О каких атаках надо помнить фронтенду

В этой статье поговорим про три на мой взгляд самые популярные атаки. Считайте это введением в тему.

XSS (Reflected, Persistent, DOM-based)

Атаки XSS подразумевают исполнение вредоносного кода браузером клиента. Самый распространенный вариант - Reflected XSS. Вот, как он выглядит:

Мы добавляем некий скрипт JavaScript в URL и отправляем в таком виде пользователю. Этот скрипт может отразиться от сервера и вернуться в таком же виде клиенту. Браузер будет считать, что код валиден, поскольку он вернулся с сервера, а значит исполнит его.

Reflected XSS - “одноразовая” уязвимость. Отправляя разным пользователям, код придется вставлять в URL каждый раз. Другой вариант - Persistent XSS. Атака реализуется, если удается засунуть вредоносный код в базу или иное хранилище на бэкенде. Далее база будет его отдавать всем пользователям по запросу. 

Отчасти эта атака затрагивает проблемы фильтрации на бэке. Но поговорите со своей командой бэкенда. Вопрос, г��е именно выявлять вставки кода, довольно холиварный. Технически скрипт спокойно может лежать в базе и ничего не сломает - основываясь на этой мысли, бэк может ждать фильтрации на стороне фронта.

Persistent XSS, пожалуй, самый распространенный вариант атаки, с которым все мы сталкивались. К примеру, дырявый сайт на самописной CMS предлагает вам оставить комментарий. В дополнение к комментарию вы пишите скрипт с отправкой cookie или редиректом пользователя на сайт, где нужны просмотры. Скрипт попадает в базу и все, кто видят этот комментарий, исполняют в своем браузере скрипт.

Лично я видел много алертов, выскакивающих при обнаружении Persistent XSS на каких-нибудь блогах. Таким образом ломали Twitter (https://hackerone.com/reports/485748) - тогда увели довольно много учеток. Да и сам я с различными вариантами XSS встречался на работе довольно часто.

Еще одна разновидность XSS - DOM-based XSS. Это одна из немногих уязвимостей, которая не связана с бэкендом (изменение на бэке никак не поможет).

Атака реализуется, когда фронт написан настолько криво, что изменение URL может выводиться в код на странице - например, если цену товара мы берем непосредственно из URL и вставляем в фильтр. Насколько я знаю, так давно никто не делает. Лично я сталкивался с такими решениями еще до выпуска из колледжа.

Идея атаки в том, чтобы вредоносным кодом, заложенным в URL, изменить DOM-дерево. Мы можем вставить скрипт, который редиректит пользователя куда-то или выполняет некий запрос. Получив возможность выполнять запросы на стороне жертвы, идей можно реализовать массу.

XSS хорошо фильтруется:

  • Можно фильтровать на бэке - все данные, которые поступают от клиента, можно проверять по определенной модели.

  • На фронте мы также можем фильтровать ввод при помощи того же DOMPurify, который перед любой вставкой или отображением чего-либо будет проверять данные и не допустит исполнения кода. Причем, фильтровать надо не только JS, но и HTML и CSS, поскольку вредоносные скрипты могут быть очень разные.

  • Важно обращать внимание на Content-type, который мы настраиваем. Браузеры могут по-разному реагировать на MIME тип. Если на бэке об этом не говорят явно, некоторые браузеры могут попытаться догадаться. И догадки не всегда работают так, как ты ожидаешь. Управлять догадками можно через x-content-type-options: nosniff (браузер не пытается гадать MIME).

  • Настройка заголовка CSP (Content Security Policy) - я читал, что все уязвимости смотрят, настроен ли у вас CSP.

С современными фреймворками типа React реализовать XSS сложнее. Чтобы запустить тот же скрипт, надо указывать специальный атрибут и случайно этого не сделаешь. В этом смысле с React все стало проще. Проблема в том, что иногда этот атрибут указывают, чтобы просто немного поиграть стилями, не особо вдаваясь в редактирование. Так что надо помнить, что подобный костыль может выйти боком.

CSRF (подделка запросов)

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

В отличие от XSS лично я такие атаки не встречал и не знаю, насколько CSRF распространены. Но защищаться надо. Простые способы:

  • Использовать CSRF токены. Это кусочки информации, которые присылает бэк. Раньше это было супер-легко. Условный Laravel сам создавал форму, подставлял к ней определенный параметр и бэк всегда знал, что эта форма была сгенерирована им. Сейчас, когда фронт и бэк - отдельные миры, приходится вставлять токены в запросы, которые делает React.

  • SameSite cookies (lax, strict) - настройка кук, с помощью которой мы можем лимитировать хосты, с которых и на которые эти куки могут отправляться. Можно потребовать отправку только с одного домена или поддомена.

  • Валидация Origin в запросах от фронта на стороне бэка.

Clickjacking (UI-Redressing)

На мой взгляд, это самая интересная штука, которую до сих пор можно встретить на каких-нибудь торрентах третьего эшелона. Пользователя заманивают на некий сайт и над функциональной кнопкой (например, кнопкой поиска) делают прозрачный iFrame, который вытаскивается наверх с помощью z-индекса. В iFrame можно сделать какой-нибудь лайк или дизлайк на Facebook. Думая, что нажимает на функциональную кнопку, пользователь будет ставить этот невидимый лайк от своего имени.

В свое время таким образом был взломан Facebook. 

Как от этого защититься:

  • x-frame-options (deny, sameorigin, allow-from) - можно ограничить открытие приложения только нашим хостом или списком доверенных хостов, чтобы на любых других доменах в iFrame просто ничего не открылось.

  • samesite в cookie тоже поможет.

Что на проектах делаем мы

  • Используем статический анализатор кода, который запускается прямо во время merge request и ищет типовые ошибки в конфигурации, потенциально приводящие к проблемам. Он размечает минорные и критические уязвимости, при этом с последними код не пропускают в прод. Такие инструменты особенно полезны, если, допустим, у вас open source проект, где кто угодно может подложить закладку (хороший пример - https://thecode.media/backdoors-to-php/). В маленьких командах их двух-трех человек, где хватает ресурсов следить за чистотой кода друг друга, это менее критично.

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

  • Тестируем результат.

Полезные ссылки 

  • OWASP Cheat Sheet (https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html) - список рекомендаций по каждой уязвимости, можно искать по функционалу приложения. Здесь по пунктам расписано, что можно сделать для защиты.

  • CWE (Common Weakness Enumeration, https://cwe.mitre.org/data/index.html) - это разработанный сообществом список типов слабых или уязвимых мест программного и аппаратного обеспечения. Можно автоматически проверять образ на возможные уязвимости из этого списка.

  • https://portswigger.net/ (burp suite) - здесь можно пройти ряд практических работ. Платная версия заточена скорее на специалистов по безопасности, но бесплатная тоже помогает больше понять про взломы рядовому разработчику. 

Автор: Сергей Широковских, Максилект.

P.S. Мы публикуем наши статьи на нескольких площадках Рунета. Подписывайтесь на нашу страницу в VK или на Telegram-канал, чтобы узнавать обо всех публикациях и других новостях компании Maxilect.