У меня есть следующий код:
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.
Майк, спасибо за понимание. Возможно, я неясно выразился, но в конце концов я делаю это именно так, потому что так сказал начальник. Я не первый раз сталкиваюсь с ситуацией, когда современные браузеры закрыли уязвимую дыру, и мне нужен метод, чтобы продемонстрировать эксплойт. К сожалению, этот код представляет собой значительно упрощенную версию того, что происходит. В лаборатории студентам предлагается ввести сценарий в текстовое поле, а затем сохранить его в базе данных. На другом экране введенный сценарий выполняется как часть отображаемого поля. Так что это должно работать.
Итак, возьмите пользовательские данные, а затем «как идиот» превратите их в DOM и внедрите их обычным способом, например. DOMParser.prototype.parseFromString. Вы всегда находитесь в JS, буквально нет необходимости пытаться принудительно использовать XSS «через React»: XSS не зависит от React.
Я нашел ответ на свой вопрос и публикую его здесь для тех, кто поддержит меня.
Короткий ответ: современные браузеры теперь отключают сценарии, исходящие от онлайн-пользователя. Никакие изменения Политики безопасности контента этого не изменят. Даже отключение 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>
С какой стати ты так поступаешь? Просто создайте обычный JSX-контент с useEffect, который вызывает оповещение. Нет смысла вставлять необработанный HTML для того, что вы показываете. Если вы хотите показать студентам, как обнаруживать XSS, по крайней мере, делайте это обычным способом: не пытайтесь вставить текст шаблона React на страницу, просто используйте обычный JS. Например.
const s = document.createElement("script"); s.textContent = "alert(document.cookie)"; document.head.appendChild(s);
.