Node.js NodeJS spawn不会转义坏字符串

Node.js NodeJS spawn不会转义坏字符串,node.js,security,exec,spawn,sanitization,Node.js,Security,Exec,Spawn,Sanitization,我想使用ssh在远程主机中下载url,我使用的是exec(),它正在工作: const cmd = `mkdir -p /home/username/test; wget --no-check-certificate -q -U \"\" -c \"${url}\" -O /home/username/test/img.jpg`; const out = execSync(`ssh -o ConnectTimeout=8 -o StrictHostKeyC

我想使用ssh在远程主机中下载url,我使用的是exec(),它正在工作:

const cmd = `mkdir -p /home/username/test; wget --no-check-certificate -q -U \"\" -c \"${url}\" -O /home/username/test/img.jpg`;
const out = execSync(`ssh -o ConnectTimeout=8 -o StrictHostKeyChecking=no -p 2356 username@${ip} '${cmd}'`);
但是这样使用
url
变量是很有用的,这个变量的值来自用户输入,所以我在stackoverflow上找到一些帖子说我需要使用
spawn

const url = 'https://example.com/image.jpg';

const out = spawnSync('ssh', [
    '-o', 'ConnectTimeout=8',
    '-o', 'StrictHostKeyChecking=no',
    '-p', '2356',
    `username@${ip}`,
    `mkdir -p /home/username/test; wget --no-check-certificate -q -U "" -c "${url}" -O /home/username/test/img.jpg`,
]);

如果
consturl='1,该怎么办https://example.com/image.jpg“回声5;”,将执行
echo
,有人能告诉我如何安全地执行此代码吗?

有两个方面。首先,您认为
execSync
不安全是正确的。引自:

切勿将未初始化的用户输入传递到此函数。任何包含shell元字符的输入都可用于触发任意命令执行

一个解决方案是使用
execSpawn
,如您所指出的,如中所示

但是,在您的示例中,您正在调用
ssh
并向其传递一个文本,该文本将由shell在远程系统上执行。因此,您仍然容易受到攻击,如示例中所示。但请注意,它不再是与NodeJs相关的攻击,而是对
ssh
和shell的攻击

为了减轻攻击,我建议将重点放在远程服务器上。您可以从服务器提供一个明确定义的API,而不是通过ssh向它发送命令(它应该信任并在shell中执行该命令)。在HTTP接口中,您可以接受输入并执行适当的验证(而不是简化信任)。优点是您不需要处理shell的微妙之处

如果您被迫使用ssh,您可以验证URL,并且只有在安全的情况下,才能将其转发到服务器。从安全角度来看,这仍然不理想。首先,远程服务器需要完全信任您(通常最好避免这种情况,而是尽可能在本地进行验证)。其次,验证本身并不简单。您需要确定字符串是否看起来像URL(例如,通过使用
新URL(URL)
),但更困难的方面是确保没有漏洞。我没有具体的例子,但我会谨慎地假设所有通过URL解析器的字符串都可以安全地在shell环境中执行

总之,如果可能的话,在这种情况下通过传递shell命令(由攻击者控制的输入数据),尽量避免ssh
。相反,您更喜欢HTTP接口(或其他文本或二进制协议)之类的普通API。如果不可能,请在发送数据之前尽量对其进行清理。也许您事先知道URL的外观(例如,允许的主机名列表、允许的路径等)。但是要意识到,可能有一些隐藏的例子你会忽略,永远不要低估攻击者的创造力