setuid介绍

本文详细探讨了Linux系统中不为人知的权限设置,包括SetUID、SetGID和sticky bit的作用与操作方法。通过实例展示了如何利用这些权限进行更安全的服务器管理,并解释了Linux中进程的用户标识符及其在执行setuid、setruid函数时的行为差异。最后,文章提供了如何在实际应用中操作这些标志的指导,以增强对Linux权限管理的理解。
一些有经验的Linux人员我相信都知道Linux权限中有一些不为人知的权限.了解了这些权限对以后更好管理服务器安全有很大的管理,下面我们就来谈谈. 相对于Windows系统的安全权限设置来说Linux安全权限设置相对来麻烦些..起码没有Win人性化..但也这无非这个RWX这三个权限的互相搭配 和使用,我相信大家都知道的..好,不知大家是否留意看/bin/su,/usr/sbin/passwd等等这个目录以及文件的属性. 如: /etc/passwd -rw-r--r-- 1 root root       /etc/shadow -r-------- 1 root root      按照上面的二种权限来看的话,/etc/passwd只有root才有写入的权限..那为什么,我su - skycn时,用passwd修改skycn密码没有任何问题呢?再来看看/etc/shadow的权限,默认应该是只有root才能读,其它用户应该是 连写的权限都没有...那修改密码的奥秘又在那里呢?接下来出场的就是今天的主角SetUID,SetGID.    先来看看这个权限/bin/su -rws-r-xr-x 1 root root                         /usr/bin/passwd -r-s--x--x 1 root root    注意看到没有那个s权限是什么呢?s就是SetUID的标识,有了这个标识当用户执行此命令时,将拥有此命令相当于root的权限操作,这就是为什么当普 通用户使用/etc/passwd修改密码可能正常修改的原因了.SetUID只会出现了Binary file中,目录中存在将没有意思...还有一点就是当其它用户使用带用Setuid标识的命令时,自己对此命令也必需有X(执行)的权限,否则一切都免 谈..这点应该不难理解的..^_^     SetGID如果标识在文件中的话,那么执行用户将会拥有此命令所属组的权限..     SetGID如果标识在目录中,那么执行者将在此目录下建立的目录以及文件所属将会是目录的所属组. 规范的说 setuid: 设置使文件在执行阶段具有文件所有者的权限. 典型的文件是 /usr/bin/passwd. 如果一般用户执行该文件, 则在执行过程中, 该文件可以获得root权限, 从而可以更改用户的密码. setgid: 该权限只对目录有效. 目录被设置该位后, 任何用户在此目录下创建的文件都具有和该目录所属的组相同的组. sticky bit: 该位可以理解为防删除位. 一个文件是否可以被某用户删除, 主要取决于该文件所属的组是否对该用户具有写权限. 如果没有写权限, 则这个目录下的所有文件都不能被删除, 同时也不能添加新的文件. 如果希望用户能够添加文件但同时不能删除文件, 则可以对文件使用sticky bit位. 设置该位后, 就算用户对目录具有写权限, 也不能删除该文件. 下面说一下如何操作这些标志: 操作这些标志与操作文件权限的命令是一样的, 都是 chmod. 有两种方法来操作, 1) chmod u+s temp -- 为temp文件加上setuid标志. (setuid 只对文件有效) chmod g+s tempdir -- 为tempdir目录加上setgid标志 (setgid 只对目录有效) chmod o+t temp -- 为temp文件加上sticky标志 (sticky只对文件有效) 在linux中每个进程有三个[实际上有第4个]用户标识符.         real uid      : 真实用户ID.         saved uid     : 已保存用户ID         effective uid : 有效用户ID     真实用户ID(real uid)是login时的用户.而在运行过程中, 用于所有的安全检查的是有效用户ID(effective uid). 一般情况下:     real uid = saved uid = effective uid     在某些场合下,使用用setuid,setruid函数可以改变effective uid,从而 使得程序运行时具有特殊的权限.常见的例子是linux系统中的passwd命令, 由于所有的用户信息包括用户密码都保存在/etc/passwd文件中,而/etc/passwd 文件只有root权限可以读写,若想让每个用户都只可以修改自己的密码,就必须 让普通用户暂时获得有限的读写/etc/passwd的权限.用setuid就可以解决这个 问题. Linux setuid(uid)函数:     (1)如果由普通用户调用,将当前进程的有效ID设置为uid.     (2)如果由有效用户ID符为0的进程调用,则将真实,有效和已保存用户ID都设     置为uid. Linux的setuid函数和Unix中的setuid函数的行为是不同的. Unix中.setuid(uid)函数的行为:     (1)如果进程没有超级用户特权,且uid等于实际用户ID或已保存用户ID,则只     将有效的用户ID设置为uid.否则返回错误.     (2)如果进程是有超级用户特权,则将真实,有效和     已保存用户表示符都设置为uid.     这里主要的区别在于普通用户调用时的行为.产生这个问题的原因是POSIX和 BSD的实现差异,而linux却同时支持这两者.BSD中使用             setreuid(uid_t ruid, uid_t euid) 来设定真实用户ID(real uid)和有效用户ID(effective uid).这个函数在由有效 用户ID符为0的进程调用时,不会改变已保存用户ID.函数seteuid(uid_t uid)等价 于setreuid(-1,uid),只改变有效用户ID(effective uid). 例子:   使用setuid或是setruid,让非root用户也可以读取只有root用户有读写权限的 文件. #假设此程序名为:setuid_ex #要读取的文件为:root_only.txt $ users dd admin $ ls -l root_only.txt -rw-------  1 root root 33 Jan 11 17:07 root_only.txt $ vi setuid_ex.cpp      1  /**      2   * Linux setuid函数的例子.      3   * */      4  #include  //setuid() and getuid()      5  #include      6  #include      7      8  using namespace std;      9  void test_read_file(const char *name)     10  {     11      ifstream f(name);     12      if(f.fail())     13          cout<<"=[ERROR]: read failed."<<endl;     14      else     15          cout<<"=[OK]: read successful."<<endl;     16  }     17  //打印uid和euid.     18  inline void p_states(void)     19  {     20      int uid,euid;     21      cout<<"-----Current states--------------------------"<<endl;     22      cout<<"real uid/t"<<getuid()<<endl;     23      cout<<"effective uid/t"<<geteuid()<<endl;     24      cout<<"---------------------------------------------"<<endl;     25  }     26  //调用setuid.     27  inline void run_setuid_fun(int uid)     28  {     29      if(setuid(uid) == -1)     30           cout<<"=[ERROR]: setuid("<<uid<<") error"<<endl;     31      p_states();     32  }     33  //调用seteuid.     34  inline void run_seteuid_fun(int uid)     35  {     36      if(seteuid(uid) == -1)     37           cout<<"=[ERROR]: seteuid("<<uid<<") error"<<endl;     38      p_states();     39  }     40     41  int main()     42  {     43      int t_re=0;     44      const char * file = "root_only.txt";     45     46      cout<<endl<<"TEST 1: "<<endl;     47      p_states();     48      //[1]此时 real uid= login user id     49      //     effective uid = root     50      //     saved uid = root     51      test_read_file(file);     52     53      cout<<endl<<"TEST 2: seteuid(getuid())"<<endl;     54      run_seteuid_fun(getuid());     55      //[2]此时 real uid= login user id     56      //     effective uid = login user id     57      //     saved uid = root     58      test_read_file(file);     59     60      cout<<endl<<"TEST 3: seteuid(0)"<<endl;     61      run_seteuid_fun(0);     62      //[3]此时 real uid= login user id     63      //     effective uid = root     64      //     saved uid = root     65      test_read_file(file);     66     67      cout<<endl<<"TEST 4: setuid(0)"<<endl;     68      run_setuid_fun(0);     69      //[4]此时 real uid= root     70      //     effective uid = root     71      //     saved uid = root     72      test_read_file(file);     73     74      cout<<endl<<"TEST 5: setuid(503)"<<endl;     75      run_setuid_fun(503);     76      //[5]此时 real uid= login user id     77      //     effective uid = login user id     78      //     saved uid = login user id     79      test_read_file(file);     80     81      cout<<endl<<"TEST 6: setuid(0)"<<endl;     82      //[6]此时 real uid= login user id     83      //     effective uid = login user id     84      //     saved uid = login user id     85      // 运行setuid(0)是将返回错误值-1.     86      run_setuid_fun(0);     87      test_read_file(file);     88      return 0;     89  }     90     91 $ vi Makefile      1  src=setuid_ex.cpp      2  exe=setuid_ex      3  cc=g++      4  flags=-g      5      6  all:${src}      7          ${cc} ${flags} -o ${exe}      8          chown root:root ${exe}      9          ### 实际上chmod 4111改变了effective id 和saved uid的值.     10          ### 这也是setuid setruid函数在不同权限间正常切换的前提.     11          chmod 4111 ${exe}     $ sudo make #使用root进行Make. $ ls -l setuid_ex ---s--x--x  1 root root 58579 Jan 15 11:27 setuid_ex $ ./setuid_ex TEST 1: -----Current states-------------------------- real uid        503 effective uid   0 --------------------------------------------- =[OK]: read successful. TEST 2: seteuid(getuid()) -----Current states-------------------------- real uid        503 effective uid   503 --------------------------------------------- =[ERROR]: read failed. TEST 3: seteuid(0) -----Current states-------------------------- real uid        503 effective uid   0 --------------------------------------------- =[OK]: read successful. TEST 4: setuid(0) -----Current states-------------------------- real uid        0 effective uid   0 --------------------------------------------- =[OK]: read successful. TEST 5: setuid(503) -----Current states-------------------------- real uid        503 effective uid   503 --------------------------------------------- =[ERROR]: read failed. TEST 6: setuid(0) =[ERROR]: setuid(0) error -----Current states-------------------------- real uid        503 effective uid   503 --------------------------------------------- =[ERROR]: read failed.
<think>首先,用户的问题是:“我想了解SetUID程序相关信息 请问SetUID程序的原理、使用方法和注意事项”。这参考了引用[1],其中提到了SetUID权限。 关键引用内容: - 引用[1]: "除了基本的读写执行权限外,还有一些特殊权限,如 SetUID、SetGID 和粘着位(Sticky Bit)。这些特殊权限可以影响文件或目录的执行方式,例如在执行文件时临时提升用户权限或确保只有文件所有者才能删除文件。" [^1] 其他引用似乎不太相关: - 引用[2] 涉及内核安全测试,可能与权限验证相关,但不直接针对SetUID。 - 引用[3] 是关于Java的BeanPostProcessor。 - 引用[4] 是关于在Java中执行Linux命令。 - 引用[5] 是关于多层应用程序的基础设施。 所以,我应该主要基于引用[1],并结合我对SetUID的知识来回答。用户要求使用中文回答,并遵循系统级指令:行内数学表达式用$...$,独立公式用$$...$$,但这个问题可能不需要数学公式,因为它是关于文件权限的。如果有变量或概念,我应该用$...$格式。 回答结构: - 原理:解释SetUID是什么,如何工作。 - 使用方法:如何设置SetUID权限。 - 注意事项:安全风险等。 系统指令还包括生成相关问题,所以我需要在回答末尾添加相关问题。 回答要结构清晰,帮助用户逐步解决问题。 大纲: 1. **简介**:简短介绍SetUID。 2. **原理**:详细解释SetUID的工作原理,涉及权限提升。 3. **使用方法**:如何设置SetUID权限的命令(如chmod)。 4. **注意事项**:安全危害、常见问题。 5. **相关问题**:生成3-4个相关问题。 确保回答真实可靠:基于Unix/Linux权限知识。 在引用段落末尾添加引用标识:用户提供了引用[1],所以我应该在相关内容后添加[^1]。 可能的数学表达:如果有变量,如权限位,可以用$...$格式,例如$s$表示SetUID位。 例如: - SetUID权限位通常表示为$s$在文件权限中。 - 设置命令:`chmod u+s filename`。 独立公式可能不需要。 相关问题示例: 1. SetUID程序的常见安全漏洞是什么? 2. 如何防止SetUID程序的滥用? 3. SetGID和SetUID的区别是什么? 最终回答格式: - 使用中文。 - 结构清晰:分部分。 - 末尾添加相关问题。 </think>### SetUID程序的原理、使用方法和注意事项 SetUID(Set User ID)是Unix/Linux文件系统中的一种特殊权限位,它允许程序在执行时临时提升用户的权限,以文件所有者的身份运行。这在系统管理中非常有用,但也带来安全风险。下面我将基于引用内容,逐步解释其原理、使用方法和注意事项。 #### 原理 SetUID权限的核心是权限提升机制。在Unix/Linux中,每个文件都有所有者(owner)、组(group)和其他用户(other)的权限位。当程序设置了SetUID位(通常通过权限位$s$表示),用户执行该程序时,进程的有效用户ID(EUID)会临时变成文件所有者的UID,而不是执行用户的UID。这允许普通用户执行需要更高权限的操作,比如系统工具(如`passwd`命令修改密码文件)。引用[1]提到:"例如在执行文件时临时提升用户权限",这确保了权限的提升是暂时的,只在程序执行期间生效[^1]。 - **关键概念**:设文件所有者的UID为$o$,执行用户的UID为$u$。执行SetUID程序时,进程的EUID从$u$变为$o$,但真实用户ID(RUID)仍保持$u$。程序结束后,权限恢复到原状态。 - **权限位表示**:在`ls -l`输出中,SetUID位显示为所有者执行位上的$s$(例如,`-rwsr-xr-x`),如果执行位未设置,则显示大写$S$。 #### 使用方法 设置和使用SetUID程序涉及简单的命令行操作,主要通过`chmod`命令实现。以下是详细步骤: 1. **创建或选择程序**:确保程序是安全可靠的脚本或二进制文件。例如,编写一个C程序`my_program.c`,编译为可执行文件。 ```c #include <stdio.h> int main() { printf("Running with elevated privileges\n"); return 0; } ``` 编译:`gcc my_program.c -o my_program`。 2. **设置SetUID位**:使用`chmod`命令添加SetUID权限。 - 基本语法:`chmod u+s <filename>`。 - 示例:为`my_program`设置SetUID: ```bash chmod u+s my_program ``` 验证权限:执行`ls -l my_program`,输出应类似`-rwsr-xr-x`,其中$s$表示SetUID位已设置。 3. **执行程序**:用户运行该程序时,会自动提升权限。 - 示例:普通用户执行`./my_program`,进程将以文件所有者(通常是root)的EUID运行。 4. **移除SetUID位**:如果需要撤销权限,使用`chmod u-s <filename>`。 SetUID常用于系统工具,如`/usr/bin/passwd`(允许普通用户修改密码文件)。引用[1]强调这些特殊权限"影响文件或目录的执行方式",确保在需要时临时提升权限[^1]。 #### 注意事项 SetUID程序虽然强大,但容易引入安全漏洞。基于引用[1]和相关知识,以下是关键注意事项: 1. **安全风险**: - **权限滥用**:如果程序存在漏洞(如缓冲区溢出),攻击者可能利用SetUID以root权限执行恶意代码。引用[1]提到"确保只有文件所有者才能删除文件",但SetUID可能被误用导致未授权操作[^1]。 - **常见漏洞**:例如,程序中未正确过滤用户输入,导致权限提升攻击。 2. **最佳实践**: - **最小权限原则**:仅对必要程序设置SetUID,并确保文件所有者为最小权限用户(非root)。 - **代码审计**:仔细检查程序代码,避免使用危险函数(如`system()`),并确保输入验证。 - **文件所有权限制**:设置严格的权限:`chmod u+s,o-w <filename>`,防止其他用户写入。 - **禁用不必要的SetUID**:定期检查系统(使用`find / -perm -4000`),移除未使用的SetUID程序。 3. **其他考虑**: - **与SetGID的区别**:SetGID提升组权限,而SetUID提升用户权限;两者均可用于类似场景,但SetUID风险更高。 - **系统兼容性**:在引用[2]提到的内核版本中,权限验证机制可帮助测试SetUID的安全性,但并非所有系统都内置此类保护[^2]。 - **使用场景**:适用于需要临时权限提升的工具,如密码修改或系统备份,避免用于用户自定义脚本。 总之,SetUID是一个强大的工具,但必须谨慎使用。务必遵循安全指南,以减少潜在风险。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值