在 SXSS 漏洞被利用之前识别并缓解它们
卢克·哈里森
本文最初发布在 IBM Developer 上。
当前许多应用程序需要在其网站上呈现 HTML 格式的富文本。为了根据用户输入生成这种格式化文本,开发人员使用富文本编辑器组件。问题?此功能可以间接使您的应用程序和数据面临称为存储跨站点脚本 (SXSS) 的漏洞。
在本文中,您将了解什么是 SXSS 漏洞,并回顾一些可用于检查您的应用程序是否受到影响的“代码味道”。您还将看到易受攻击的应用程序的示例,并了解此漏洞的修复策略。
什么是存储型跨站脚本?
存储的跨站点脚本是一种漏洞,攻击者可以利用它向数据库注入恶意代码。该代码在由前端框架获取并呈现后,在受害者的浏览器上运行。
此漏洞极其危险,因为它可以使攻击者窃取 cookie、触发重定向或在受害者的浏览器中运行各种危险脚本。攻击者只需很少的工作就可以传播漏洞:受害者不需要点击恶意链接或陷入网络钓鱼计划,他们只需使用受 SXSS 影响的可信站点即可。查看页面底部的链接,了解有关跨站脚本漏洞的更多详细信息。
代码味道:innerHTML和dangerouslySetInnerHTML
代码异味只是代码中指示更深层次问题的特征。浏览器通常不会自动运行注入的脚本,但如果开发人员使用一些潜在危险的浏览器 API 或元素属性,则可能会导致脚本 do 运行的情况。
看看下面的代码片段:
const someHTML = “<h1 id="Hello-world">Hello world</h1>“ const output = document.getElementById("rich-text-output"); output.innerHTML = someHTML
在此示例中,我们将一些 HTML 存储在变量中,从 DOM 中获取元素,并将该元素的 innerHTML 属性设置为存储在变量中的内容。 innerHTML 属性可用于从另一个 HTML 元素内的字符串呈现 HTML。
此属性的危险在于它会渲染您传递给它的任何 HTML 或 JavaScript。这意味着如果有人能够控制传递到属性中的数据,从技术上讲他们就可以在用户的浏览器中运行任何 JavaScript。
在浏览器中渲染动态 HTML 的另一种流行但危险的方法是使用危险的SetInnerHTML React 组件属性。此属性的行为方式与普通 JavaScript 和 HTML 中的innerHTML 属性完全相同。
以下示例出现在 React 文档中:
const someHTML = “<h1 id="Hello-world">Hello world</h1>“ const output = document.getElementById("rich-text-output"); output.innerHTML = someHTML
如果您当前在前端 Web 应用程序中使用这些属性中的任何一个,那么您很可能存在某种类型的跨站点脚本漏洞。我们将在本文后面介绍如何利用这些属性以及您可以采取的一些步骤来修复这些问题。
代码味道:富文本编辑器
您的应用程序可能容易受到 SXSS 攻击的另一个迹象是您是否使用富文本编辑器,例如 TinyMCE 或 CKEditor。
大多数富文本编辑器的工作原理是将用户生成的格式化文本转换为 HTML。作为一项附加的安全措施,许多编辑器采用某种形式的清理来从其输入中删除潜在的恶意 JavaScript。但是,如果您没有在接收和存储富文本内容的服务上应用这些相同的清理技术,那么您的应用程序很可能容易受到 SXSS 的攻击。
即使您没有在自己的网站上渲染内容,这些数据也很有可能被执行渲染的应用程序消耗。要设计安全的应用程序,考虑数据当前和未来的消费者非常重要。如果您的数据受到 SXSS 的影响,那么所有消耗您数据的应用程序也会受到影响。
具有 SXSS 漏洞的示例应用程序
让我们看一个带有 SXSS 漏洞的 Web 应用程序的小示例,然后尝试利用它。
要运行此应用程序,请首先克隆此演示应用程序存储库并按照 readme.md 文件中的“运行应用程序”说明进行操作。
运行应用程序并访问 http://localhost:3000/unsanitized.html 后,您应该看到如下所示的页面:
此应用程序只是从用户处获取一些富文本输入,将其存储在 Web 服务器上,然后将其呈现在标记为 Output 的部分中。
在我们利用 SXSS 漏洞之前,请花点时间看一下该应用程序。参考上面提到的代码味道,扫描一下代码,看看是否能发现有问题的部分。尝试在浏览器中打开网络选项卡,并查看当您输入并提交一些富文本时它发送的请求。
在 unsanitzed.html 文件中,您将看到以下函数,名为 renderPostByID:
const someHTML = “<h1 id="Hello-world">Hello world</h1>“ const output = document.getElementById("rich-text-output"); output.innerHTML = someHTML
仔细看这个函数。您会注意到,我们正在使用前面提到的innerHTML 属性来呈现我们从API 中以HTML 形式获取的一些富文本。
现在我们看到了代码中易受攻击的部分,让我们利用它。我们将绕过富文本编辑器输入并点击将帖子直接保存到 Web 服务器的 API 端点。为此,您可以使用以下 cURL 命令:
function createMarkup() { return {__html: 'First · Second'}; } function MyComponent() { return <div dangerouslysetinnerhtml="{createMarkup()}"></div>; }
注意我们在请求中发送的数据负载。这是一些恶意制作的 HTML,其中包含一个图像标记,该图像标记的 onerror 属性设置为某些显示警报对话框的 JavaScript。攻击者将使用这样的技巧来避免实施不当的清理方法,这些方法旨在在将 HTML 元素存储到数据库之前从 HTML 元素中剥离 JavaScript。
运行上面的脚本后,您应该会收到如下所示的帖子 ID:
const renderPostByID = async (id) => { // setting url seach params let newURL = window.location.protocol + "//" + window.location.host + window.location.pathname + `?post=${id}`; window.history.pushState({ path: newURL }, "", newURL); // getting rich text by post id let response = await fetch(`/unsanitized/${id}`, { method: "GET" }); let responseJSON = await response.json(); console.log(responseJSON); // rendering rich text output.innerHTML = responseJSON.richText; };
将此帖子 ID 粘贴到帖子 URL 查询参数中,然后按 Enter.
执行此操作时,您应该会在屏幕上看到一个警报对话框,确认该网站确实容易受到 SXSS 的攻击。
现在我们已经了解了如何
利用 SXSS 漏洞,让我们看看如何修复一个漏洞。为此,您需要在三个不同的位置清理基于 HTML 的富文本:
- 服务器端,在内容存储到数据库之前。
- 服务器端,从数据库检索内容时。
- 客户端,当内容由浏览器呈现时。
但请记住,向所有三个位置添加消毒可能会导致性能下降,因此您需要自行决定是否需要这种级别的安全性。至少,您应该在渲染动态 HTML 内容之前清理客户端上的所有数据。
让我们看看如何在易受攻击的应用程序的安全版本中实施清理。由于该应用程序主要使用 JavaScript 编写,因此我们在客户端使用 dompurify 库,在服务器端使用 isomorphic-dompurify 库进行清理。在充当我们的 Web 服务器的 app.js 程序中,您将找到一个带有 GET 和 POST 实现的快速端点 /sanitized:
const someHTML = “<h1 id="Hello-world">Hello world</h1>“ const output = document.getElementById("rich-text-output"); output.innerHTML = someHTML
在 POST 实现中,我们首先从请求正文中检索富文本,然后调用 isomorphic-dompurify 库的 sanitize 方法,然后将其存储在数据对象中。类似地,在 GET 实现中,我们在从数据对象检索富文本之后并将其发送给消费者之前对富文本调用相同的方法。
在客户端,我们在 sanitized.html 中设置输出 div 的innerHTML 属性之前再次使用相同的方法。
function createMarkup() { return {__html: 'First · Second'}; } function MyComponent() { return <div dangerouslysetinnerhtml="{createMarkup()}"></div>; }
现在您已经了解了我们如何正确清理 HTML 以防止跨站点脚本编写,请返回到此应用程序的原始漏洞并再次运行它,这次使用清理后的端点。您不应再看到弹出的警报对话框,因为我们现在正在使用适当的技术来防止 SXSS 漏洞。
有关完整的 SXSS 指南,包括防止 XSS 的最佳实践和其他技术,请查看 OWASP 跨站脚本备忘单。
摘要和后续步骤
在本文中,我们了解了如何通过防止存储的跨站点脚本(一种常见的 Web 应用程序漏洞)来提高应用程序的安全性。您现在应该能够识别自己的应用程序是否容易受到攻击、您需要检查哪些功能以及如何在恶意行为者利用这些漏洞之前进行缓解。
安全对于企业开发者来说至关重要。使用以下资源继续增强您对可能存在的漏洞以及改善安全状况的方法的认识。
- IBM Developer:安全中心
- OWASP 跨站脚本概述
- 视频:跨站脚本 — 25 年来仍然存在的威胁
以上是您的富文本可能是跨站点脚本漏洞的详细内容。更多信息请关注PHP中文网其他相关文章!

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Dreamweaver Mac版
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。