gpt4 book ai didi

javascript - 将 HTML 插入用户字符串并在 React 中渲染(并避免 XSS 威胁)

转载 作者:行者123 更新时间:2023-12-03 13:34:36 26 4
gpt4 key购买 nike

用户正在向我们的 React 应用程序提供一个字符串,并且它正在显示给其他用户。我想搜索一些字符,并用一些 HTML 替换它们,就像我要搜索“特殊”这个词一样,我会将其变成:

My <span class="special-formatting">special</span> word in a user string

之前我执行此替换,然后使用angerlySetInnerHTML 将结果插入到DOM 中。这当然给我带来了一个问题,即用户能够直接在应用程序中输入他们喜欢的任何 HTML/Javascript 并将其呈现给每个人都可以看到。

我尝试将 HTML 字符转义为其实体,但危险的SetInnerHTML 似乎正确渲染了 HTML 实体,而不是实际的字符串。 (编辑:见下文,这是实际的解决方案)

有没有办法将他们的消息转换为纯字符串,仍然保留这些特殊字符的显示,但也将我自己的 HTML 插入到字符串中?尝试避免在将每个字符串插入 DOM 后运行脚本。

<小时/>

以下是有关当前流程的更多信息。所有示例都经过相当优化,仅显示相关代码。

使用此函数将用户文本提交到数据库:

handleSubmit(event) {
event.preventDefault();

var messageText = this.state.messageValue;

//bold font is missing some common characters, fake way of making the normal font look bold
if (this.state.bold == true) {
messageText = messageText.replace(/\'/g, "<span class='bold-apostrophe'>'</span>");
messageText = messageText.replace(/\"/g, "<span class='bold-quote'>&quot;</span>");
messageText = messageText.replace(/\?/g, "<span class='bold-question'>?</span>");
messageText = messageText.replace(/\*/g, "<span class='bold-asterisk'>*</span>");
messageText = messageText.replace(/\+/g, "<span class='bold-plus'>+</span>");
messageText = messageText.replace(/\./g, "<span class='bold-period'>.</span>");
messageText = messageText.replace(/\,/g, "<span class='bold-comma'>,</span>");
}

Messages.insert({
text: messageText,
createdAt: new Date(),
userId: user._id,
bold: this.state.bold,
});

}

因此,我的替换没有出现任何问题,但是此时,messageText 字符串仍可能包含不需要的用户输入 HTML 代码。

然后,我们的带有消息列表的主应用程序尝试呈现所有用户消息:

render() {
return (
<div ref="messagesList">
{this.renderMessages()}
</div>
);
}
renderMessages() {
return [].concat(this.props.messages).reverse().map((message) => {
return <Message
key={message._id}
message={message} />;
}
});
}

在 Message.jsx 中,我对消息字符串进行最后的修改(我不想将某些更改保存到消息数据库中)并将其插入要返回的元素中:

export default class Message extends React.Component {
render() {

var processedMessageText = this.props.message.text;

//another find and replace to insert images for :image_name: strings, similar to how Discord inputs its emoji
processedMessageText = processedMessageText.replace(/:([\w]+):/g, function (text) {
text = text.replace(/:/g, "");
if (text.indexOf("_s") !== -1) {
text = text.replace(/_s/g, "");
text = "<img class='small-smiley' src='/smileys/small/" + text + ".png'>";
return text;
}
else {
text = "<img class='smiley' src='/smileys/" + text + ".png'>";
return text;
}
});

return (
<div>
<div className='username'>{this.props.message.username}: </div>
<div className='text' dangerouslySetInnerHTML={{ __html: processedMessageText }}></div>
</div>
);
}
}

同样,如果用户在输入字符串中包含恶意 HTML,它将遍历所有这些并将输出输出到消息列表,这非常糟糕。我希望有某种方法可以将这些所需的 HTML 插入到他们的字符串中,同时也不将他们可能输入的 HTML 呈现为实际的 HTML。我还想显示 HTML 中常用的字符,例如尖括号 (<>),因此我想避免彻底删除输入字符串中的常见 HTML 字符。

<小时/>

由于接受的答案没有太多细节,我将在这里发布我最终所做的事情。我对 OWASP 建议的字符进行 HTML 编码在添加我自己的 HTML 并将其呈现为 HTML 元素的内容之前。我想避免使用另一个库,所以我这样做了:

messageText = messageText.replace(/\&/g, "&amp;");
messageText = messageText.replace(/</g, "&lt;");
messageText = messageText.replace(/>/g, "&gt;");
messageText = messageText.replace(/\//g, "&#x2F;");
messageText = messageText.replace(/\'/g, "&#x27;");
messageText = messageText.replace(/\"/g, "&quot;");

这样做后,我无法再插入任何恶意内容,并且使用 OWASP 中的各种测试字符串进行测试,没有出现任何问题。

最佳答案

当您在将用户的输入文本保存到数据库之前将 HTML 注入(inject)其中时,问题就出现了。这让事情变得很困难,因为现在你必须对其进行 sanitizer ,但不需要那么多。

作为补救措施,您可以使用 dompurifysanitize-html删除除您注入(inject)的 html 之外的任何 html。这是使用 dompurify 的示例:

import DOMPurify from "dompurify";

const dangerousString =
"<img onError='alert(\"h4ck3r\")' src='will throw error' /><span class='bold-apostrophe'>'</span>";

<div
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(dangerousString, {
ALLOWED_TAGS: ["span"],
ALLOWED_ATTR: ["class"]
})
}}
/>
  • 请记住 sanitizer libs needs to be updated as frequently as possible ,因为黑客不断寻找创造性的方法来绕过它们。
  • 前面的声明暗示您仍然可能受到 XSS 攻击。避免这种情况的唯一方法是在将字符串保存到数据库之前停止使用 HTML 调整字符串,因此您可以使用类似于 Ferrybig 提出的解决方案,用于动态添加特殊格式,而不是 dangerouslySetInnerHTML

关于javascript - 将 HTML 插入用户字符串并在 React 中渲染(并避免 XSS 威胁),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58479405/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com