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 相关文章推荐
node.js WEB开发中图片验证码的实现方法
Jun 03 Javascript
javascript使用smipleChart实现简单图表
Jan 02 Javascript
Javascript编写2048小游戏
Jul 07 Javascript
Bootstrap网格系统详解
Apr 26 Javascript
javascript实现鼠标点击页面 移动DIV
Dec 02 Javascript
jQuery编写网页版2048小游戏
Jan 06 Javascript
基于jQuery Easyui实现登陆框界面
Jul 10 jQuery
JavaScript中in和hasOwnProperty区别详解
Aug 04 Javascript
weex slider实现滑动底部导航功能
Aug 28 Javascript
vue2.0自定义指令示例代码详解
Apr 25 Javascript
Vue实现点击箭头上下移动效果
Jun 11 Javascript
jQuery实现简单飞机大战
Jul 05 jQuery
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
php 静态变量的初始化
2009/11/15 PHP
检测codeigniter脚本消耗内存情况的方法
2015/03/21 PHP
php array_pop 删除数组最后一个元素实例
2016/11/02 PHP
初试jQuery EasyUI 使用介绍
2010/04/01 Javascript
原生Js与jquery的多组处理, 仅展开一个区块的折叠效果
2011/01/09 Javascript
js操纵跨frame的三级联动select下拉选项实例介绍
2013/05/19 Javascript
JavaScript cookie的设置获取删除详解
2014/02/11 Javascript
详细解读JavaScript的跨浏览器事件处理
2015/08/12 Javascript
JS模拟简易滚动条效果代码(附demo源码)
2016/04/05 Javascript
jQuery插件JWPlayer视频播放器用法实例分析
2017/01/11 Javascript
jQuery代码实现实时获取时间
2017/01/29 Javascript
canvas轨迹回放功能实现
2017/12/20 Javascript
详解node child_process模块学习笔记
2018/01/24 Javascript
Vue中key的作用示例代码详解
2020/06/10 Javascript
原生JS利用transform实现banner的无限滚动示例代码
2020/06/15 Javascript
[02:09]2018DOTA2亚洲邀请赛TNC赛前采访
2018/04/04 DOTA
详解Python多线程
2016/11/14 Python
python os.path模块常用方法实例详解
2018/09/16 Python
python原类、类的创建过程与方法详解
2019/07/19 Python
Python ATM功能实现代码实例
2020/03/19 Python
详解python中groupby函数通俗易懂
2020/05/14 Python
详解Python IO编程
2020/07/24 Python
西班牙电子产品购物网站:Electronicamente
2018/07/26 全球购物
医院后勤自我鉴定
2013/10/13 职场文书
英文导游欢迎词
2014/01/11 职场文书
中学生寄语大全
2014/04/03 职场文书
学生安全责任书
2014/04/15 职场文书
推荐信格式要求
2014/05/09 职场文书
党的群众路线教育实践活动查摆问题及整改措施
2014/10/10 职场文书
有限责任公司股东合作协议书范本
2014/10/30 职场文书
六一儿童节主持开场白
2015/05/28 职场文书
小学生读书笔记范文
2015/06/30 职场文书
JS数组的常用方法整理
2021/03/31 Javascript
python OpenCV学习笔记
2021/03/31 Python
go 原生http web 服务跨域restful api的写法介绍
2021/04/27 Golang
MySQL窗口函数的具体使用
2021/11/17 MySQL