[TOC]
| 代码示例支持 |
|---|
| 平台: Centos 6.3 |
| Python: 2.7.14 |
| 代码示例: code_demo目录 |
请注意该案例为虚拟案例, 为了展示uid euid等功能性, 不能直接应用于生产环境
小明是个服务器管理员, 他从老管理员手里接手了一个非常繁琐的运维工作: 短暂授权root 账号给不同的 team 接口人运行备份任务
该运维任务有几个特点:
- 任务需且仅需运行在 root 下
- root 账号只能短暂授权给各个小组
- 通过账号管理平台, 提前申请一段时间的临时密码
- 将临时密码提供给小组接口人
- 时间超时后密码自动变更
- 不同 team 分时使用, 无法并发使用
小明非常烦躁, 为了填上这个坑, 他调研了填坑解法.
填坑解法满足:
- 短时出借权限
- (在权限范围内)执行该任务时才能使用 root 权限
- 做完任务立即失去 root 权限
- 权限范围必须清晰
- 能做什么
- 能做数据备份
- 不能做什么
- 除了数据备份其他什么都不在 root 权限下做
- 能做什么
具体做法:
-
利用c/c++程序出借部分 root 权限
- 该c程序限定执行的备份操作为 python 代码 euid_backup.py
int main(int argc, char **argv){ if(0==isRunUnderRoot()){ fprintf(stderr,"does not run under +S attribute. Exiting....\n"); return EXIT_FAILURE; } exit(runNewProcess("./", "/usr/bin/backup/secured/python /usr/bin/backup/secured/euid_backup.py")); }
- euid_backup.py owner 为 root, 非 root 用户不准更改备份操作内容
-
为生成的执行文件euid_cp及euid_backup.py 设置root权限借用
sudo rm -f /usr/bin/backup/secured/euid_cp sudo gcc euid_cp.c -o /usr/bin/backup/secured/euid_cp # 设置文件owner为root, 非root用户无法更改执行内容 sudo chown root /usr/bin/backup/secured/* # 设置a. 非root只读 b. 增加执行权限 sudo chmod 755 /usr/bin/backup/secured/euid_cp # 设置stick bit, 执行euid_cp即可短暂获取root 权限, 执行任务 sudo chmod +s /usr/bin/backup/secured/euid_cp
-
/usr/bin/backup/secured/euid_backup.py Python 代码执行具体的备份任务
from __future__ import print_function import os import time print('euid is {0}'.format(os.geteuid())) if os.geteuid() == 0: print('start to copy under root') print('do some operations here') time.sleep(2) print('end copying things') print('drop privileges from root') else: print('non-root, euid {0} will exit'.format(os.geteuid()))
运行试验:
-
通过 /usr/bin/backup/secured/euid_cp 执行, 可以在非 root 下执行 root 权限才能执行的备份任务(euid_backup.py)
-
直接执行备份任务(/usr/bin/backup/secured/euid_backup.py) 会失败, 没有权限
-
uid / euid / suid 是什么
- uid 是用户的 userid
- 登陆后, 在不切换用户情况下 uid 一般不变
- euid 是用户的有效 id
- euid 在正常执行情况下一般等于uid
- euid 一般决定了用户对系统中存储介质的access (访问) 权限
- suid (saved uid) 是文件在被访问过程中的短暂切换用户euid的属性设置
- 简单来说, suid让本没有权限的用户可以短暂访问这些资源
- suid 在执行过程中进行了权限切换
- 执行之初, 切换到这个saved uid(文中为 root)
- fork执行过程中, euid == suid
- 执行完成后, euid 在切换回 uid
- uid 是用户的 userid
-
gid, egid 等同理, [*]uid的判断优先
- uid euid suid
- gid egid sgid
-
为什么本文没有直接对euid_backup.py文件进行设置+s操作, 而是用可执行的c/c++程序做执行器
-
Linux 系统里的passwd 程序是否也是这个原理? 它跟哪些文件/命令相关
P.S. 示例代码经 py-cn 圈朋友提醒作下进一步说明:
- 该示例代码和场景更多的是为了展示 suid 的特性
- 如果真实环境要进行如上的备份任务有多种实现选择, 该项并非最优
- 比如任务执行器实现 (普通用户下, 提交任务到 root 启动的执行器), 该执行器鉴权后在 root 下执行具体备份任务
- 分配 sudo 权限到不同的用户组进行权限控制
欢迎大家对内容\示例代码等提更多的建议.
进程篇其五之眼花缭乱的进程间通信
Life is short. We use Python.