文章目录
  1. 简介
  2. 详解
  3. 提权

简介

设置用户凭证

1
2
3
4
5
#include <sys/types.h>
#include <unistd.h>

/* 返回0:成功 || 返回-1并设置errno: 失败*/
int setuid(uid_t uid);

详解

设置调用进程的有效用户ID。如果调用进程具有特权(更确切地说:如果进程的用户命名空间中具有CAP_SETUID功能),则还会设置实际UID和保存集用户ID。这允许设置用户ID(而不是root)程序放弃其所有用户权限,做一些没有权限的工作,然后以安全的方式重新连接原始有效的用户ID。

如果用户是root用户或程序设置为用户ID root,则必须特别小心:setuid检查调用方的有效用户ID,如果它是超级用户,则所有与流程相关的用户ID都设置为uid。发生这种情况后,程序就不可能重新获得root权限。

因此,一个设置用户ID的根程序希望暂时放弃根权限,采用无特权用户的身份,然后重新获得根权限,则不能使用setuid。您可以使用seteuid完成此操作

提权

当一个程序使用setuid标志启动时,它会在执行时获得与所有者相同的特权级别。因此,如果一个root用户把一个文件设置为setuid root,任何普通用户运行该程序时都会以超级用户的身份运行。

如何使用setuid提权,这里给出一个例子。

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include<stdlib.h>

int main()
{
setgid(0);
setuid(0);
system("bash");
}
/* gcc switch_to_root.c -o switch_to_root */

接下来,以root权限做如下设置:

  • 设置switch_to_root的属主为root

  • 赋予switch_to_root可执行权限,并启动switch_to_root的setuid标志

1
2
3
4
# chown root:root switch_to_root
# chmod u+s switch_to_root
$ ./switch_to_root
#

然后退出root,以普通用户执行switch_to_root,执行完进入root。