Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在节点中转义shell命令的字符串?_Javascript_Shell_Escaping_Node.js_V8 - Fatal编程技术网

Javascript 如何在节点中转义shell命令的字符串?

Javascript 如何在节点中转义shell命令的字符串?,javascript,shell,escaping,node.js,v8,Javascript,Shell,Escaping,Node.js,V8,在中,执行外部命令的唯一方法是通过sys.exec(cmd)。我想调用一个外部命令并通过stdin给它数据。在nodejs中,似乎还没有一种方法可以打开一个命令,然后将数据推送到该命令中(仅用于执行并接收其标准+错误输出),因此我现在要做的唯一方法似乎是通过一个字符串命令,例如: var dangerStr = "bad stuff here"; sys.exec("echo '" + dangerStr + "' | somecommand"); 对这类问题的大多数回答都集中在正则表达式上,

在中,执行外部命令的唯一方法是通过sys.exec(cmd)。我想调用一个外部命令并通过stdin给它数据。在nodejs中,似乎还没有一种方法可以打开一个命令,然后将数据推送到该命令中(仅用于执行并接收其标准+错误输出),因此我现在要做的唯一方法似乎是通过一个字符串命令,例如:

var dangerStr = "bad stuff here";
sys.exec("echo '" + dangerStr + "' | somecommand");
对这类问题的大多数回答都集中在正则表达式上,正则表达式在nodejs中不适用(它使用谷歌的v8javascript引擎),或者来自其他语言(如Python)的本机特性


我想避开dangerStr,这样就可以安全地编写上面的exec字符串。如果有帮助,dangerStr将包含JSON数据。

有一种写入外部命令的方法:
process.createChildProcess
()使用
write
方法返回对象
createChildProcess
并不方便,因为它不缓冲stdout和stderr,因此需要事件处理程序以块的形式读取输出

var stdout = "", stderr = "";
var child = process.createChildProcess("someCommand");

child.addListener("output", function (data) {
    if (data !== null) {
        stdout += data;
    }
});
child.addListener("error", function (data) {
    if (data !== null) {
        stderr += data;
    }
});
child.addListener("exit", function (code) {
    if (code === 0) {
        sys.puts(stdout);
    }
    else {
        // error
    }
});

child.write("This goes to someCommand's stdin.");
这就是我使用的:

var escapeShell = function(cmd) {
  return '"'+cmd.replace(/(["'$`\\])/g,'\\$1')+'"';
};
如果您需要简单(但正确)的解决方案,您可以使用以下方法:

function escapeShellArg (arg) {
    return `'${arg.replace(/'/g, `'\\''`)}'`;
}
因此,正如Chris Johnsen所提到的,您的字符串将简单地用单引号转义

echo 'John'\''s phone';
它在
bash
中工作,因为,感觉它也在
fish
中工作,但在
zsh
sh
中不工作

如果您有
bash
,您可以在
sh
zsh
中使用
'bash-c\''+escape('all-the-rest-escape')+'\'
运行脚本

但实际上。。。node.js将转义您所需的所有字符:

var child = require('child_process')
  .spawn('echo', ['`echo 1`;"echo $SSH_TTY;\'\\0{0..5}']);

child.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});

child.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});
这段代码将执行:

echo '`echo 1`;"echo $SSH_TTY;'\''\\0{0..5}'
并将输出:

stdout: `echo 1`;"echo $SSH_TTY;\'\\0{0..5}
或者是一些错误

看看

顺便说一下,运行一组命令的简单解决方案是:

require('child_process')
  .spawn('sh', ['-c', [
    'cd all/your/commands',
    'ls here',
    'echo "and even" > more'
  ].join('; ')]);

祝你今天愉快

如果您还需要处理特殊字符(换行符等),可以这样做:

str = JSON.stringify(str)
    .replace(/^"|"$/g,'') //remove JSON-string double quotes
    .replace(/'/g, '\'"\'"\'') //escape single quotes the ugly bash way
这假设您使用Bash(通过单引号)并且接收者可以理解JSON的C-like转义。

您-几乎总会有一些您没有想到的边缘情况,允许用户在您的服务器上执行任意代码

节点支持调用命令并分别传递每个参数,无需转义。这是最安全的方法:

const { spawn } = require('child_process');
// Note that the arguments are in an array, not using string interpolation
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.log(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});
文档是

我赞同的意见,只要有可能,你应该避免用手逃跑,而更喜欢繁殖

但是,在无法避免转义的情况下,例如,如果您需要使用exec或您正在使用exec。然后可以使用base64将安全字符传递给bash,并依靠bash来转义未知字符

const dangerStr = 'bad stuff here'
// base64 has safe characters [A-Za-z=0-9+/]
const dangerBase64 = btoa(dangerStr)

sys.exec(`echo "$(echo ${dangerBase64} | base64 -d)" | somecommand`)
解释如下:

dangerbase 64
未知,但其中不包含不安全字符。因此,
echo${dangerBase64}
将输出我们想要的内容


最后,
$(echo${dangerBase64}| base64-d)
的双引号转义用户在bash中传递的实际值,该值是安全的,并且具有用户想要的值

如果您正在构建自己的软件,您可以将命令编码为base64或十六进制格式,然后解码程序中的参数

对于我使用的Nodejs应用程序

var base64_encode = exports.base64_encode = function(non_base64_string){
    return Buffer.from(non_base64_string).toString('base64');
}


var base64_decode = exports.base64_decode = function(base64_string){
    return Buffer.from(base64_string, 'base64').toString('ascii')
}
所以当我运行一个base64编码的命令时

webman grep --search "aW5jbHVkZV9vbmNlICRfU0VSVkVSWyJET0NVTUVOVF9ST09UIl0uIi9zZXR0aW5ncy5waHAiOw==" --replacement "JGRvY3VtZW50X3Jvb3QgPSBfX0RJUl9fO3doaWxlKHRydWUpe2lmIChmaWxlX2V4aXN0cygkZG9jdW1lbnRfcm9vdC4iL3NldHRpbmdzLmpzb24iKSl7YnJlYWs7fWVsc2V7JGRvY3VtZW50X3Jvb3Q9ZGlybmFtZSgkZG9jdW1lbnRfcm9vdCk7fX08bmV3bGluZT5pbmNsdWRlX29uY2UgJGRvY3VtZW50X3Jvb3QuIi9zZXR0aW5ncy5waHAiOw=="

对于Bourne类型的Shell,我可以使用
base64\u decode

无压力地获取参数
search
replacement
对于Bourne类型的Shell,您可以使用以下算法安全地转义字符串:1)用四字符序列单引号、反斜杠、单引号替换所有出现的单引号('),单引号('\'')2)在已修改字符串的开头和结尾添加一个额外的单引号。前导单引号和尾随单引号的编码效率不高,但它仍然有效——当它可能只是\'时,它就变成了\'。澄清一下:我花了一点时间才理解@ChrisJohnsen的建议,但它确实有效。如果希望
不要在shell上执行该操作
,请执行
echo'don'\''don'\'don'
以生成
不要执行该操作
。。谢谢顺便说一句,新的URI是你没有解释任何关于转义参数的事情。这并没有回答OP所问的问题,即转义参数。
echo
的使用只是一个例子。OP不仅仅是试图通过管道将字符串传输到命令。他们试图在命令行中使用任意字符串。它不能回答标题中的问题,但这通过完全避免问题解决了问题。OP接受了答案,因此显然它起了作用。@DavidTorres
abc$abc
变成了
abc\$abc
如果使用撇号
,则无需使用esacpe
$
这似乎是错误的:它将
foo bar
转义为
foo\bar
,将解析为
foo\bar
。引用空格(
\s
)如果您将所有内容都用双引号括起来,则不必这样做,因为这样会自动保留所有空白。只有在字符串周围没有引号时才需要这样做,否则shell会将空格视为参数分隔符。此外,当您将选项卡转换为
\
时,您没有正确引用空格,但正确的形式应该是
\t
。这似乎是命令注入和奇怪的边缘案例问题的邀请。