如何使用 Net::OpenSSH 安全地写入远程文件
How to safely write to a remote file using Net::OpenSSH
假设应用程序服务器从客户端接收二进制 blob 并将其写入远程主机上的文件。
client -(HTTP)> application server -(SSH)> remote data host
鉴于文件名是来自客户端的用户输入,(应用程序)服务器必须做些什么来防止攻击(目录遍历攻击)?
用于连接到远程主机的用户帐户有一个主目录 /home/datauser
,不应访问其主目录以外的任何内容。
这是代码:
# User input
my $name = ...; # bob's car.jpg
my $dir = ...; # pics/vacation "country"/
# Slashes are illegal
die "Illegal dir" if ($dir =~ /\.\.\//); # ../ is an attack
die "Illegal name" if ($name =~ /\//); # / in file name is an attack
# Escape single quotes
my $safe_path = $dir.$name;
$safe_path =~ s/'/'\''/g;
# my $ssh = Net::OpenSSH->new(...);
my $root_dir = '/home/datauseruser';
my $cmd =
"cd '$root_dir' && ".
"cat >>'$safe_path'";
$ssh->system({stdin_data => $bytes}, $cmd);
这是一个好方法吗?还有更多漏洞吗?
注意:需要随机访问,所以不能使用scp。
通过 SSH 连接发送内容的主要潜在安全问题是远程 shell 是不可避免的。换句话说,每次你要求 SSH 执行一个命令,而不是仅仅 fork+exec
给定的命令 (@CMD
),它实际上调用了一个 shell ($LOGIN_SHELL -c $CMD
), 因此必须正确引用命令参数。
你已经在自己引用了,代码对我来说似乎是正确的。但无论如何,你可以让 Net::OpenSSH 为你做这件事而不必担心:
my $safe_path = $ssh->shell_quote($path);
$ssh->system("cat >>$safe_path");
最后,实际上,有一种方法可以避免 shell:使用 SFTP。
Net::OpenSSH 与 Net::SFTP::Foreign 集成,您可以使用它轻松访问远程文件系统。
假设应用程序服务器从客户端接收二进制 blob 并将其写入远程主机上的文件。
client -(HTTP)> application server -(SSH)> remote data host
鉴于文件名是来自客户端的用户输入,(应用程序)服务器必须做些什么来防止攻击(目录遍历攻击)?
用于连接到远程主机的用户帐户有一个主目录 /home/datauser
,不应访问其主目录以外的任何内容。
这是代码:
# User input
my $name = ...; # bob's car.jpg
my $dir = ...; # pics/vacation "country"/
# Slashes are illegal
die "Illegal dir" if ($dir =~ /\.\.\//); # ../ is an attack
die "Illegal name" if ($name =~ /\//); # / in file name is an attack
# Escape single quotes
my $safe_path = $dir.$name;
$safe_path =~ s/'/'\''/g;
# my $ssh = Net::OpenSSH->new(...);
my $root_dir = '/home/datauseruser';
my $cmd =
"cd '$root_dir' && ".
"cat >>'$safe_path'";
$ssh->system({stdin_data => $bytes}, $cmd);
这是一个好方法吗?还有更多漏洞吗?
注意:需要随机访问,所以不能使用scp。
通过 SSH 连接发送内容的主要潜在安全问题是远程 shell 是不可避免的。换句话说,每次你要求 SSH 执行一个命令,而不是仅仅 fork+exec
给定的命令 (@CMD
),它实际上调用了一个 shell ($LOGIN_SHELL -c $CMD
), 因此必须正确引用命令参数。
你已经在自己引用了,代码对我来说似乎是正确的。但无论如何,你可以让 Net::OpenSSH 为你做这件事而不必担心:
my $safe_path = $ssh->shell_quote($path);
$ssh->system("cat >>$safe_path");
最后,实际上,有一种方法可以避免 shell:使用 SFTP。
Net::OpenSSH 与 Net::SFTP::Foreign 集成,您可以使用它轻松访问远程文件系统。