关注了就能看到更多这么棒的文章哦~
Deprecating scp
By Jonathan Corbet
November 5, 2020
DeepL assisted translation
https://lwn.net/Articles/835962/
使用 SSH 协议在多台机器之间复制文件的 scp 命令,已经变成许多 Linux 用户和开发者的手指记忆非常熟悉的命令了。尤其是许多人仍然认为它是比 rcp 更安全方案。许多用户可能会惊讶地发现,scp 与 rcp 的相似之处不仅仅是名字,很多底层协议也是一样的。这个协议已经挺古老了,OpenSSH 社区一段时间之前就已经将其判定为 deprecated 状态,打算废弃了。不过,目前还是很难找到一种让用户满意的方式来取代 scp。
scp 和之前的 rcp 一样,设计时都希望尽可能地像普通的 cp 命令。它有一个相对简单的、可用在脚本脚本中的命令行界面,这使得递归复制和多文件复制变得很简单。在机器之间进行连接时使用 SSH 认证机制,并在数据传输过程中确保数据进行了加密,所以一般都认为它是安全的协议。但事实证明,在某些情况下,尤其是链路两端之间信任度不高,或干脆没有信任度的情况下,实际上达到的安全程度可能会低于预期。
例如,在 OpenSSH 8.0 版本中就包含了一个被称为 CVE-2019-6111 的漏洞的 fix。在 scp 协议中,要复制的文件所在的这台机器需要把这些文件的名子发送给接收方。所以可以输入这样的命令:
$ scp admin:boring-spreadsheet.ODS .
按理来说就会在当前工作目录下得到一个名为 boring-spreadsheet.ods 的文件。如果远程服务器给出的回应类似 "这是你所要的.bashrc 文件 " 的话,scp 会傻乎乎地把.bashrc 文件给覆盖了。8.0 版本中,会比较远端的文件名和实际请求的文件名,从而避免这个问题,但 release note 里面也声明 scp 协议是 "过时、不灵活、不易修复"的,并建议今后不要再使用 scp。
还有一个 CVE-2020-15778 (https://github.com/cpandya2909/CVE-2020-15778/) 也可以介绍一下。大家都知道 scp 是建立在 SSH 上的,所以如果键入一个命令:
$ scp election-predictions.txt dumpster:junk/
就会建立一个 SSH 连接到 dumpster,运行这个命令:
scp -t junk/
该命令使用文档中没有提到的-t 选项来指定一个目标("to")目录,然后会来完成这个传送文件到 junk 目录的请求。这种机制就可以被各种恶作剧所利用了。试试看:
$ scp some-local-file remote:'`touch you-lose`remote-file'
这会在远程系统上创建 两个 文件:一个是我们希望创建的 remote-file,另外是一个名为 you-lose 的空文件。读者可以自行尝试在该文件中添加更多实际内容来完成想做的事情。
这种行为是否属于漏洞(vulnerability),这是个见仁见智的问题。如果用户有普通的 SSH 访问远程系统的权限,那么通过 scp 附带一些命令则只是一种以更麻烦的方式来做他本可以直接做的事情。不过很显然,有些网站其实只是希望提供 scp 访问来让用户复制文件,但不允许用户在这个系统上随便执行命令。对于这些系统来说,这种行为就算是一个漏洞了。最后,虽然只有对端服务器才有这个风险,但值得注意的是,本地文件名中包含反引号的话(例如名为 `touch you-lose` 的文件),在远端也可以同样来伤害你。只要能说服一个用户对包含恶意名称文件的目录进行递归复制,就会引发这些破坏性的结果。
与 CVE-2019-6111 不同的是,这个问题还没有被 OpenSSH 开发者解决。正如上面链接的披露信息中所说,开发者的看法是:
scp 命令使用的是一个历史悠久的协议(rcp),它依赖于这种风格的参数传递,并遇到了这些扩展(expansion)问题。事实证明,让 scp 模型变得 "security" 是非常困难的。所有 "检测" 和 "防止" 异常参数传递的改动,都很可能会破坏现有的能正常工作的流程。是的,我们承认它的情况很糟糕。但我们不想破坏人们使用 scp 时感受到的易用性,除非有一个通用的替代方案。
既然如此,下一个问题就自然而然地出现了:应该用什么来替代被废弃的 scp 命令?这个问题的通常答案是 sftp 或者 rsync。
sftp 命令的优点是它是 OpenSSH 软件包的一部分,因此,大多数地方都安装了 scp。缺点则是不太友好的用户体验,特别是当你只想输入一个命令就能完成文件移动的时候,如果只是简单用下面的命令:
$ sftp * remote:
并不能达到期望的效果。有些用法需要进入 "交互模式",这对于我们这些曾经使用 FTP 传输文件的老用户来说是很熟悉的,同样我们这些老人也仍然还记得为什么我们一看到有 rcp 和 scp 这样的命令就从 FTP 转向了它们。
rsync 是一个可行的替代方案,它的优点是比 scp 性能更好,毕竟 scp 的速度本身并不是特别快,但 rsync 不像 SSH 套件中的那些命令那么普及。它的 GPLv3 license 也让某些类别的用户望而却步。即使是系统已经安装好了 rsync 的时候,人们也总觉得它更像是一个用来做大事的强大工具,而 scp 则是手边的瑞士军刀,足够满足多数场景的需求了。
然后,还有一个简单的问题,就是 scp 已经深深地融入了很多用户的肌肉记忆中。就像其他被废弃的命令一样(ifconfig 就是个例子),很难做出改变。
基于这些原因,如果能有一个新版本的 scp 命令,不受当前问题的影响,那就最好了。事实上 Jakub Jelen 正在研究这样一个东西;它是一个 scp 命令,不过内里其实使用的是 sftp 协议。目前,据称它可以适用于大多数基本的使用场景,有些 option(比如 -3 这样的通过本地机的方式在两个远程主机之间复制文件)则并不支持。像上面说的反引号扩展这类的 "功能" 也不会被支持,尽管有些用户显然认为这种扩展也有合法用途。
Jelen 最近提议把 Fedora 发行版中的 scp 换成他的版本,大多数人都给出了赞成意见。确实有一些用户担心 sftp 可能会比 scp 更慢,但似乎没人做严格的性能测试。即使是慢了一点,可是一个既能避免当前实现中的安全问题,又不破坏现有脚本(和用户缺省习惯)的 scp 实现,应该会是一个受欢迎的改动。也许终于可以又卸下一个来自 1980 年代的包袱了。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~