51

nodejsでは、外部コマンドを実行する唯一の方法はsys.exec(cmd)を使用することです。外部コマンドを呼び出して、stdinを介してデータを提供したいと思います。nodejsには、コマンドを開いてデータをプッシュする方法がまだないようです(実行して、標準+エラー出力を受け取るだけです)。そのため、今これを行う必要がある唯一の方法は次のとおりです。次のような単一の文字列コマンドを介して:

var dangerStr = "bad stuff here";
sys.exec("echo '" + dangerStr + "' | somecommand");

このような質問に対するほとんどの回答は、nodejs(GoogleのV8 Javascriptエンジンを使用)では機能しない正規表現、またはPythonなどの他の言語のネイティブ機能に焦点を当てています。

上記のようなexec文字列を安全に作成できるように、dangerStrをエスケープしたいと思います。それが役立つ場合、dangerStrにはJSONデータが含まれます。

4

7 に答える 7

39

これは私が使用するものです:

var escapeShell = function(cmd) {
  return '"'+cmd.replace(/(["'$`\\])/g,'\\$1')+'"';
};
于 2011-10-07T09:37:35.767 に答える
24

シェルパラメータへの未知の入力のエスケープに依存すること絶対にしないでください。ほとんどの場合、ユーザーがサーバー上で任意のコードを実行できるとは思わなかったエッジケースがあります。

ノードは、コマンドの呼び出しと各引数の受け渡しをサポートしており、エスケープは必要ありません。これが最も安全な方法です。

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}`);
});

ドキュメントはこちら

于 2018-05-19T11:50:47.823 に答える
23

単純な(しかし正しい)ソリューションが必要な場合は、次を使用できます。

function escapeShellArg (arg) {
    return `'${arg.replace(/'/g, `'\\''`)}'`;
}

したがって、Chris Johnsenが述べたように、文字列は一重引用符で簡単にエスケープされます。

echo 'John'\''s phone';

引用符が強いbashために機能し、で機能するように感じますが、とでは機能しません。fishzshsh

を持っている場合は、でまたはを使用しbashてスクリプトを実行できます。shzsh'bash -c \'' + escape('all-the-rest-escaped') + '\''

しかし実際には...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}

またはいくつかのエラー。

http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_optionsをご覧ください

ちなみに、一連のコマンドを実行する簡単な解決策は次のとおりです。

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

良い1日を!

于 2014-04-03T03:08:21.587 に答える
4

私はウィルの意見を2番目に言います。可能な限り、手で逃げるのを避け、スポーンを好むべきです。

ただし、エスケープが避けられない場合、たとえばexecを使用する必要がある場合や、sshを介してコマンドを実行している場合などです。次に、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`)

説明は次のとおりです。

dangerBase64不明ですが、bashに安全でない文字が含まれていません。したがってecho ${dangerBase64}、必要なものを出力します。

最後に、二重引用符は$(echo ${dangerBase64} | base64 -d)、bash内でユーザーから渡された実際の値をエスケープします。これは安全で、ユーザーが望んでいたのと同じ値です。

于 2020-02-14T07:33:50.033 に答える
0

特殊文字(改行など)も処理する必要がある場合は、次の方法で処理できます。

str = JSON.stringify(str)
    .replace(/^"|"$/g,'') //remove JSON-string double quotes
    .replace(/'/g, '\'"\'"\'') //escape single quotes the ugly bash way

これは、Bashの強い引用符を一重引用符で使用し、受信者がJSONのCのようなエスケープを理解できることを前提としています。

于 2017-02-04T06:25:28.973 に答える
0

独自のソフトウェアを構築している場合は、コマンドをbase64またはhex形式にエンコードしてから、プログラムから引数をデコードできます。

私が使用する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=="

使用してストレスなく引数searchと引数を取得できますreplacementbase64_decode

于 2021-02-15T14:31:44.827 に答える
-12

外部コマンドに書き込む方法がありますprocess.createChildProcess:(ドキュメント)はメソッドを使用してオブジェクトを返しますwritecreateChildProcessただし、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.");
于 2009-11-22T21:51:00.677 に答える