每个 Java 软件架构师都应该知道的 20 件事
Vue XML 外部 实体(XXE)指南:示例和预防
在本文中,我们将讨论 Vue XML 外部实体注入这一主题。我们的目标是为您提供坚实的基础,以了解和缓解 Vue 和 NodeJS 中的 XML 外部实体注入漏洞。此外,我们希望帮助您准备在项目中实施解决方案。
值得注意的是,我们将为 NodeJS 提供缓解策略,因为大部分漏洞都位于应用程序的后端。
我们首先解释一下 XML 是什么。然后,我们将为您提供一些 XML 外部实体注入漏洞和利用的基本示例。最后,我们将为您提供一些策略和机制,以防止这种利用影响您的应用程序。
不言而喻,如果您没有使用过 Vue,那么本文可能不适合您。如果您只是想知道什么是 XML 外部实体注入,我们建议您在此处阅读我们关于它的深入文章。此外,如果您只是想了解 Vue 的基础知识,您可能需要在这里花一些时间。
解释 XML
XML(可扩展标记语言)是一种用于存储、传输和重建数据的标记语言。该语言定义了以人可读和机器可读格式对文档进行编码的规则。
但是等一下——为什么标记语言会对您的系统构成威胁?
事实上,我们到处都使用这种语言来以方便且易于理解的方式处理数据。此外,大多数使用的 XML 处理工具都允许指定所谓的外部实体。
这个实体通常是 URI,在解析 XML 文件时被检索和处理。这会促使解析器请求并包含 XML 文档中的内容。而且,正如您可能已经猜到的那样,这是一个麻烦的窗口。
XML 外部实体注入(也称为 XXE 注入)是针对 XML 解析漏洞的攻击。而且,鉴于大多数使用面向用户的 XML 解析功能的系统都存在潜在漏洞,它们可能允许恶意行为者访问服务器上的文件和资源。
鉴于一个执意不法之徒可能会利用此实体作为获取服务器中任何资源的途径,此漏洞可能会对我们的安全造成毁灭性的影响。我们所需要的只是充分了解服务器结构和所用技术堆栈的信息。
XML 外部实体注入漏洞示例
XXE 注入带来的最大威胁是它的简单性。
大多数开发人员都无法发现危险代码。许多人甚至根本看不到危险,即使危险就在他们面前。
因此,为了防止这种情况,让我们看一些常见的例子。
该 XML 文档仅包含一个用户名元素。
<?xml version="1.0" encoding="ISO-8859-1"?>
<username>Michael</username>
</xml>
这里没什么可怕的,对吧?好吧,我们还没有添加任何外部实体。
好的,我们如何添加外部实体?
简单。外部实体是使用 DOCTYPE 标头内的系统标识符的简单 XML 标签。
此标头的工作原理是向 XML 文件结构本身添加更多属性。例如,这可能是一个引用另一个包含其他数据的 XML 文件的 URL — 没什么复杂的。
但是如果我们利用这个特性来检索一些不该检索的东西会怎么样呢?例如,以下包含外部 XML 实体的代码将获取 /privates.txt 的内容并显示它。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///privates.txt" >]>
<username>&xxe;</username>
</xml>
哎呀。
很明显,这是一个潜在的灾难性漏洞,因为这些实体可以访问我们服务器内的本地或远程内容。
如果你错误地将敏感文件保存在服务器上,那么情况就尤其糟糕。从本质上讲,这最终会为恶意收购你的整个平台提供途径。
顺便说一句,XML 外部实体注入攻击还可以访问可能循环返回数据的本地资源,从而影响应用程序的可用性并导致一种拒绝服务攻击。
现在,如果您留意的话,这时您应该感到恐慌并开始提倡完全禁用 XML 文件处理。
但不要这么急。我们仍然可以采取一些措施来缓解此漏洞的影响。
缓解 XML 外部实体注入漏洞
现在您已经稍微冷静了一点,让我们来探索如何防止您的系统成为这些攻击的受害者,以便您可以保住您的工作。
首先,减轻 XXE 注入攻击实际上非常简单 – 抱歉,我散布了恐慌。
假设您需要加载用户提供的 XML 文件的功能,只要您没有故意尝试打开后门以供攻击,大多数库都可以很好地保护您的应用程序。
防止此漏洞的一般方法是不使用支持实体替换的库,如 LibXML。并且,如果必须,请完全禁用该功能。
编写代码
现在,这主要涉及应用程序的后端。在我们的例子中,这是 NodeJS,但如果您出于任何特定目的在前端解析 XML,请避免使用支持实体替换的库。
正如我们在有关该主题的 NodeJS 文章中提到的那样,“遗憾的是,NodeJS 没有内置的 XML 解析引擎,因此,您可能已经在项目中使用了这个库。但不用担心;默认情况下实体替换是禁用的。”
尽管如此,我们建议您在项目中明确禁用此功能。
您可以通过简单地更改库的所有初始化来实现这一点,就像这样。
const lib = libxmljs.parseXml(xml, {noent: true});
幸运的是,最新版本的 LibXML 使得故意替换实体变得困难。不过,我们希望您知道,无论您采用哪种方法,以这种方式使用 LibXML 时,您仍然可能容易受到 DoS 攻击。
现在,如果您确实需要此功能,您仍然可以通过将您允许的外部实体列入安全列表来最大限度地减少漏洞的可能性。
app.post('/load_xml', upload.single('xml'), async function (req, res) {
if (!req.file) {
res.sendStatus(500); return;
}
try {
const xml = req.file.buffer; const doc = libxmljs.parseXml(xml, {noent: true});
if (doc.text().includes("<!ENTITY")) {
throw new Error("INVALID XML FILE");
}
res.send(doc.text());
} catch (err) {
res.send(err.toString()); res.sendStatus(500);
}
});
在使用我们的库解析 XML 文档之前,只需检查其中是否有包含我们列表中没有的“ENTITY”的字符串,我们就可以为应用程序提供最低级别的安全性。
万无一失的解决方案
我最后要告诉你们的是,最好的安全方法就是首先不要打开门。
除非应用程序需要,否则不要解析 XML。尽管解析 XML 可能会带来便利,但还有许多方法可以提供等效功能,而不会暴露这些漏洞。
下一步是什么?
毋庸置疑,保护我们的平台免受不良行为者的攻击需要对所使用的技术和基础设施有广泛的了解。
然而,如果你负责管理一个高效的团队,肩负重任,压力重重,那么尽最大努力为他们提供工具和机制,让他们发挥出最佳水平就至关重要。这不是一件容易的事。
幸运的是,我们已经为您开发出了理想的解决方案。
我们的动态应用程序安全测试解决方案是一种出色且功能强大的解决方案,它使团队能够专注于在网络上提供最佳解决方案,同时保护您的用户。
文章来源:Vue XML External Entities (XXE) Guide: Examples and Prevention