Почему установка в window.location.href значения элемента хранилища сеанса считается уязвимостью DOM XSS?

Fortify SCA сообщает, что следующий код уязвим для DOM XSS:

const returnUrl = sessionStorage.getItem('returnUrl') || '/';
window.location.href = returnUrl;

Когда пользователь входит в мое приложение, например, щелкнув ссылку, и пользователь не вошел в систему:

  1. Приложение сохраняет window.location.href в returnUrl элемент в хранилище сеансов.
  2. Он устанавливает window.location.href на внешнюю страницу входа
  3. Когда пользователь вводит свои учетные данные, внешняя страница входа перенаправляется на logged-in.html страницу моего приложения.
  4. logged-in.html содержит приведенный выше код, устанавливающий window.location.href значение, хранящееся в returnUrl элементе хранилища сеанса.

Почему это уязвимо? Как я могу смягчить это?

Обновлено: Я не выполнял Fortify, это сделала внешняя компания и сообщила следующее:

КВЕ-80. Проверка ввода и Представление: Межсайтовый скриптинг: ДОМ

О какой конкретной ошибке сообщает Fortify SCA? Пожалуйста, используйте копирование и вставку, чтобы добавить его к вопросу (с > впереди, поэтому отметьте его как цитируемый).

T.J. Crowder 25.01.2023 09:19

Итак, что произойдет, если скрипт на странице сделает sessionStorage.setItem("returnUrl", "theattackerdomain.com")?

VLAZ 25.01.2023 09:22

@VLAZ, чтобы это было возможно, мое приложение должно быть успешно атаковано, чтобы внедрить этот код. Верно?

Jesús López 25.01.2023 09:25

Я не знаю, как работает ваше приложение. Возможно, вы используете внешние скрипты, которые уже уязвимы, поэтому для проявления атаки не требуется много времени. Или, кто знает, у вас может быть какая-то другая XSS-уязвимость. Или у вас его нет сейчас, но он может появиться в будущем — через 15 месяцев, когда вы бы забыли об этом отчете Fortify. В конце концов, так ли это важно? Ясно, что процесс уязвим для довольно простого вмешательства в приложение.

VLAZ 25.01.2023 09:29

@Т.Дж.Краудер. Я не запускал Fortify, это сделала внешняя компания и сообщила следующее: CWE-80. Проверка входных данных и представление: Межсайтовый скриптинг: DOM

Jesús López 25.01.2023 09:33

Вы не должны доверять никаким внешним данным, даже SessionStorage, данные могут быть подделаны перед их сохранением (также они могут быть подделаны при хранении на зараженном устройстве). Вот почему вы всегда должны проверять внешние данные перед использованием.

Teemu 25.01.2023 09:36

@ВЛАЗ. Это приложение Angular, оно загружает все скрипты с сервера веб-приложений, кроме logedd-in.html, который загружает alcdn.msauth.net/browser/2.22.1/js/msal-browser.min.js. Если кто-то может вводить sessionStorage.setItem("returnUrl", "theattackerdomain.com"), он может вводить и window.location.href = "theattackerdomain.com", так какой в ​​этом смысл?

Jesús López 25.01.2023 09:39

@Тему. Спасибо. Итак, вы предлагаете проверить значение returnUrl?. Я могу легко проверить домен и протокол, но проверить путь и строку запроса очень сложно, так как их много.

Jesús López 25.01.2023 09:43

@JesúsLópez ¯\_(ツ)_/¯ Ну, я думаю, просто не делайте никаких проверок, не принимайте никаких мер предосторожности, основанных на здравом смысле, и просто заново изобретите, как выполняется перенаправление после входа в систему. Возможно, вы нашли схему перенаправления, возможности которой не смогли реализовать все другие веб-приложения. Они, да и сама Fortify, наверное, ошибаются.

VLAZ 25.01.2023 09:44

Проверка протокола и домена уже будет большим подспорьем, так как посетитель не сможет перейти на сайт злоумышленника.

Teemu 25.01.2023 09:45

@ВЛАЗ. Я не изобретаю ничего нового. Получение returnUrl из хранилища сеансов — это именно то, что делает библиотека @azure/msal-browser от Microsoft. Мне просто нужно знать, почему это уязвимо и как его смягчить. не могу убрать эту функцию

Jesús López 25.01.2023 09:48

@Тему. Не могли бы вы сделать свои комментарии в качестве ответа? Что-то вроде: «Он уязвим, потому что sessionStorage не заслуживает доверия. Устройство может быть заражено, а sessionStorage может быть подделан».

Jesús López 25.01.2023 10:42

@JesúsLópez Это только часть истории. Было сложно найти объяснение этому в Fortify, мне удалось найти только этот исходник на Github. Как необработанный XML, его немного трудно читать, но есть полное объяснение этой конкретной ошибки аудита безопасности.

Teemu 25.01.2023 11:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
13
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как я могу смягчить это?

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

const returnInfo = JSON.parse(sessionStorage.getItem("returnUrl"));
if (returnInfo && validatePageName(returnInfo.pageName) && /*...*/) {
    window.location.href = "/" + returnInfo.pageName; // Or similar
}

... где validatePageName гарантирует, что переданная ему строка является просто именем страницы в вашем приложении, а не (например) полным URL-адресом.

Или, если это слишком большое изменение, по крайней мере, проверьте URL-адрес перед его использованием:

const returnUrl = new URL(
    sessionStorage.getItem("returnUrl") || "/"),
    location
);
if (
  returnUrl.protocol === location.protocol &&
  returnUrl.port === location.port &&
  returnUrl.hostname === location.hostname &&
  /*...other checks as necessary ...*/
) {
    window.location.href = returnUrl;
}

Другие вопросы по теме