Node.js中安全调用系统命令的方法(避免注入安全漏洞)


Posted in Javascript onDecember 05, 2014

在这篇文章中,我们将学习正确使用Node.js调用系统命令的方法,以避免常见的命令行注入漏洞。

我们经常使用的调用命令的方法是最简单的child_process.exec。它有很一个简单的使用模式;通过传入一段字符串命令,并把一个错误或命令处理结果回传至回调函数中。

这里是你通过child_process.exec调用系统命令一个非常典型的例子。

child_process.exec('ls', function (err, data) {

    console.log(data);

});

不过,当你需要在你调用的命令中添加一些用户输入的参数时,会发生什么?显而易见的解决方案是把用户输入直接和您的命令进行字符串合并。但是,我多年的经验告诉我:当你将连接的字符串从一个系统发送到另一个系统时,总有一天会出问题。

var path = "user input";

child_process.exec('ls -l ' + path, function (err, data) {

    console.log(data);

});

为什么连接字符串会出问题?

嗯,因为在child_process.exec引擎下,将调用执行"/bin/sh"。而不是目标程序。已发送的命令只是被传递给一个新的"/bin/ sh'进程来执行shell。 child_process.exec的名字有一定误导性 - 这是一个bash的解释器,而不是启动一个程序。这意味着,所有的shell字符可能会产生毁灭性的后果,如果直接执行用户输入的参数。

[pid 25170] execve("/bin/sh", ["/bin/sh", "-c", "ls -l user input"], [/* 16 vars */]

比如,攻击者可以使用一个分号";"来结束命令,并开始一个新的调用,他们可以使用反引号或$()来运行子命令。还有很多潜在的滥用。

那么什么是正确的调用方式?

execFile / spawn

像spawn和execFile采用一个额外的数组参数,不是一个shell环境下可以执行其他命令的参数,并不会运行额外的命令。

让我们使用的execFile和spawn修改一下之前的例子,看看系统调用有何不同,以及为什么它不容易受到命令注入。

child_process.execFile

var child_process = require('child_process');
var path = "."

child_process.execFile('/bin/ls', ['-l', path], function (err, result) {

    console.log(result)

});

运行的系统调用
[pid 25565] execve("/bin/ls", ["/bin/ls", "-l", "."], [/* 16 vars */]

child_process.spawn

使用 spawn 替换的例子很相似。

var child_process = require('child_process');
var path = "."

var ls = child_process.spawn('/bin/ls', ['-l', path])

ls.stdout.on('data', function (data) {

    console.log(data.toString());

});

运行的系统调用

[pid 26883] execve("/bin/ls", ["/bin/ls", "-l", "."], [/* 16 vars */

当使用spawn或execfile时,我们的目标是只执行一个命令(参数)。这意味着用户不能运行注入的命令,因为/bin/ls并不知道如何处理反引号或pipe或;。它的/bin/bash将要解释的是那些命令的参数。它类似于使用将参数传入SQL查询(parameter),如果你熟悉的话。

但还需要警告的是:使用spawn或execFile并不总是安全的。例如,运行 /bin/find,并传入用户输入参数仍有可能导致系统被攻陷。 find命令有一些选项,允许读/写任意文件。

所以,这里有一些关于Node.js运行系统命令的指导建议:

避免使用child_process.exec,当需要包含用户输入的参数时更是如此,请牢记。
尽量避免让用户传入参数,使用选择项比让用户直接输入字符串要好得多。
如果你必须允许用户输入参数,请广泛参考该命令的参数,确定哪些选项是安全的,并建立一个白名单。

Javascript 相关文章推荐
javascript中直接写php代码的方法
Jul 31 Javascript
jQuery插件开发的两种方法及$.fn.extend的详解
Jan 16 Javascript
Ext4.2的Ext.grid.plugin.RowExpander无法触发事件解决办法
Aug 15 Javascript
以JavaScript来实现WordPress中的二级导航菜单的方法
Dec 14 Javascript
Bootstrap每天必学之折叠(Collapse)插件
Apr 25 Javascript
最实用的jQuery分页插件
Oct 09 Javascript
jQuery File Upload文件上传插件使用详解
Dec 06 Javascript
javaScript中封装的各种写法示例(推荐)
Jul 03 Javascript
关于Ajax的原理以及代码封装详解
Sep 08 Javascript
微信小程序手机号码验证功能的实例代码
Aug 28 Javascript
js canvas实现二维码和图片合成的海报
Nov 19 Javascript
js中script的上下放置区别,Dom的增删改创建操作实例分析
Dec 16 Javascript
jQuery前端框架easyui使用Dialog时bug处理
Dec 05 #Javascript
Javascript实现获取窗口的大小和位置代码分享
Dec 04 #Javascript
Javascript 中创建自定义对象的方法汇总
Dec 04 #Javascript
dreamweaver 8实现Jquery自动提示
Dec 04 #Javascript
jquery实现动态画圆
Dec 04 #Javascript
javascript数组遍历for与for in区别详解
Dec 04 #Javascript
c#+jquery实现获取radio和checkbox的值
Sep 12 #Javascript
You might like
利用中国天气预报接口实现简单天气预报
2014/01/20 PHP
php实现的SSO单点登录系统接入功能示例分析
2016/10/12 PHP
PHP实现的迪科斯彻(Dijkstra)最短路径算法实例
2017/09/16 PHP
PHP实现求连续子数组最大和问题2种解决方法
2017/12/26 PHP
通过身份证号得到出生日期和性别的js代码
2009/11/23 Javascript
关于JS字符串函数String.replace()
2013/04/07 Javascript
javascript将数字转换整数金额大写的方法
2015/01/27 Javascript
js实现的简洁网页滑动tab菜单效果代码
2015/08/24 Javascript
基于jQuery实现仿百度首页换肤背景图片切换代码
2015/08/25 Javascript
初步了解javascript面向对象
2015/11/09 Javascript
关于ES6的六个小特性(二)
2017/02/20 Javascript
nodejs mysql 实现分页的方法
2017/06/06 NodeJs
node.js通过axios实现网络请求的方法
2018/03/05 Javascript
jQuery动态生成的元素绑定事件操作实例分析
2019/05/04 jQuery
Vue解决移动端弹窗滚动穿透问题
2020/12/15 Vue.js
[02:31]DOTA2帕克 英雄基础教程
2013/11/26 DOTA
python 从远程服务器下载东西的代码
2013/02/10 Python
在Django的session中使用User对象的方法
2015/07/23 Python
python自带的http模块详解
2016/11/06 Python
Python判断文件或文件夹是否存在的三种方法
2017/07/27 Python
让代码变得更易维护的7个Python库
2018/10/09 Python
Python实现高斯函数的三维显示方法
2018/12/29 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
一篇文章弄懂Python中的可迭代对象、迭代器和生成器
2019/08/12 Python
python图的深度优先和广度优先算法实例分析
2019/10/26 Python
pygame实现打字游戏
2021/02/19 Python
Python importlib动态导入模块实现代码
2020/04/16 Python
完美解决Django2.0中models下的ForeignKey()问题
2020/05/19 Python
python热力图实现简单方法
2021/01/29 Python
第二层交换机和路由器的区别?第三层交换机和路由器的区别?
2013/05/23 面试题
国家助学金获奖感言
2014/01/31 职场文书
五分钟演讲稿
2014/04/30 职场文书
2014企业年终工作总结
2014/12/23 职场文书
反腐倡廉影片观后感
2015/06/08 职场文书
css position fixed 左右双定位的实现代码
2021/04/29 HTML / CSS
idea 在springboot中使用lombok插件的方法
2021/08/02 Java/Android