33

我认为不信任任何输入是网络上众所周知的最佳实践。这句话

“所有输入都是邪恶的。”

可能是关于输入验证的引用最多的引用。现在,对于 HTML,您可以使用诸如DOMPurify之类的工具对其进行清理。

我的问题是,如果我有一个运行 Express 和body-parser中间件来接收和解析 JSON 的 Node.js 服务器,我是否还需要运行任何清理程序?

我的(也许是天真的?)想法是 JSON 只是数据,没有代码,如果有人发送无效的 JSON,body-parser(JSON.parse()内部使用)无论如何都会失败,所以我知道我的应用程序将收到一个有效的 JavaScript 对象. 只要我不运行 eval 或调用函数,我应该没问题,不是吗?

我错过了什么吗?

4

2 回答 2

34

由于JSON.parse()不会在要解析的数据中运行任何代码,因此它并不容易受到攻击eval(),但是您仍然应该做一些事情来保护服务器和应用程序的完整性,例如:

  1. 在适当的地方应用异常处理程序JSON.parse()可以引发异常。
  2. 不要假设那里有什么数据,您必须在使用之前明确测试数据。
  3. 仅处理您专门寻找的属性(避免可能在 JSON 中的其他内容)。
  4. 将所有传入数据验证为合法、可接受的值。
  5. 清理数据长度(以防止数据过大导致 DOS 问题)。
  6. 不要将这些传入数据放在可以进一步评估的地方,例如直接放入页面的 HTML 或直接注入到 SQL 语句中,而无需进一步清理以确保它对于该环境是安全的。

因此,要直接回答您的问题,“是的”除了使用 body-parser 之外,还有更多工作要做,尽管它是第一次处理数据的完美前线。从 body-parser 获取数据后,下一步如何处理数据在许多情况下都很重要,并且可能需要格外小心。


例如,下面是一个解析函数,它需要一个具有应用其中一些检查的属性的对象,并为您提供仅包含您期望的属性的过滤结果:

// pass expected list of properties and optional maxLen
// returns obj or null
function safeJSONParse(str, propArray, maxLen) {
    var parsedObj, safeObj = {};
    try {
        if (maxLen && str.length > maxLen) {
            return null;
        } else {
            parsedObj = JSON.parse(str);
            if (typeof parsedObj !== "object" || Array.isArray(parsedObj)) {
                safeObj = parseObj;
            } else {
                // copy only expected properties to the safeObj
                propArray.forEach(function(prop) {
                    if (parsedObj.hasOwnProperty(prop)) {
                        safeObj[prop] = parseObj[prop];
                    }
                });
            }
            return safeObj;
        }
    } catch(e) {
        return null;
    }
}
于 2014-09-22T21:34:08.330 回答
10

你应该没事。JSON 的早期用户经常会调用eval()接收到的字符串,这当然是一个巨大的安全漏洞。但是JSON.parse,正如您所说,处理大多数此类健全性检查。

例如,只要确保不从接收到的 JSON 对象中取出某些内容并将其直接传递到 SQL 查询中,就可以了。

于 2014-09-22T21:10:09.760 回答