阻止Node.js中的SQL注入

fun*_*iki 80 javascript mysql sql-injection node.js node-mysql

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

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


一些背景:

我正在使用node-mysql模块制作一个带有Node.js + MySql的后端堆栈的Web应用程序.从可用性的角度来看,该模块很棒,但它还没有实现类似于PHP的Prepared Statements(虽然我知道它是在todo上).

根据我的理解,PHP的预处理语句的实现,尤其有助于防止SQL注入.但我担心,我的node.js应用程序可能会受到类似的攻击,即使默认情况下提供了字符串转义(如下面的代码片段).

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

我应该暂时切换到node-mysql-native,因为它确实提供了准备语句吗?我对此犹豫不决,因为它似乎不像node-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?
   });
Run Code Online (Sandbox Code Playgroud)

Mic*_*att 54

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

  • 但它是否会阻止所有SQL注入?[这个答案](http://stackoverflow.com/a/12118602/865883)建议不要(至少对于PHP + MySQL)并暗示PHP的准备语句.同样,这是在PHP的上下文中. (4认同)
  • 正如我在帖子中提到的,我知道该库会转义字符,但如果我不切换到已实现预准备语句的库,我会更担心安全隐患,即是否存在可能发生的SQL注入我现在在做什么? (3认同)
  • 转义字符可防止 SQL 注入。当字符没有被转义时就会发生注入,恶意用户可以利用它来关闭查询并开始一个新的查询,例如删除表或插入假记录。对于转义字符,这是不可能的。[维基百科](http://en.wikipedia.org/wiki/SQL_injection) 有一些关于 SQL 注入的附加信息。 (2认同)

hex*_*ide 11

图书馆有部分在有关转义自述.它是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'
});
Run Code Online (Sandbox Code Playgroud)

除此之外:

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'
});
Run Code Online (Sandbox Code Playgroud)

除了这些函数,您还可以使用转义函数:

connection.escape(query);
mysql.escape(query);
Run Code Online (Sandbox Code Playgroud)

要转义查询标识符:

mysql.escapeId(identifier);
Run Code Online (Sandbox Code Playgroud)

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

从可用性的角度来看,该模块很棒,但它还没有实现类似于PHP的Prepared Statements的东西.

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

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));
};
Run Code Online (Sandbox Code Playgroud)

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

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


jas*_*as- 11

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

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

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

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

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

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

无论如何,我意识到这不是一个可能一直希望的"是"或"否"的答案,但我认为除非他们对相关软件进行分析,否则任何人都不能给你.


Boy*_*pro 5

Mysql-native 已经过时了,所以它变成了MySQL2,这是在原始 MySQL 模块团队的帮助下创建的新模块。这个模块有更多的功能,我认为它有你想要的,因为它已经像 PHP 中一样准备了语句(通过 using.execute())以提高安全性。

它也非常活跃(最后一次更改是从 2-1 天开始)我之前没有尝试过,但我认为这是你想要的,甚至更多。