如何使用 bash 进程替换 sftp 私钥文件?

如何使用 bash 进程替换 sftp 私钥文件?

与我的团队一起,我们需要共享一些私钥并将它们存储在经过存储库。

因此,我不是提取密钥并将其以明文形式存储在文件系统上,而是寻找一种仅将解密版本短暂保留在内存中的方法:

$ sftp -i <(pass foo) user@host
Warning: Identity file /dev/fd/63 not accessible: No such file or directory.

知道为什么 sftp 无法读取临时文件描述符吗?如何修复它?

答案1

知道为什么sftp无法读取临时文件描述符吗?

几个事实:

  • 进程<(pass foo)替换将导致bash创建一个管道,pass foo异步运行命令,其输出连接到管道的写入端,并将 替换<(...)为 形式的路径/dev/fd/63,其中63是引用管道读取端的文件描述符。
  • /dev/fd/63是一个特殊的路径,允许进程stat()重新打开其文件描述符之一引用的文件。
  • shell forks + execs sftp,然后sftp本身 forks 和 execs ssh,导致63文件描述符通过继承向下传递。
  • ssh将要关闭其所有文件描述符使用该函数的 0、1、2 除外closefrom()。这也将关闭 fd 63

由于63不再是进程中打开的文件描述符ssh,因此stat()on/dev/fd/63将失败并出现来自 OP 的错误。

如何修复它?

将密钥临时存储在内存中的文件系统中。在我的Debiansystemd下为我提供了tmpfs/run/user/<myUID>。除了我(当然还有root)之外,任何人都无法访问该挂载点。

请注意,在您的用户(或根用户)下运行的恶意进程可以读取该文件。但是这样的过程也可以从原始方法中sshd的文件描述符中读取。63

或者,当没有可用的安全 tmpfs 时:

  1. 创建临时 fifo。注意mktemp不能直接执行此操作。安全的方法是创建一个临时私有的目录然后mkfifo在里面。

  2. 确保fifo本身的权限较窄,否则ssh会报错。

  3. 跑步

    sftp -i "/temp_dir/the_fifo" user@host
    
  4. 并行运行pass foo > "/temp_dir/the_fifo"。一个怪癖:你需要这样做两次;至少在我的 Debian 中ssh读取密钥两次。以下命令似乎在我的测试中有效:cat ~/.ssh/id_rsa > "/temp_dir/the_fifo" && cat ~/.ssh/id_rsa > "/temp_dir/the_fifo"。也许类似的重复命令适合您:

    pass foo > "/temp_dir/the_fifo" && pass foo > "/temp_dir/the_fifo"
    

    您可以之前在后台运行它sftp(除非pass是交互式的,我根本不熟悉该工具)。

  5. 最后删除 fifo 和目录。

尽管如此,在您的用户(或 root)下运行的恶意进程仍然可以先从 fifo 中读取ssh数据。

相关内容