// 安全研究 · 2026-06-14

Linux 权限切换工具:setpriv 与 newgrp

引言

在 Linux 系统管理中,权限控制是安全体系的核心。当你需要以特定用户身份运行程序、临时切换用户组,或是精细控制进程权限时,setpriv 和 newgrp 分别代表了“精细化权限控制”和“会话级组切换”两条不同的技术路线。本文将深入介绍这两个命令的使用方法、工作原理和典型应用场景。


一、setpriv:精细控制进程权限

1.1 命令概述

setpriv 是 util-linux 包中的一个工具,允许用户在运行程序时设置或查询各种 Linux 权限参数。与传统的 su 或 sudo 不同,setpriv 既不使用 PAM(可插拔认证模块),也不会提示输入密码,它是一个简单的、非 set-user-ID 的 execve 包装器。

核心特点:

  • 不依赖 PAM,无密码交互
  • 可以精确控制 UID、GID、能力集等权限参数
  • 支持 Linux 安全模块(LSM)如 SELinux、AppArmor
  • 支持 no_new_privs 等内核安全特性

1.2 进程凭证管理

flowchart TB
    subgraph ProcessCredentials[进程凭证体系]
        UID[UID 凭证]
        GID[GID 凭证]
        Caps[能力集 Capabilities]
        Other[其他安全属性]
    end
    
    subgraph UIDDetails[UID 类型]
        RUID[Real UID<br/>真实用户ID]
        EUID[Effective UID<br/>有效用户ID]
        SUID[Saved UID<br/>保存的用户ID]
    end
    
    subgraph GIDDetails[GID 类型]
        RGID[Real GID<br/>真实组ID]
        EGID[Effective GID<br/>有效组ID]
        SGID[Saved GID<br/>保存的组ID]
        SuppGID[Supplementary GIDs<br/>附加组列表]
    end
    
    subgraph CapDetails[能力集类型]
        Perm[Permitted<br/>允许的能力]
        Inherit[Inheritable<br/>可继承的能力]
        Effective[Effective<br/>有效的能力]
        Ambient[Ambient<br/>环境能力]
        Bounding[Bounding Set<br/>边界集]
    end
    
    UID --> UIDDetails
    GID --> GIDDetails
    Caps --> CapDetails

setpriv 可以精确设置上述所有凭证类型。这种细粒度控制是实现最小权限原则的关键工具。

1.3 用户 ID 与组 ID 设置

设置用户 ID

使用 --ruid、--euid 或 --reuid 选项可以分别设置真实用户 ID、有效用户 ID 或同时设置两者:

# 切换到用户 alice(同时设置真实和有效 UID)
setpriv --reuid=alice id

# 仅设置有效 UID
setpriv --euid=bob whoami

设置组 ID

类似地,使用 --rgid、--egid 或 --regid 设置组 ID:

# 切换主要组到 developers
setpriv --regid=developers --init-groups id

# 设置附加组
setpriv --groups=staff,admin --regid=developers id

安全注意事项: 当你设置任何主要组 ID 时,必须同时指定 --clear-groups、--groups、--keep-groups 或 --init-groups 之一来明确附加组的处理方式。

同时管理 UID/GID :

# 以指定用户运行程序(类似 su,但无PAM)
setpriv --reuid=1000 --regid=1000 --init-groups /bin/bash

# 同时设置真实和有效UID/GID
setpriv --reuid=www-data --regid=www-data --clear-groups /usr/sbin/nginx

# 指定辅助组
setpriv --reuid=1000 --regid=1000 --groups=audio,video,plugdev /bin/bash

1.4 能力集管理

Linux 能力(Capabilities)将 root 用户的特权细分为独立单元,允许进程仅获得所需的特定权限。

# 查看所有可用能力
setpriv --list-caps

# 移除所有继承能力(降权运行)
setpriv --inh-caps=-all --reuid=nobody --regid=nogroup /bin/bash

# 添加特定能力
setpriv --ambient-caps=+cap_net_bind_service /usr/bin/myserver

# 从边界集中移除能力
setpriv --bounding-set=-cap_sys_admin,-cap_sys_ptrace /bin/bash

# 保留特定能力
setpriv --inh-caps=+net_raw,+cap_dac_override ./tcpdump

能力集操作语法:

  • +cap_name:添加能力
  • -cap_name:移除能力
  • +all / -all:添加/移除所有能力

重要限制: 向边界集(bounding set)添加能力是不可能的——这是内核层面的硬性限制。如果你从边界集中移除了某个能力,务必同时从可继承集中移除它,否则会导致配置混乱。

1.5 高级安全特性

no_new_privs 位

设置 --no-new-privs 后,进程及其子进程将无法通过 execve 获得新权限。这意味着 setuid/setgid 位和文件能力将被禁用:

setpriv --no-new-privs --reuid=nobody ./untrusted-program

这个特性对于运行不可信代码至关重要,自 Linux 3.5 起支持。

Landlock 沙盒

Landlock 是 Linux 内核的安全模块,允许非特权进程创建安全沙盒:

# 阻止所有文件系统访问
setpriv --landlock-access fs ./sandboxed-app

# 阻止文件删除和目录创建
setpriv --landlock-access fs:remove-file,make-dir ./restricted-app

# 允许读取 /boot 目录下的文件
setpriv --landlock-access fs --landlock-rule path-beneath:read-file:/boot ./reader

seccomp 过滤

通过 --seccomp-filter 可以加载 BPF 过滤器来限制系统调用。

1.6 setpriv 最佳实践

flowchart LR
    subgraph BestPractices[最佳实践场景]
        S1[服务降权<br/>删除root权限启动守护进程]
        S2[沙盒执行<br/>隔离不可信代码]
        S3[能力修剪<br/>仅保留必要权限]
        S4[环境重置<br/>清除污染环境变量]
    end
    
    subgraph Example[命令示例]
        E1["setpriv --reuid=www-data --regid=www-data<br/>--init-groups --inh-caps=-all nginx"]
        E2["setpriv --no-new-privs --reuid=nobody<br/>--reset-env ./untrusted"]
        E3["setpriv --inh-caps=+net_admin<br/>./privileged-app"]
        E4["setpriv --reuid=1000 --reset-env bash"]
    end
    
    S1 --> E1
    S2 --> E2
    S3 --> E3
    S4 --> E4

典型场景示例:

  1. 服务进程权限降级:
setpriv --reuid=www-data --regid=www-data --init-groups --inh-caps=-all nginx
  1. 安全沙盒执行:
setpriv --no-new-privs --reuid=nobody --regid=nogroup --clear-groups ./untrusted
  1. 环境重置:
setpriv --reset-env --reuid=1000 bash

二、newgrp:临时切换用户组

2.1 命令概述

newgrp 命令允许用户在登录会话中临时切换当前组 ID。它在不退出当前会话的情况下,更改用户的真实组 ID(RGID),并尝试将该组添加到用户的附加组集合中。

核心机制:

  • 启动一个新的 shell 实例,使用新的组身份
  • 退出新 shell 后恢复原始组设置
  • 支持组密码验证(如果用户不是组成员)

2.2 工作流程

flowchart TD
    Start[用户执行 newgrp group] --> Check{用户是<br/>组成员?}
    
    Check -->|是| Change[切换到目标组]
    Check -->|否| PassCheck{组有密码?}
    
    PassCheck -->|有密码| Prompt[提示输入组密码]
    PassCheck -->|无密码| Deny[拒绝访问]
    
    Prompt --> PassVerify{密码正确?}
    PassVerify -->|正确| Change
    PassVerify -->|错误| Deny
    
    Change --> NewShell[启动新 shell<br/>RGID = 目标组]
    NewShell --> Exit[用户执行 exit]
    Exit --> Restore[恢复原始组身份]
    
    Deny --> End1[保持原组]

2.3 基本用法

# 切换到 developers 组
newgrp developers

# 切换回用户默认组(无参数)
newgrp

# 使用 "-" 选项重新初始化环境(类似重新登录)
newgrp - developers

# 在指定组下执行单个命令(util-linux 版本支持)
newgrp developers -c "touch /tmp/shared-file"

2.4 密码验证机制

newgrp 的密码验证遵循以下规则:

  1. 如果用户已经是组成员,直接切换,无需密码
  2. 如果用户不是组成员且组有密码,提示输入密码
  3. 如果用户不是组成员且组没有密码,拒绝访问
  4. 密码从 /etc/gshadow 或 /etc/group 读取

2.5 相关命令对比

命令 作用范围 权限要求 使用场景
newgrp 当前 shell 组成员或有组密码 临时以其他组身份创建文件
sg 单个命令 同 newgrp 以指定组执行单个命令
sudo -g 单个命令 sudo 权限 需要 root 授权的组切换
setpriv --regid 指定程序 root 或相应能力 服务/进程权限控制

三、实际应用场景

3.1 服务进程沙盒化

#!/bin/bash
# 以最小权限运行 Web 服务

setpriv --reuid=httpd \
        --regid=httpd \
        --init-groups \
        --inh-caps=-all \
        --no-new-privs \
        --reset-env \
        /usr/sbin/httpd -DFOREGROUND

3.2 协作目录管理

# 场景:开发团队共享目录
# 用户 alice 需要创建属于 project 组的文件

alice@host:~$ newgrp project
alice@host:~$ touch shared-file.txt
alice@host:~$ ls -l shared-file.txt
-rw-r--r-- 1 alice project 0 Dec 15 10:30 shared-file.txt
alice@host:~$ exit

3.3 能力集限制实践

# 仅允许进程使用原始套接字(ping 命令)
setpriv --inh-caps=+cap_net_raw \
        --reuid=nobody \
        --regid=nogroup \
        --clear-groups \
        /bin/ping -c 1 8.8.8.8

四、注意事项与最佳实践

setpriv 安全警告

  1. 能力集一致性: 从边界集移除能力时,必须同时从可继承集中移除,否则会导致不可预测的行为
  2. LSM 交互: 设置 no_new_privs 可能会影响 SELinux/AppArmor 策略的执行
  3. root 权限处理: 从 root 切换普通用户时,通常需要同时丢弃所有能力:
setpriv --reuid=1000 --regid=1000 --inh-caps=-all

newgrp 使用建议

  1. 组密码管理: 避免使用组密码,优先将用户添加到所需组
  2. 使用 - 选项谨慎: 该选项会重置环境变量和当前目录,可能造成意外
  3. 单命令执行: 如需只执行单个命令,优先使用 sg 命令

总结

setpriv 和 newgrp 是 Linux 权限管理的两个不同层次的工具:

  • setpriv 提供精细的进程权限控制,是服务降权、沙盒实现和安全加固的首选工具。它支持 UID/GID 切换、能力集管理、Landlock 沙盒、seccomp 过滤等现代 Linux 安全特性。

  • newgrp 专注于组身份切换,是团队协作和临时文件权限管理的便捷工具。它简单直观,适合交互式使用场景。

理解并善用这两个工具,能够帮助系统管理员更好地贯彻“最小权限原则”,构建更加安全的 Linux 系统环境。

原文 https://blog.csdn.net/2301_79518550/article/details/161903494