防止Node.js中的SQL注入

是否有可能防止SQL注入在Node.js(最好与一个模块),就像PHP有防备他们的Prepared语句相同的方式。

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


一些上下文:

我正在使用node-mysql模块构build一个由Node.js + MySql组成的后端堆栈的Web应用程序。 从可用性的angular度来看,这个模块非常棒,但是它还没有实现类似于PHP的Prepared Statements (尽pipe我知道它是在待办事项上 )。

从我的理解来看,除了别的之外,PHP的准备语句的实现在预防SQL注入方面起了很大作用。 不过,我担心, 即使使用默认提供的string转义 (如下面的代码片段),我的node.js应用程序也可能面临类似的攻击。

node-mysql似乎是node.js最stream行的mysql连接器,所以我想知道其他人可能在做什么(如果有的话)来解决这个问题 – 或者如果它甚至是node.js的问题开始(不知道这将不会如何,因为涉及用户/客户端input)。

我应该暂时切换到node-mysql-native ,因为它提供了准备好的语句? 我不愿意这样做,因为它似乎不像node-mysql那样活跃(尽pipe这可能意味着它是完整的)。

下面是用户注册代码片段,它使用了卫生清理器模块,以及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? }); 

如果您已经在使用node-mysql库,则会自动执行转义。 请参阅https://github.com/felixge/node-mysql#escaping-query-values

图书馆在自述文件中有关于逃避的部分。 这是Javascript本机,所以我不build议切换到节点mysql的本地 。 该文档指出了这些转义指导:

编辑: node-mysql-native也是一个纯Javascript的解决scheme。

  • 数字保持不变
  • 布尔转换为true / falsestring
  • date对象转换为YYYY-mm-dd HH:ii:ssstring
  • 缓冲区被转换为hexstring,例如X'0fa5'
  • string安全地逃脱
  • 数组变成列表,例如['a', 'b']变成'a', 'b'
  • 嵌套数组变成分组列表(用于批量插入),例如[['a', 'b'], ['c', 'd']]变成('a', 'b'), ('c', 'd')
  • 对象被转换成key = 'val'对。 嵌套对象被转换为string。
  • 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); 

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

从可用性的angular度来看,这个模块非常棒,但是它还没有实现类似于PHP的Prepared Statements的东西。

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

 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"); 

我意识到这是一个较旧的post,但似乎答案从来没有标记,所以我会把它扔在那里。

关于testing你正在使用的模块是否安全,你可以采取几条路线。 我会触及每个人的利弊,以便您做出更明智的决定。

目前,您正在使用的模块没有任何漏洞,但这往往会导致错误的安全感,因为目前正在利用您正在使用的模块/软件包的漏洞非常可能,您将不会收到警报直到供应商应用修补程序/修补程序。

  1. 要及时了解漏洞,您需要遵循邮件列表,论坛,IRC和其他黑客相关的讨论。 PRO:在供应商被提醒或者已经发布修补程序/补丁以补救他们软件的潜在攻击途径之前,您经常会发现图书馆内潜在的问题。 CON:这可能是非常耗时和资源密集的。 如果你使用RSS feed,使用关键短语(在本例中为node-mysql-native)loggingparsing(IRC聊天logging)和/或网页报废,那么这个路由就可以使用这个路由,通知可以帮助减less花费在这些资源上的时间。

  2. 创build一个模糊器,使用模糊 器或其他漏洞框架(如metasploit , sqlMap等)来帮助testing供应商可能没有find的问题。 PRO:这可以certificate是一个确保火灾的方法,确保您所实施的模块/软件是否可以安全地进入公共访问,以确保达到可接受的水平。 CON:这也变得耗时且昂贵。 另外一个问题是由于误报以及没有受过教育的问题所在,而没有被发现的问题。

一般来说,真正的安全性和应用程序安全性可能非常耗时且耗费资源。 pipe理者经常会用到的一个方法是确定执行上述两个选项的成本效益(人力,资源,时间,工资等)。

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