Как мне избежать строки для команды оболочки в узле?

javascript shell escaping node.js v8

23285 просмотра

5 ответа

В nodejs единственный способ выполнить внешние команды - через sys.exec (cmd). Я хотел бы вызвать внешнюю команду и передать ей данные через стандартный ввод. В nodejs пока не существует способа открыть команду и затем передать ей данные (только для выполнения и получения ее стандартных сообщений об ошибках +), так что, похоже, единственный способ сделать это прямо сейчас - с помощью одной строковой команды, такой как:

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

Большинство ответов на подобные вопросы были посвящены либо регулярному выражению, которое не работает для меня в nodejs (который использует движок JavaScript V8 от Google), либо нативным функциям из других языков, таких как Python.

Я хотел бы избежать dangerStr, чтобы было безопасно составлять строку exec, подобную приведенной выше. Если это поможет, dangerStr будет содержать данные JSON.

Автор: Maciek Источник Размещён: 29.07.2019 05:23

Ответы (5)


-1 плюса

Решение

Существует способ записи во внешнюю команду: 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.");
Автор: Matthew Crumley Размещён: 22.11.2009 09:51

36 плюса

Это то, что я использую:

var escapeShell = function(cmd) {
  return '"'+cmd.replace(/(["\s'$`\\])/g,'\\$1')+'"';
};
Автор: Sylvain Zimmer Размещён: 07.10.2011 09:37

14 плюса

Если вам нужно простое решение, вы можете использовать это:

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

Таким образом, ваша строка будет просто экранирована одинарными кавычками, как упоминал Крис Джонсен.

echo 'John'\''s phone';

Он работает bashиз-за сильного цитирования , кажется, что он тоже работает fish, но не работает в zshи sh.

Если у вас есть, bashвы можете запустить свой скрипт в shили zshс '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('; ')]);

Хорошего дня!

Автор: Alex Yaroshevich Размещён: 03.04.2014 03:08

7 плюса

Вы никогда не должны полагаться на экранирование неизвестного ввода при переходе к параметру оболочки - почти всегда будет некоторый крайний случай, о котором вы даже не думали, что позволит пользователю выполнить произвольный код на вашем сервере.

Узел поддерживает вызов команды и передачу каждого аргумента отдельно, без экранирования. Это самый безопасный способ сделать это:

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

Документация здесь

Автор: Will Richardson Размещён: 19.05.2018 11:50

-2 плюса

Если вам также нужно иметь дело со специальными символами (переводы строк и т. Д.), Вы можете сделать это следующим образом:

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

Это предполагает, что вы используете сильные кавычки Баша через одинарные кавычки), и получатель может понять C-подобный выход JSON.

Автор: MicMro Размещён: 04.02.2017 06:25
Вопросы из категории :
32x32