SFTP Chroot的开发历程
- 研究OpenSSH源码!
- 发现OpenSSH是先auth,然后chroot + setuid(如果配了ChrootDirectory的话),然后再根据session的类型调用相应的subsystem
- 问题:在走到session之前chroot所需的capability CAP_SYS_CHROOT就已经被drop了,然而我们到了session才能知道这个SSH连接到底是shell,还是scp,还是sftp
- 思路:在setuid之前,保留CAP_SYS_CHROOT权限,这样就能chroot了
- 精读OpenSSH源码
- OpenSSH在auth成功后,在do_setusercontext执行Drop privilege的逻辑
- do_setusercontext调用permanently_set_uid执行具体的setuid逻辑
- 如果是sftp的session,则在最后的逻辑调用sftp_server_main
- 开始Hook
- 首先是找到sftp_server_main函数,然后hook上,在里面执行chroot
- 然后是hook permanently_set_uid里面的setresuid函数,在setuid发生前,执行PR_SET_KEEPCAPS保留capability,然后自定义保留的Capability为CAP_SYS_CHROOT
- Debug
- 很神奇的是,在某些时机里,sshd竟然没法写入/tmp(已经排除了权限问题,即使用随机文件名都写不进去),只好xjb猜
- LightHook没处理指令重定位的逻辑,所以得写个逻辑绕开指令重定位,否则程序就crash了
- LightHook的指令长度解析有问题,所有的sub XXX, imm32都被解析成了imm64,导致长度有问题