当前位置: 首页 > news >正文

Linux权限机制:RUID/EUID/SUID与进程安全

当普通用户修改自己的密码时,为何能写入受保护的/etc/shadow文件?这背后是一场精心设计的权限魔术。

一、用户身份的“三重面具”:RUID/EUID/SUID解密

在Linux的权限舞台上,每个进程都戴着三张不同的身份面具:

  1. 实际用户ID(RUID)

    • 进程的真实所有者,继承自启动它的用户

    • 查看命令:ps -eo pid,ruid,cmd

    • 如同身份证上的法定姓名

  2. 有效用户ID(EUID)

    • 内核进行权限检查时使用的身份

    • 决定进程能否访问文件或资源

    • 相当于门禁卡上的权限标签

  3. 保存用户ID(SUID)

    • EUID的临时备份仓库

    • 允许进程在特权/普通模式间切换

    • 通过seteuid()函数动态切换身份

关键规则:当进程尝试打开文件时,内核只检查EUID是否匹配文件所有者或所属组权限。


二、SetUID的魔法与风险:以passwd命令为例

魔法时刻:普通用户如何修改/etc/shadow

  • s位玄机:权限位的x被替换为s,表示启用SetUID

  • 执行瞬间的权限变身

    1. 用户A执行passwd程序

    2. 进程RUID=用户A,EUID=0(root)

    3. 进程获得root权限修改/etc/shadow

    4. 操作完成后EUID恢复为原用户

⚠️ 黑暗面:SetUID的安全陷阱
  1. 权限泄露风险
    若程序存在漏洞,攻击者可利用高权限执行任意操作

  2. 环境变量劫持
    通过LD_PRELOAD注入恶意库:

  3. 竞争条件攻击
    利用程序执行过程中的时间窗口篡改资源

历史教训:2016年曝光的pkexec本地提权漏洞(CVE-2021-4034)正是利用SetUID机制获取了root权限。


三、最小权限原则:安全开发黄金法则

正确使用权限切换API

安全编码实践
  1. 尽早丢弃权限
    特权操作完成后立即调用seteuid(orig_uid)

  2. 避免Shell操作
    禁用system()popen(),改用直接的系统调用

  3. 限制子进程权限
    fork()后子进程继承权限,需显式降权


四、Capabilities:精细化的权限手术刀

SetUID如同给用户管理员万能钥匙,Capabilities则是按需分配单把钥匙

核心能力列表
能力名称权限描述
CAP_DAC_OVERRIDE绕过文件读写权限检查
CAP_NET_RAW使用RAW和PACKET套接字
CAP_SYS_ADMIN执行系统管理操作
CAP_SYS_CHROOT使用chroot()
操作实践
  1. 赋予进程特定能力

  2. 程序内控制能力

  3. 容器中的应用
    Docker默认丢弃所有能力,按需添加:

优势对比:当Web服务器只需绑定80端口时,使用CAP_NET_BIND_SERVICE比SetUID root安全100倍!


五、案例深潜:sudo如何安全实现提权

执行sudo时的权限流转

图表

代码

安全设计精髓
  1. 双因子验证
    支持密码+二次认证(如Google Authenticator)

  2. 权限限制
    /etc/sudoers精细控制:

  3. 环境净化
    重置危险环境变量:

  4. 时间戳机制
    默认15分钟内无需重复认证,通过/var/run/sudo/ts管理

  5. 日志审计
    详细记录所有sudo操作到/var/log/auth.log


六、加固指南:权限管理最佳实践

  1. SetUID清理行动

  2. Capabilities替代方案

  3. 特权进程沙箱化
    使用命名空间隔离:

  4. 实时监控
    借助auditd跟踪权限变更:


结语:权限管理的艺术

Linux权限机制如同精密的门禁系统:

  • RUID 标识你的合法身份

  • EUID 决定你此刻能打开哪些门

  • SetUID 是临时通行证

  • Capabilities 则是细分的权限钥匙

在安全领域,最小权限原则不是选项而是铁律。当您下次执行sudo或修改密码时,不妨想象背后严密的权限检查机制——正是这些设计,守护着系统最后的安全防线。

思考题:为何Docker容器默认以root运行仍是安全的?答案藏在Linux Capabilities和Namespace的协同设计中。

http://www.dtcms.com/a/299336.html

相关文章:

  • 排序算法,咕咕咕
  • 【Zephyr】Window下的Zephyr编译和使用
  • window下MySQL安装(三)卸载mysql
  • PYTHON从入门到实践-16数据视图化展示
  • Rust Web框架性能对比与实战指南
  • 数据结构 二叉树(3)---层序遍历二叉树
  • SQLite 子查询详解
  • 告别复杂配置!Spring Boot优雅集成百度OCR的终极方案
  • C语言基础10——函数
  • Qt 与 WebService 交互开发
  • Linux学习 韦东山IMX6ULL(一)搭建环境并编译程序
  • SQL Developer Data Modeler:一款免费跨平台的数据库建模工具
  • 强化学习(第三课第三周)
  • Rust赋能土木工程数字化
  • AUTOSAR进阶图解==>AUTOSAR_SRS_TimeService
  • Raft 协议 Paxos协议 和zk协议的特点和异同
  • 【Pandas】pandas Index objects Index.shape
  • 【温度传感器】热电偶、热敏电阻、热电阻、热成像仪原理及精度解析
  • ASP.NET Core MVC中taghelper的ModelExpression详解
  • .NET Core中的配置系统
  • 记录和分享抓取的数字货币和大A时序数据
  • 去中心化时代的通信革命:briefing与cpolar技术融合带来的安全范式革新
  • AI代理性能提升实战:LangChain+LangGraph内存管理与上下文优化完整指南
  • 如何创建或查看具有 repo 权限的 GitHub 个人访问令牌(PAT)
  • kafka的消费者负载均衡机制
  • 《人性的弱点》重构【01】
  • Java:采用mybatis+pagehealper优雅的实现分页功能
  • Flutter 提取图像主色调 ColorScheme.fromImageProvider
  • Go 的时间包:理解单调时间与挂钟时间
  • SWC 深入全面讲解