执行权限如何严格限制

wen 网络安全 25

本文目录导读:

执行权限如何严格限制

  1. 核心原则:最小权限原则
  2. 用户与组隔离
  3. 文件系统权限
  4. Linux Capabilities(能力机制)
  5. 系统调用过滤 (Seccomp)
  6. 容器与沙箱隔离
  7. 特殊的文件系统挂载选项
  8. 一份严格限制执行权限的最佳实践清单

严格限制执行权限是 Linux/Unix 系统安全的核心,一个被攻破的进程如果拥有过高的执行权限,攻击者就能轻易窃取数据、安装后门或破坏系统。

要做到“严格限制”,需要从最小权限原则用户与组隔离文件系统权限Capabilities 机制系统调用过滤以及容器/沙箱隔离等多个层面入手。

以下是核心策略和具体操作方法:

核心原则:最小权限原则

每个进程和用户只应拥有完成其任务所绝对必需的最小权限,不要给“可能用到的”权限,只给“现在就要用”的。


用户与组隔离

这是最基础也是最重要的一环。

  • 不要使用 root 运行服务: 绝大多数应用(如 Nginx、MySQL、Java 应用)都不需要 root 权限,使用 root 运行是最大的安全隐患。

  • 创建专用系统用户: 为每个服务创建独立的、没有 shell 登录权限的系统用户。

    # 创建一个系统用户 nginx,不允许登录,没有主目录
    sudo useradd -r -s /usr/sbin/nologin -M nginx
    # 创建一个系统用户 myapp
    sudo useradd -r -s /usr/sbin/nologin -M myapp
  • 权限分离: 将不同功能模块分配到不同用户下。

    • webapp 用户:运行 Web 应用代码(只读)。
    • webapp-data 用户:拥有上传目录(上传目录绝对不能有执行权限)。
    • nginx 用户:运行 Nginx 反向代理。

文件系统权限

严格使用 chmodchown 控制谁可以读、写、执行文件。

  • 精准的属主和属组:

    # 应用代码属主为 root,属组为 webapp-group
    chown -R root:webapp-group /var/www/myapp/
    # 应用代码目录权限:属主读写执行,属组读执行,其他人无权限
    chmod -R 750 /var/www/myapp/
    # 上传目录属主为 webapp-user
    chown -R webapp-user:webapp-group /var/www/myapp/uploads/
    # 上传目录权限:属主读写执行,属组读执行,其他人无权,关键:移除组和其他人的写权限!
    chmod -R 750 /var/www/myapp/uploads/
  • 不要使用 777: 永远不要设置 chmod 777,任何需要写权限的地方,都应该通过属主或属组来控制,而不是让“其他用户”都能写。

  • 慎用 SUID/SGID/Sticky Bit:

    • SUID (Set User ID): 极其危险,当一个设置了 SUID 位的可执行文件运行时,它会以文件所有者的权限运行,而不是当前用户。passwd 命令需要 SUID 才能修改 /etc/shadow除非绝对必要,否则不要给任何自定义程序或脚本设置 SUID。
    • SGID (Set Group ID): 相对安全,但也要小心,它主要用于协作目录(让新创建的文件继承父目录的组)。
    • Sticky Bit (粘滞位): 用于 /tmp 之类的共享目录,防止用户删除不属于自己的文件(chmod +t /tmp)。

Linux Capabilities(能力机制)

这是传统 SUID 的现代替代方案,也是严格限制权限的最强大工具

传统上,root 用户拥有一切能力(Capability),Capabilities 机制将 root 的超级权限分解成 40 多种独立的小权限(如 CAP_NET_BIND_SERVICE 允许绑定到低于 1024 的端口,CAP_DAC_OVERRIDE 允许绕过文件权限检查)。

使用方法: 你不需要给程序整个 root 权限,只需要给它一项或几项 Capability。

  • 场景: 你的普通用户 webapp 需要监听 80 端口(要求 root 权限)。

  • 传统做法: 用 root 启动,然后降权(依然可能被利用)。

  • 最佳做法: 直接赋予程序绑定低端口的 Capability。

    # 给 nginx 二进制文件添加绑定特权端口的 Capability
    # 注意:要设置有效的 Capability (p e i 分别代表 Permitted, Effective, Inheritable)
    sudo setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx
    # 验证
    getcap /usr/sbin/nginx
    # 输出:/usr/sbin/nginx = cap_net_bind_service+ep
  • 常用 Capabilities 及用途:

    • CAP_NET_BIND_SERVICE:绑定到小于 1024 的端口。
    • CAP_DAC_OVERRIDE:绕过文件读写权限检查(非常危险)。
    • CAP_CHOWN:修改文件属主(危险)。
    • CAP_KILL:发送信号给任何进程。
    • CAP_SETUID / CAP_SETGID:设置用户/组 ID。

系统调用过滤 (Seccomp)

这是内核层面的终极防御,Seccomp (Secure Computing Mode) 允许你限制一个进程可以使用的系统调用。

即使程序被攻破,攻击者也无法执行 fork()execve()open() 等危险系统调用来提权或执行新代码。

  • 如何实现:

    • 编程方式: 使用 prctl()seccomp() 系统调用编写 BPF (Berkeley Packet Filter) 规则。
    • 工具库: libseccomp 提供了方便的 C API。
    • Docker/容器: Docker 和 Podman 默认会为容器应用一个安全的 Seccomp 配置文件,你可以在 docker run 时使用 --security-opt seccomp=profile.json 自定义配置文件。
  • 实践示例(Docker):

    # 使用默认的 seccomp 配置文件(会阻止 44 个危险系统调用)
    docker run --security-opt seccomp=default.json alpine sh
    # 创建一个更严格的配置文件 my-seccomp.json,只允许 read, write, exit, getpid
    # 然后运行容器:
    docker run --security-opt seccomp=my-seccomp.json myapp

容器与沙箱隔离

容器(如 Docker、Podman)和沙箱(如 Firejail、Bubblewrap)通过 Namespace 和 Cgroups 提供了一层极强的隔离。

  • 容器隔离: 每个容器有自己的 PID、网络、挂载点等 Namespace。

    • 避免以 --privileged 运行: 这会关闭所有隔离,赋予容器几乎与宿主机 root 同等的权限。
    • 使用只读文件系统: docker run --read-only myapp,将应用代码和数据目录挂载为只读,只有 /tmp 或上传目录可写。
    • 禁用 Capabilities: docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myapp
  • 沙箱隔离: Firejail 可以让你以普通用户运行任何程序,并限制其对文件系统、网络和进程的访问。

    # 运行 Firefox,限制其访问家目录以外的文件
    firejail --private=~/firefox-data firefox
    # 运行一个无法访问网络的程序
    firejail --net=none /usr/bin/myapp

特殊的文件系统挂载选项

在挂载文件系统或目录时,可以使用 noexecnosuidnodev 选项来限制可执行文件的运行。

  • 场景: 挂载 /tmp 目录或上传目录时。

    # 在 /etc/fstab 中
    /dev/sdaX /tmp ext4 defaults,nosuid,noexec,nodev 0 0
    # 或使用 mount 命令(临时)
    sudo mount -o remount,nosuid,noexec,nodev /tmp
    • noexec:禁止从此文件系统执行任何二进制文件或脚本。
    • nosuid:忽略此文件系统上的 SUID/SGID 位。
    • nodev:不解释此文件系统上的块设备文件。

一份严格限制执行权限的最佳实践清单

  1. 绝不使用 root 运行非必要服务。
  2. 为每个服务创建独立、无 shell 的系统用户。
  3. 严格文件权限: chmod 750640,避免 777 和 755,精确控制写权限
  4. 用 Capabilities 替代危险的 SUID 脚本: 只授予程序完成任务所需的最小能力。
  5. 启用 Seccomp: 在容器或通过工具(如 nsjail)限制系统调用。
  6. 使用容器隔离: 运行 --read-only--cap-drop=ALL--security-opt seccomp=...
  7. /tmp、上传目录等可写目录挂载 noexec
  8. 定期审计: 使用 ps aux 检查进程运行用户,使用 find / -perm /4000 查找 SUID 文件,使用 getcap -r / 查找设置了 Capabilities 的文件。

通过结合以上策略,你可以将攻击面缩小到最小,即使某个服务被攻破,攻击者也无法轻松地横向移动或提权,从而获得整个系统的控制权。

抱歉,评论功能暂时关闭!