Обеспечение безопасности Frontend приложений

bb636e6f4aabd6850eb0ae698057f218

Безопасность является важным фактором при создании frontend приложений, поскольку они часто являются отправной точкой для атак. Я решил собрать в одну статью основные меры, которых стоит придерживаться или о которых хотя бы нужно задуматься.

Следуя этим основным мерам безопасности, frontend приложения можно сделать более безопасными и менее уязвимыми для атак. Однако важно помнить, что безопасность — это непрерывный процесс, который должен постоянно контролироваться и улучшаться с течением времени. Меры могут быть комбинированы, а некоторые опущены и не использованы — это определяет контекст проекта. Контекст может не позволять заниматься некоторыми видами безопасности, однако настаивать на этом необходимо и полезно, так как это снижает не только технический уровень уязвимости, но и напрямую влияет на репутационные риски компании.

HTTPS

HTTPS расшифровывается как Hypertext Transfer Protocol Secure. Это протокол, используемый для шифрования данных, передаваемых через Интернет между клиентом (например, веб-браузером) и сервером. Протокол HTTPS использует комбинацию симметричного и асимметричного шифрования для обеспечения безопасной передачи данных и их невозможности перехвата или изменения неавторизованными сторонами.

Как HTTPS обеспечивает безопасность? (подробно и полезно)

Работает это примерно так. Когда клиент подключается к серверу по протоколу HTTPS, сервер отправляет клиенту свой сертификат SSL / TLS, который содержит открытый ключ, используемый для установления безопасного соединения. Затем клиент генерирует симметричный сеансовый ключ, который используется для шифрования и дешифрования данных, которыми обмениваются клиент и сервер во время сеанса.

Процесс шифрования данных включает в себя шифрование открытых текстовых (незашифрованных) данных с использованием определенного алгоритма и ключа. Полученные в результате зашифрованные данные могут быть расшифрованы только тем, у кого есть ключ. Ключ генерируется случайным образом в начале сеанса и используется только между клиентом и сервером. Это означает, что даже если злоумышленник перехватывает передаваемые данные, он не может их расшифровать, поскольку у него нет ключа для их расшифровки. В дополнение к шифрованию HTTPS также обеспечивает целостность данных, что означает, что данные не могут быть подделаны или изменены во время передачи.

Таким образом, протокол HTTPS шифрует данные, используя комбинацию симметричного и асимметричного шифрования, чтобы гарантировать, что данные передаются безопасно и что они не могут быть перехвачены или изменены неавторизованными сторонами. Это помогает защитить конфиденциальную информацию, такую как пароли, номера кредитных карт и личные данные, от перехвата злоумышленниками.

О каком перехвате идет речь?

Когда мы говорим о перехвате в контексте HTTPS, то имеем в виду перехват сетевых пакетов, которые передаются между клиентом (например, веб-браузером) и сервером через Интернет. Когда клиент подключается к серверу по незащищенному соединению (HTTP), данные, передаваемые между клиентом и сервером, отправляются в виде обычного текста, что означает, что они могут быть перехвачены и прочитаны любым, кто отслеживает сетевой трафик. Перехватить можно с помощью различных инструментов, таких как сетевые анализаторы (снифферы), которые захватывают и анализируют сетевые пакеты по мере их перемещения по сети.

Когда клиент подключается к серверу по защищенному соединению (HTTPS), данные, передаваемые между клиентом и сервером, шифруются, что означает, что они не могут быть прочитаны кем-либо, кто перехватывает сетевые пакеты. Это гарантирует, что конфиденциальная информация, такая как пароли, номера кредитных карт и личные данные, остается конфиденциальной и защищенной.

Проверка входных данных (валидация)

Проверка входных данных — это процесс проверки достоверности введенных пользователем данных перед их обработкой приложением. Целью проверки является предотвращение инъекционных атак, которые происходят, когда злоумышленник вставляет вредоносный код (например, SQL, JavaScript или HTML) в приложение, используя уязвимости в полях ввода.

Распространенные типы инъекционных атак

SQL-инъекция

Этот тип атаки возникает, когда злоумышленник вставляет SQL-код в поле ввода, которое используется для запроса к базе данных. Злоумышленник может использовать SQL-инъекцию для доступа к конфиденциальным данным или выполнения вредоносных команд в базе данных.

Допустим, в приложении есть панель поиска, которая позволяет пользователям искать продукты по названию. Приложение может создать SQL-запрос для поиска продуктов на основе поискового запроса, введенного пользователем. Однако, если приложение не выполняет надлежащую валидацию, злоумышленник может ввести SQL-код в строку поиска, который будет выполнен приложением. Например, злоумышленник может ввести следующий поисковый запрос: OR 1=1 --. Это может привести к тому, что SQL-запрос вернет все продукты в базе данных, независимо от поискового запроса, введенного пользователем.

Атака с использованием межсайтового скриптинга (XSS)

Этот тип атаки возникает, когда злоумышленник вводит вредоносный код JavaScript в поле ввода, которое отображается другим пользователям. Злоумышленник может использовать XSS для кражи конфиденциальных данных, таких как сеансовые файлы cookie, или для перенаправления пользователей на вредоносный веб-сайт.

Допустим, в приложении есть раздел, где пользователи могут оставлять комментарии. Приложение может отображать комментарии на веб-странице без надлежащей валидации данных. Злоумышленник может опубликовать комментарий, содержащий вредоносный код JavaScript, который будет выполнен другими пользователями, просматривающими этот комментарий. Например, злоумышленник может опубликовать следующий комментарий: . Это приведет к появлению окна предупреждения на экранах всех пользователей, просматривающих комментарий.

Кстати, на хабре есть прекрасная статья, раскрывающая эту тему очень широко. XSS атакует! Не краткий обзор где и как искать уязвимости

Внедрение команд (sh-команды)

Этот тип атаки происходит, когда злоумышленник вставляет вредоносные команды в поле ввода, которое используется для выполнения системных команд. Злоумышленник может использовать внедрение команд для выполнения произвольных действий на сервере. Чтобы обезопасить приложение от атак с использованием инъекций, проверка входных данных должна выполняться для всех полей ввода в приложении.

Допустим, в приложении есть функция, которая позволяет пользователям загружать файлы. Приложение может использовать системную команду для обработки загруженного файла без надлежащей валидации входных данных. Злоумышленник может загрузить файл, содержащий вредоносные команды, которые будут выполняться приложением. Например, злодей загрузит файл со следующим именем: ; rm -rf /. Это приведет к тому, что приложение выполнит rm -rf / и удалит все файлы на сервере.

В действительности, большинство сайтов и приложений обладают внутренней защитой, либо разработчики уже позаботились о том, чтобы обеспечить её. Поэтому подобные примеры вряд ли можно будет протестировать на большинстве сайтов. Иначе, уже в текущей статье, было бы возможно наблюдать всплывающее сообщение «You have been hacked!», в качестве XSS внедрения.

Виды проверок

Белый список

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

const usernameInput = document.getElementById('username');
 
usernameInput.addEventListener('input', function(event) {
  const regex = /^[a-zA-Z0-9]+$/;
  const input = event.target.value;
 
  if (!regex.test(input)) {
    // Показать ошибку ввода
    // Не дать отправить форму
  }
});

Черный список

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

const phoneInput = document.getElementById('phone');
 
phoneInput.addEventListener('input', function(event) {
  const blacklist = /['";<>]/;
  const input = event.target.value;
 
  if (blacklist.test(input)) {
    // Показать ошибку ввода
    // Не дать отправить форму
  }
});

Очистка

Удаление или кодирование любых потенциально вредоносных символов из входных данных перед их обработкой. Например, преобразование любых HTML-тегов в соответствующие им HTML-объекты.

const commentInput = document.getElementById('comment');
 
commentInput.addEventListener('input', function(event) {
  const input = event.target.value;
  const sanitizedInput = input.replace(//g, '>');
});

Достаточно ли этих проверок?

Определенно, нет. Все проверки и валидации, которые производятся на стороне frontend обходимы. Проверка и очистка на стороне клиента могут быть полезны для обеспечения немедленной обратной связи с пользователем и снижения нагрузки на сервер за счет обнаружения явно неверных входных данных до их отправки на серверную часть. Однако важно помнить, что любые меры безопасности, реализуемые исключительно на стороне клиента, могут быть обойдены мотивированным злоумышленником.

Чтобы обеспечить надежную защиту от атак с использованием инъекций, важно также выполнять двустороннюю валидацию — одна на frontend-стороне, вторая на сервере. Это гарантирует, что любой вредоносный ввод будет перехвачен и отклонен до того, как он может быть обработан и потенциально нанести ущерб приложению или его пользователям. Таким образом, проверку и очистку входных данных на стороне клиента следует рассматривать как дополнительный уровень безопасности, а не как единственное средство предотвращения инъекционных атак. Комбинация проверки и очистки на стороне клиента и сервера является наиболее эффективным способом защиты от инъекционных атак.

Аутентификация и авторизация

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

Слабые и предсказуемые пароли

Здесь важно убедиться, что действуют надежные рекомендации для создания паролей. Слабые или легко угадываемые пароли могут представлять серьезную угрозу безопасности, поскольку они могут быть легко скомпрометированы злоумышленниками. Этот вариант носит рекомендательный характер для пользователя, но также обязан быть валидирован с двух сторон — frontend и backend. Короче, всё, что здесь можно сделать — это предупредить пользователя, что его пароль не лучшего качества и вообще принадлежит другому пользователю.

Небезопасное хранение данных аутентификации

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

localStorage.setItem('sessionToken', token);

В этом примере токен аутентификации хранится в локальном хранилище браузера, которое не является безопасным механизмом хранения. Злоумышленник, получивший доступ к устройству пользователя, может легко получить доступ к этому токену и использовать его для получения несанкционированного доступа к учетной записи пользователя. Более безопасным подходом было бы хранить токены в cookie с флагами HttpOnly и secure. Хотя на хабре существует статья, рассказывающая, как использовать localStorage просто потому что это возможно

© Habrahabr.ru