在 nodejs 中保护自己免受 sql 注入的最佳方法

The best way to secure yourself against sql injection in nodejs

这是设置。

我正在使用 ajax 发送一个 POST,我将程序的参数发送到 nodejs 服务器。在这种特殊情况下,用户名和代码。

此 POST 调用 request.get 到 Web 服务,该服务执行使用这两个参数的过程。

例如

app.post('url/:username/:code', function(req,res,next){

 var procedure = 'EXECUTE procedureName'+req.params.code;

  request.get('myWslink/myService.asmx/service?
  callback=&userName='+req.params.username+'&procedureName='+procedure, function(){});
});

前端用户看不到我的网络服务 url、我的 request.get url 或我的程序名称,但他仍然可以看到正在发送的参数(用户名、代码) 他可以更改这些参数,使他能够执行他不应该执行的程序。

如果是插入过程,他也可以多次调用 POST 请求并用一堆垃圾填满数据库。

保护自己免受这些攻击的最佳方法是什么?

为了防止 sql 注入,您可以转义网络服务上的输入数据。 并且为了避免在数据库中出现多个虚假条目,您可以为每个 post 请求添加一个唯一的令牌,并在您的网络服务上验证该令牌,如果令牌合法则允许插入,否则避免插入。 你正在使用网络服务,据我所知你必须将这些令牌保存在数据库中以进行验证。

这里有几点建议:

不要进行这种程度的元编程。为每个程序在您的应用程序上创建单独的路由,然后自己注入那些 'codes'。这将允许您执行一些操作,例如验证用户输入以确保传入的不是垃圾数据,以及对特定路由进行速率限制以确保数据库中没有填满垃圾。

您还可以创建允许 'codes' 的白名单数组,并确保 whitelist.instanceOf(procedure) != -1 但这不会让您进行每个路由的输入验证。

即使您手动包含该过程,仍然存在问题。在您现有的代码中,对外部服务的调用将 'req.params.username' 参数放在 procedureName 之前。对于大多数 HTTP 解析框架来说,参数是先到先得。看到这段代码后,我首先尝试的攻击之一就是注入 '&procedureName=something_i_shouldnt_be_able_to_call' 进入我的用户名。这将导致您包含的 procedureName 属性被忽略,而我提交的属性将被使用。您可以通过将基于用户输入的参数放在最后并在字符串插值之前对用户输入进行 URI 编码,或者通过将查询字符串包含为名为 'qs' passed into the options argument to request.

的对象来防止这种情况

这是否会造成 SQL 注入漏洞完全取决于 Web 服务如何解析参数和执行过程。最佳情况是服务 URI 解码每个参数,然后将它们作为参数传递给 PDO 或准备好的语句。考虑到它的调用方式,我的猜测是它正在使用 PDO。

所以我在这里最终建议的是对每个用户输入提供的参数进行 URI 编码,并使用如上所述传递到请求选项中的 qs 对象,而不仅仅是插入字符串。完成后,您可以采取任何或所有这些步骤来帮助验证:

  1. 尝试手动将单引号插入用户输入。
  2. 运行 在该特定路径上使用像 sqlmap 这样的工具来测试 SQL 注入。这将为您提供相当可靠的测试,而无需深入了解 SQL 注入技术。
  3. 安排经验丰富的 node.js 安全专家进行应用程序安全评估。 (我在 liftsecurity.io 有空)

重申一下——不要相信用户会给你程序代码——制作单独的路由并自己插入数据,URI 在进一步处理之前对所有用户输入进行编码,并使用请求选项对象,如:{qs:{name:value}} 而不是字符串插值。

有了这些保护,您可能就没事了,因为这里似乎使用了存储过程。但是,除非您可以在 Web 服务的文档中找到对此的确认,否则唯一可以确定的方法是通过我上面建议的方法之一。

希望对您有所帮助!