ОпасноSetInnerHTML не работает с <script>

У меня есть следующий код:

const Show = () => {
  const dangerousMarkup = { __html: "<script>alert('ERROR');</script>" };
  return (
             div dangerouslySetInnerHTML = {dangerousMarkup} />
            <div>
              <div>
                The length of dangerousMarkup is: {dangerousMarkup.__html.length}
                <br />
                The instructions are: {dangerousMarkup.__html }
              </div>
            </div>
    )

Предупреждение не отображается, но текст есть. На экране я увижу следующее:

The length of dangerousMarkup is: 32
The instructions are: <script>alert('ERROR');</script>

Я тестировал это на Firefox, Chrome и Edge — все с одинаковыми результатами. Мне нужно, чтобы XSS работал.

Прежде чем кто-нибудь скажет: «Это опасно» или «не делайте этого», я провожу лабораторное упражнение, чтобы научить студентов обнаруживать воздействие XSS. Этот код будет работать только в контролируемой лабораторной среде.

Я попытался запустить этот код с const dangerousMarkup = { __html: "<p>some raw html</p>" }; в качестве HTML, и это работает, как и ожидалось, с появлением «необработанного HTML» в браузере.

Я также просмотрел документацию.

Я установилОтключить политику безопасности контента в своем браузере Chrome из магазина Chrome.

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

С какой стати ты так поступаешь? Просто создайте обычный JSX-контент с useEffect, который вызывает оповещение. Нет смысла вставлять необработанный HTML для того, что вы показываете. Если вы хотите показать студентам, как обнаруживать XSS, по крайней мере, делайте это обычным способом: не пытайтесь вставить текст шаблона React на страницу, просто используйте обычный JS. Например. const s = document.createElement("script"); s.textContent = "alert(document.cookie)"; document.head.appendChild(s);.

Mike 'Pomax' Kamermans 28.06.2024 19:35

Майк, спасибо за понимание. Возможно, я неясно выразился, но в конце концов я делаю это именно так, потому что так сказал начальник. Я не первый раз сталкиваюсь с ситуацией, когда современные браузеры закрыли уязвимую дыру, и мне нужен метод, чтобы продемонстрировать эксплойт. К сожалению, этот код представляет собой значительно упрощенную версию того, что происходит. В лаборатории студентам предлагается ввести сценарий в текстовое поле, а затем сохранить его в базе данных. На другом экране введенный сценарий выполняется как часть отображаемого поля. Так что это должно работать.

Howard 28.06.2024 22:27

Итак, возьмите пользовательские данные, а затем «как идиот» превратите их в DOM и внедрите их обычным способом, например. DOMParser.prototype.parseFromString. Вы всегда находитесь в JS, буквально нет необходимости пытаться принудительно использовать XSS «через React»: XSS не зависит от React.

Mike 'Pomax' Kamermans 28.06.2024 22:47
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
3
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

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

Но есть обходной путь. Вы можете создать чистый HTML-файл и поместить его в общедоступный каталог. Затем ваш компонент React вызовет HTML-файл с параметрами. В своем приложении я поместил HTML-файл в рамку. HTML-файл должен запускать код специально для тега и использовать eval(script), чтобы запустить скрипт.

Напоминаю, это крайне опасно!

Код из компонента реагирования, который создает фрейм:

<iframe
      src = {`/ShowSpecial.html?content=${encodeURIComponent(
        Instructions  
      )}`}
      width = "100%"
      height = "500px"
      title = "Show Special"
    ></iframe>

Вот HTML-файл:

<!-- public/ShowSpecial.html -->
<!DOCTYPE html>
<html lang = "en">
  <head>
    <meta charset = "UTF-8" />
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0" />
    <title>Show Special</title>
  </head>
  <body>
    <div id = "special-content">Loading...</div>

    <script>
      // Function to get URL parameters
      function getUrlParameter(name) {
        name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
        var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
        var results = regex.exec(location.search);
        return results === null
          ? ""
          : decodeURIComponent(results[1].replace(/\+/g, " "));
      }

      // Get the special content from URL parameter
      var specialContent = getUrlParameter("content");

      // Display the special content (dangerous)
      document.getElementById("special-content").innerHTML = specialContent;

      // Execute the script (dangerous)
      if (specialContent.includes("<script>")) {
        specialContent = specialContent.replace(/</?script[^>]*>/gi, '');
        // Execute the script (dangerous)
        try {
          eval(specialContent);
        } catch (e) {
          console.error("Error executing script:", e);
        }
      }
    </script>
  </body>
</html>

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