阻止Node.js中的SQL注入

时间:2013-04-03 03:55:54

标签: javascript mysql node.js sql-injection node-mysql

是否有可能阻止Node.js中的SQL注入(最好使用模块),就像PHP具有保护它们的Prepared Statements一样。

如果是这样,怎么样?如果没有,可能会绕过我提供的代码的一些示例(见下文)。


某些情境:

我正在使用node-mysql模块创建一个包含Node.js + MySql的后端堆栈的Web应用程序。从可用性的角度来看,该模块很棒,但它还没有实现类似于PHP Prepared Statements的东西(尽管我知道它在todo上)。

根据我的理解,PHP在预防SQL注入方面实现了预准备语句,helped greatly等。不过我很担心我的node.js应用可能会受到类似攻击even with the string escaping provided by default(如下面的代码段所示)。

node-mysql似乎是node.js最受欢迎的mysql连接器,所以我想知道其他人可能正在做什么(如果有的话)来解决这个问题 - 或者甚至是node.js的问题开头(不知道这不会是什么,因为涉及用户/客户端输入)。

我应该暂时切换到node-mysql-native,因为它确实提供了准备好的语句吗?我对此犹豫不决,因为它似乎不像节点那样活跃-mysql(虽然这可能仅仅意味着它已经完成)。

这是一个用户注册代码片段,它使用sanitizer模块,以及node-mysql准备好的类似语句的语法(如上所述,它可以进行字符转义),以防止跨站点脚本和sql注入分别:

// Prevent xss
var clean_user = sanitizer.sanitize(username);

// assume password is hashed already
var post = {Username: clean_user, Password: hash};

// This just uses connection.escape() underneath
var query = connection.query('INSERT INTO users SET ?', post,
   function(err, results)
   {
       // Can a Sql injection happen here?
   });

6 个答案:

答案 0 :(得分:49)

node-mysql库会在您正在使用时自动执行转义。见https://github.com/felixge/node-mysql#escaping-query-values

答案 1 :(得分:10)

图书馆有关于转义的自述文件中有section。它是Javascript原生的,所以我不建议切换到node-mysql-native。文档说明了这些转义指南:

编辑: node-mysql-native也是纯粹的Javascript解决方案。

  • 数字保持不变
  • 布尔值转换为true / false字符串
  • 日期对象转换为YYYY-mm-dd HH:ii:ss字符串
  • 缓冲区转换为十六进制字符串,例如X'0fa5'
  • 字符串安全转义
  • 阵列变成列表,例如['a', 'b']变为'a', 'b'
  • 嵌套数组转换为分组列表(对于批量插入),例如[['a', 'b'], ['c', 'd']]变为('a', 'b'), ('c', 'd')
  • 对象变为key = 'val'对。嵌套对象被强制转换为字符串。
  • undefined / null转换为NULL
  • NaN / Infinity保持原样。 MySQL不支持这些,并且尝试将它们作为值插入将触发MySQL错误,直到它们实现支持。

这允许你这样做:

var userId = 5;
var query = connection.query('SELECT * FROM users WHERE id = ?', [userId], function(err, results) {
  //query.sql returns SELECT * FROM users WHERE id = '5'
});

以及:

var post  = {id: 1, title: 'Hello MySQL'};
var query = connection.query('INSERT INTO posts SET ?', post, function(err, result) {
  //query.sql returns INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
});

除了这些功能外,您还可以使用转义功能:

connection.escape(query);
mysql.escape(query);

转义查询标识符:

mysql.escapeId(identifier);

作为对你准备好的陈述的评论的回应:

  

从可用性的角度来看,该模块很棒,但还没有实现类似于PHP的准备语句。

准备好的语句位于此连接器的todo列表中,但此模块至少允许您指定与预准备语句非常相似的自定义格式。以下是自述文件中的一个示例:

connection.config.queryFormat = function (query, values) {
  if (!values) return query;
  return query.replace(/\:(\w+)/g, function (txt, key) {
    if (values.hasOwnProperty(key)) {
      return this.escape(values[key]);
    }
    return txt;
  }.bind(this));
};

这会更改连接的查询格式,因此您可以使用以下查询:

connection.query("UPDATE posts SET title = :title", { title: "Hello MySQL" });
//equivalent to
connection.query("UPDATE posts SET title = " + mysql.escape("Hello MySQL");

答案 2 :(得分:10)

我意识到这是一个较旧的帖子,但似乎答案从未标记过,所以我会把它扔出去。

关于测试您使用的模块是否安全,您可以采取多种途径。我会谈谈每个人的利弊,以便你做出更明智的决定。

目前您正在使用的模块没有任何漏洞,但是,这通常会导致错误的安全感,因为当前正在利用您正在使用的模块/软件包的漏洞很可能并且您不会在供应商应用修补程序/修补程序之前,系统会发出问题警告。

  1. 要及时了解漏洞,您需要关注邮件列表,论坛,IRC&其他与黑客相关的讨论。 专业版:在供应商收到警报或已发布修复程序/修补程序以补救其软件的潜在攻击途径之前,您经常会发现库中存在潜在问题。 CON:这可能非常耗时且资源密集。如果您使用RSS源,日志解析(IRC聊天日志)和/或使用关键短语(在本例中为node-mysql-native)的网络剪贴板,并且通知可以帮助减少用于控制这些资源的时间。

  2. 创建模糊器,使用fuzzer或其他漏洞框架,例如metasploitsqlMap等,以帮助测试供应商可能未查找的问题。 PRO:这可以证明是一种确保可接受水平的确定的火灾方法,无论您实施的模块/软件是否对公共访问是安全的。 CON:这也变得耗时且昂贵。另一个问题将来自误报以及对问题所在但没有​​注意到的结果的未经教育的审查。

  3. 真正的安全性和应用程序安全性通常非常耗时且资源密集。管理者将始终使用的一件事是确定执行上述两种选择的成本效益(人力,资源,时间,工资等)的公式。

    无论如何,我意识到这不是一个可能一直希望的“是”或“否”的答案,但我认为在他们对相关软件进行分析之前,任何人都不能给你这个答案。

答案 3 :(得分:1)

我知道这个问题很旧,但是对于任何感兴趣的人,Mysql原生版本已经过时,因此它变成了MySQL2,这是在原始MySQL模块团队的帮助下创建的新模块。该模块具有更多功能,我想它具有所需的功能,因为它已经准备好了语句(通过使用.execute()),如PHP中那样,可以提高安全性。

它也非常活跃(最后一次更改是2-1天),我之前没有尝试过,但我想这是您想要的,并且更多。

答案 4 :(得分:0)

在本文中您可以找到针对注入、xss 和蛮力攻击的简单解决方案 How to secure your node app from attacks

答案 5 :(得分:-1)

最简单的方法是在您导出到路由的模块中处理所有数据库交互。如果您的路由没有数据库的上下文,那么SQL无论如何都无法触摸它。