Linux下如何安全限制交互式应用递归启动
安全实现嵌套启动限制的方案
你当前使用的环境变量标记方案完全不具备安全性:环境变量存储在进程用户态地址空间中,用户可通过unset EXTRA_SHELL、env -u EXTRA_SHELL your_app等方式随意清除、覆写该标记,直接绕过限制。
以下是按可靠性从高到低排列的可落地方案:
方案1:基于/proc文件系统的祖先进程链校验(推荐,实现简单可靠性高)
Linux系统下所有进程的父子关系、对应可执行文件路径都由内核维护,以/proc/<pid>/虚拟文件系统的形式对外暴露,普通用户无法篡改该信息,可直接作为校验依据:
- 你的应用启动时,首先校验自身是否持有控制终端:作为交互式登录shell,无控制终端的实例无交互意义,直接退出即可,同时可防范nohup/setsid脱离终端的绕过尝试。
- 从当前进程PID开始,循环读取
/proc/<current_pid>/stat文件获取父进程PID(ppid),逐级向上遍历父进程链直到PID为1的init进程。 - 遍历过程中对每一个父进程,读取
/proc/<ppid>/exe符号链接的目标路径,判断是否与当前应用的二进制路径一致。 - 如果遍历到PID=1都未找到匹配的同路径二进制,说明是登录流程拉起的合法顶层实例,正常运行;如果中途找到匹配的祖先进程,说明是在受限bash中嵌套启动的实例,直接退出。
实现注意:不要通过调用
ps命令解析输出实现校验,ps输出格式随版本、参数变化可能出现兼容问题,直接读取/proc下的内核虚拟文件稳定性、可靠性更高。
方案2:seccomp系统调用过滤(零误判,安全性最高)
如果需要更强的防护,可以在fork出子进程、exec启动bash之前,为子进程加载seccomp-bpf过滤规则:
- 拦截
execve、execveat两类执行程序的系统调用 - 读取系统调用传入的可执行文件路径,对比文件inode号与你的应用二进制的inode号,若匹配则直接返回
EPERM权限错误 - 配套将你的应用二进制文件权限设置为
-rwx--x--x,属主为root,普通用户仅持有执行权限、无读取权限,无法复制二进制文件生成新inode的副本,即可完全阻断嵌套启动的可能。
ps --forest用法说明
ps --forest的作用是以树状缩进格式打印进程的父子层级关系,你可以通过类似以下命令查看当前会话下的进程树,手动排查是否存在嵌套的应用进程:
ps --forest -o pid,ppid,cmd -s $(ps -o sid= -p $$)
但该方式仅适合手动排查问题,不适合写到代码里做自动化校验,原因是输出解析容错性差,且容易被用户通过修改ps环境变量、替换ps二进制等方式绕过。
不推荐的方案
- 环境变量标记:完全可被用户随意修改,无安全性
- 基于PID文件加锁:用户可删除锁文件绕过
- 基于会话ID判断:用户可通过
setsid命令创建新会话绕过
内容的提问来源于stack exchange,提问作者Harish Reddy
相关产品推荐
相关产品推荐

