如何保护 $HOME/.ssh

2022-03-18 11:17:20 +08:00
 0o0O0o0O0o
/t/841188

以普通用户权限运行的程序也可以读取修改它们,有什么简单的操作可以避免这一点吗?
6365 次点击
所在节点    Linux
51 条回复
codehz
2022-03-18 12:57:05 +08:00
@0o0O0o0O0o 那你这个和单独开一个用户跑跳板没啥区别了(仔细想想你 docker 究竟隔离了什么)
yanqiyu
2022-03-18 13:01:11 +08:00
ssh key 放到硬件里面,openssh 支持 pkcs11 或者是 fido2 的硬件来存储证书,这才能做到万无一失,私钥谁也拿不到,要用私钥签名必须要用户按一下硬件按钮 /输入 pin

其他各种方式都会带来麻烦,比如 SELinux 的话你就需要给整个用户会话一个单独的上下文(默认情况下是 unconfined_t ),以及给 ssh 一个单独的上下文,分别配置权限。当然,对于系统服务的限制早就有 SELinux 的解决方案了,用户的 .ssh 文件夹是 ssh_home_t,多数系统服务的上下文(e.g. init_t)没权限访问。

要是用 systemd 的话如果你限制整个用户会话访问 ~/.ssh 那你启动的 ssh 也访问不了。你要是只限制系统服务也很简单,ProtectHome 就行,但是不够,用户自己运行有问题的程序你也没办法。
jim9606
2022-03-18 13:13:09 +08:00
Linux 确实没有比较靠谱的通用的平台凭据保护方案,靠谱的可能得靠专门的安全硬件( TPM 或者 FIDO 之类的)
我的建议是密钥设一个 KDF 循环次数较高的加密(例如 1000 ,解密要几秒),然后首次使用 ssh 前先 ssh-add 托管到 ssh-agent 。
```
ssh-keygen -p -f ~/.ssh/id_ed25519 -a 1000
```
654656413245
2022-03-18 13:15:47 +08:00
chroot
namespace
hwdef
2022-03-18 14:06:40 +08:00
都在说 linux ,,也想问下 macos 和 windows 要怎么办
vone
2022-03-18 14:36:30 +08:00
passphrase
libook
2022-03-18 15:06:06 +08:00
Linux 权限机制是以用户、用户组来管理权限,那么权限设计思路应该是确保每个用户、用户组只能干自己能干的事情。

$HOME/.ssh 是属于当前用户的,所以理应让当前用户可读、可改,题主要解决的问题是如何不让当前用户读写它自己的文件,而是应该确保这个用户的.ssh 里面没有这个用户不应该访问的文件。

一种处理方式是不以当前用户来使用 SSH 相关功能,需要使用 SSH 相关功能的时候切换到另一个用户;
或者让不应该访问此用户文件的程序以其他用户来运行。
tomychen
2022-03-18 16:08:53 +08:00
你的意思是想让“我”访问不了“我的文件”?这逻辑,好像有点不太对。

那能不能换个思路,让“其他”人访问不了“我的”文件。


为啥不考虑一下像很多服务一样添加一个新的服务用户如 mysql 和组,再配上 chroot 也算已经很 OK 了。

实在懒也可以用 nobody

事情上很多发行的 linux 在用户权限上已经做得很好了,也相对比较人性化了。
更多的时候是权限滥用引发的事故,而把责任归到操作系统上,这锅让操作系统背,是有点无辜的。
FrankHB
2022-03-18 16:26:54 +08:00
@libook UNIX 这种思路(包括管这种用户自行可以覆盖的 DAC 机制叫“权限”)很烂。多用户本来只是为了在系统中分配任务资源;就算是持久资源,owner 决定的也仅仅只是资源的生死(创建 /删除),rw 与其说是权限还不如说就只是个访问属性,而 x 根本就是个给 shell 偷懒用的标记。这些东西根本就算不上什么安全特性。
要考虑安全就不能依赖这种防君子不防小人的做法(你一个用户根本没法审计程序运行时会干什么)。这种情况就应该让专业的上,比如基于 MAC 的 SELinux 之类的玩意儿,然后限制程序可以访问的上下文。这类解决方案的 UI 的渣体验就是另一回事了。
libook
2022-03-18 16:54:10 +08:00
@FrankHB #29 工具的特性就是这个样子的,怎么用取决于使用者,简单需求可以用简单方法来实现,复杂需求也可以考虑复杂方案,还有 Cgroup 、虚拟机等方案可以考虑。

我个人是认为,在日常使用过程中的大部分需求都可以用 Unix 这套来满足了,使用成本也比较低,剩下的特殊需求值得花些成本用更复杂方案来,只要用户能有个清晰合理的规划。
tomychen
2022-03-18 17:14:15 +08:00
@FrankHB 这杆子挥得有点狠...
从历史层面上来讲也确实是先有 DAC ,而后引入的 MAC ,这并没什么毛病,而从设计年代上来讲也并没什么毛病。

而从使用者的角度而言,是使用 DAC 还是 MAC ,这得使用者,也是用户本身去评估,就像 linux 已经用了 SELinux ,但并没有强制用户去使用,这也是有原因。

在用户的使用颗粒并没达到 MAC 时,强制去推行,那让非专业的用户使用起来,只是一种负担。
反之,就是强制让对安全敏感的用户去用 DAC ,只会让他们无法相信这种模式能够保证自己的数据安全。

所以抛开场景去谈论这个确实有点不公平。

而操作系统本身就是,只是保证系统运行的稳定性,健壮性,和合乎逻辑性。

再者别忘了 Unix 的初衷 KISS
sampeng
2022-03-18 17:52:21 +08:00
这机器和 linux 有什么关系。。。你到底是让其他人进来还是不让其他人进来???
这机器干嘛用的?很多研发公用一台服务器?虚拟化就是了啊。。。
james122333
2022-03-18 18:31:53 +08:00
@FrankHB

越来越喜欢 DAC MAC 的复杂度有没有漏洞你都不知道
x 对于文件是可执行 对于目录是可进入 而且八楼说的对
0o0O0o0O0o
2022-03-18 18:34:31 +08:00
@sampeng 不是服务器,是笔记本上的桌面版,日常使用,我很难做到按用户隔离。。。
FrankHB
2022-03-18 19:32:30 +08:00
@tomychen @james122333 关键问题是所谓的访问控制本来就不应该是安全特性。
一般意义上任何可预期的访问都涉及访问控制,并且没有特定的规则的限制,默认就是 DAC 。
事实上非安全上下文的访问控制普遍存在各种具有一定抽象能力的可编程上下文中。例如 C++ 和 Java 之类的所谓 OOP 语言中,private 这样的关键字就用来提供基于名称检查的数据访问控制的限制,你能把它当作“安全”么。
这种基于名称检查的访问控制是为了实现信息隐藏来提供封装性。从这个意义上来讲,所谓的就是利用名称访问资源的日常操作的一部分,只要不是检查就不用强调。
并且,不管是不是系统安全的目的,实际上还有更靠谱的:直接不提供可见的名称,连检查都不用。(例如,包括基于求值环境的隐藏,或者弱化一点,ES 的 WeakMap 之类: https://github.com/tc39/proposal-class-fields/blob/main/PRIVATE_SYNTAX_FAQ.md#how-can-you-model-encapsulation-using-weakmaps 。)

在信息安全上下文的上下文,管理资源的 API 经常退化为 UI (例如 shell 命令),处理的输入限制也弱很多(例如 VFS 路径相对一般 PL 里的引用),这里的相关设计体现出在想象力就弱上许多,也更依赖具体名称限定的少数检查入口,以至于会滥用半吊子解决方案。
对用户来说,尽管 DAC 无处不在,去在乎权限位这种多数情况就是自欺欺人的机制只是浪费精力。

UNIX 的 FS 的这种设计其实就是附加了一些元数据,让 VFS 的系统调用保证可以获取。
这种实现手段是整体容易批判的:比一般编程机制的手段(比如说,类型系统)弱得实在发指而不成提供。
无能性首先体现在因为大部分情况下用户就不会关心这个,却又时常被坑;真要关心的时候,却又经常不顶用,而不得不指望另外的像样的 MAC 和审计措施来补救。
一部分代价跟用户是否容易误操作无关。比如,我凭什么要忍受 FS 多占用一个位来允许 drw- 这样没卵用的组合呢?(我知道扇区存储的磁盘不用纠结空间浪费,但是 tar 一下还是可以有感知的。)
并且,这还可能真的使用户增加看似便宜,实际坑爹的误操作的机会,像 chmod -R 777 这种低成本一键搞砸系统的冗余手段;如果说 rm -rf 姑且算是管理系统资源的必要手段的滥用,这就算是凭空多出来的 side channel 了。
另一方面,这种元数据就算留着,也没什么扩展性。类似的简单水平扩展,如 sticky bit ,也就是另外附加,而不是取代鸡肋设计。结果,整个设计还是同样的馊味。

于是,这样的设计,就日用来说,基本上还不如没有。如果非要实现现有 UNIX 权限位类似的功能,大可以让像样的实现(如系统级 MAC )来作为基础,重新建立适当的 UI 。
遗憾的是,不管是 SELinux 还是 NT 安全性模型,这些系统级设计都过于依赖系统机制自身,也没有充分的 UI 来让用户便于使用。但我不认为这是个安全性原则问题;易用性上的尴尬是产品力缺失的表现。

那么,为什么 UNIX 的 VFS 会特别明显地暴露这类缺陷?这恐怕根本就不是安全设计或者“用户”应该代表什么的个别问题,而是更一般意义上的“哲学”出了岔子,导致各种抽象都和开始的原意若即若离地背离,却又无法甩脱兼容性而一直被滥用。这种鸡肋抽象,最典型的就是“文件”:
cf. https://github.com/FrankHB/pl-docs/blob/master/zh-CN/about-operating-systems.md#%E4%B8%80%E5%88%87%E7%9A%86%E6%96%87%E4%BB%B6everything-is-a-file
在用户空间滥用“文件”作为首要的操作实体,与其说这是简化用户的手续(不用去学 PL 而只用学 shell ;不用认真了解怎么折腾 API 去避免非预期行为而只要等待 CLI 的反馈),倒不如说是系统设计者没能力把两种面向不同用户的可编程手段统一起来。
更一般地,这表现在对“无名师和万行码”的吹捧上——表面上看,是让 shell 干 shell 该干的活,让 C 不要掺和,属于使用合适的工具完成任务的典范;而事实上,这只是掩盖了 UNIX 祖师没能力发明出涵盖 shell 编程和更严肃的“系统”编程的统一接口而已。
比如,要是当年有像 scsh 类似的实现,现在可能就不会坚持 pid_t 乱飞导致僵尸进程这种层次的设计问题暴露给系统管理员添堵了。
FrankHB
2022-03-18 19:47:31 +08:00
@tomychen 出现的先后不是重点。而推行的实际复杂度或者说代价对非专业用户来讲,很多情况只是错觉。
如果基于上下文的机制有像样的实现,完全可以让用户感知不到复杂性,并且可能简化自动管理和修复安全规则问题的 demon 实现,而避免绝大多数系统管理员还要手动处理文件权限之类的问题,反而能整体削减用户的成本。

这在其它领域中存在先例。大部分非研究者的普通开发者认为,在动态 PL 中实现静态的词法作用域因为需要单独管理更多的上下文而不易高效实现,因此即便知道显著缺陷(但“又不是不能用”),大多数动态语言的设计者和用户还是接受继续使用动态作用域。
尽管大约 1954 年就出现了一般的解决方案(闭包),直到 1980 年代 Scheme 的高效实现才让主流开发者认识到代价到底可以怎样被有效控制。这之后大部分语言都不再采用默认动态作用域的设计。

这个领域面临的问题类似:现有的机制看上去有时候能用,就被姑息了;而更完善或者说原则上更正确的方案因为少人使用,而仅限于少数专业玩家才会考虑使用,结果不够易用。这种情况迟早应被改变。
FrankHB
2022-03-18 19:51:55 +08:00
@FrankHB typo ,闭包是 1964 年前后出现的( SECD machine, P. Landin )。
james122333
2022-03-18 20:56:34 +08:00
@FrankHB

访问控制是安全特性之一 为何要允许不可预期状况出现? 而且说的不就是实现方式差异而已 你觉得限制多好但有侯灵活性以及易用性也很重要 看这回文大概知道你是 lisp 系的 但为何类型就是系统安全保证呢? 依照现今状况不是如此吧。 而且说的 777 那是人被忽悠的问题 流行的是另一种照常可以忽悠 必定提供类似的机能
james122333
2022-03-18 21:18:13 +08:00
我都不觉得一个语言只能有一个用途 但你不能要求人人都是程序员 lisp 来讲是如此
james122333
2022-03-18 21:31:06 +08:00
@FrankHB
你还是得处理文件权限 不管你是规则 代码还是命令

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/841221

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX