在 NodeJS 中,确保用户在(文本输入)表单中提交的数据不是恶意的好方法是什么?

信息安全 xss sql注入 节点.js
2021-08-25 07:12:39

除了扫描用户上传的文件外,我还想确保用户个人资料、评论等表单不会被滥用来提交恶意脚本。有哪些已知的好方法?检查脚本注入攻击(XSS 和 SQLi)应该在客户端还是服务器端进行?

我检查了 NPM 中的一些与安全相关的模块,但它们似乎主要关注其他模块的安全性,并且可能我错过了一些有用的东西。

我知道的一种方法是去除所有 HTML 标签,但我认为它有点笨拙,而且可能并非在所有情况下都有效。

4个回答

去除 HTML 标签并不足以保护自己免受 XSS 攻击。考虑以下输入:

<scri<script>pt>

如果去掉<script>标签,就会创建另一个脚本标签。这只是一个例子——还有许多其他的攻击可以使用。

您应该考虑在服务器端保护自己免受 XSS 的侵害——这样用户就无法修改/绕过您的客户端代码。

保护自己免受 XSS 攻击是完全可行的,但您应该确保使用正确的方法。像往常一样, OWASP关于如何保护自己的说明可能是最好的方法。

SQL

防止 SQL 注入是使用准备好的语句完成的。一般来说,最好的做法是避免在 SQL 语句中手动连接用户生成的字符串。

而是使用?注释并将输入字符串作为参数提供。驱动程序确保阻止任何 SQL 注入尝试以及意外的用户输入。

MySQL 示例 -

PreparedStatement ps = connection.prepareStatement("INSERT INTO tbl VALUES (?)");
ps.setString(1, "'abc'); TRAUNCATE TABLE users; SELECT (1");
ps.executeUpdate();

注入尝试将失败。

跨站脚本

您可以 HTML 转义用户生成的字符串,或者只是在将其发送到客户端或将其写入数据库时替换<&gt;和。>&lt;

此外,请查看跨站点请求伪造 (CSRF) 预防备忘单指南。

在处理用户输入时,通常会讨论两种主要方法。这两种方法是验证消毒

这两个都应该在服务器端完成。客户端保护不会阻止跨站点脚本或 SQL 注入等攻击。

特别是,我认为您正在谈论跨站点脚本攻击。看来这个节点模块(https://github.com/theSmaw/Caja-HTML-Sanitizer)可能适合您想要实现的目标。

去除所有 HTML 标签不一定是个好主意。这是因为基于事件的跨站点脚本仍然是可能的。例如:

<a href="/yourprofilename">yourprofilename</a>

如果用户能够更改yourprofilename部分,请考虑以下输入:

" onfocus="prompt(document.location); autofocus"

这会将链接变成这样:

<a href="/" onfocus="prompt(document.location);" autofocus">yourprofilename</a>

这将在不使用 HTML 标记的情况下触发跨站点脚本。

现在许多答案都涉及未维护的软件包。Caja浏览器端似乎已被半废弃,其节点端口 ( node-google-caja) 正式未维护。express-validator很好,但是您必须做大量繁重的工作(即弄清楚您要执行哪种类型的消毒需要进行安全研究)。

上面的答案似乎建议推出你自己的,但需要大量的研究,所以也许试试DOMPurify这是积极维护的(在撰写本文时 1 小时前更新),它有 60 个贡献者并得到广泛支持。

对于 SQL 注入,我建议使用knexwhich 自动转义您的 SQL。此外,如果您可以选择限制输入,以便善意的用户无需思考,那么您应该能够更简单地验证您的数据。理想情况下,您的输入的目的应该集中,这样您就不会冒着您的消毒弄乱用户内容的风险。

在浏览器上进行清理,以便您可以显示预览内容,然后也在服务器端对其进行清理。