Linux应用程序动态更改用户ID

有时候为了系统安全,会将程序进行降权,但是当需要访问当前不允许访问的资源时,如何处理呢?那就是更改自己的用户ID或组ID,使新的ID具有合适的特权或访问权限,当处理完之后,再降低其特权,下面来介绍一下,如何在程序中动态修改程序的用户ID或组ID。

进程用户ID

首先,我们需要了解,一个进程相关联的ID有多少个,下面表格介绍:

ID作用
实际用户ID我们实际上是谁
实际组ID我们实际上是谁
有效用户ID用于文件访问权限检查
有效组ID用于文件访问权限检查
附属组ID用于文件访问权限检查
保存的设置用户ID由exec()函数保存
保存的设置组ID由exec()函数保存

另外,我们可以通过 getuid() 和 geteuid() 函数分别或者实际用户ID和有效用户ID,而设置用户ID我们是没有函数可以直接获取的。

动态更换用户ID

当我们在root用户下通过 chmod +s YourExe 命令给我们的可执行程序设置SUID位(“u+s”设置文件的用户ID位,“g+s”设置组ID位),这个时候,我们可以通过seteuid()函数暂时性的获得root权限。
“+s”设置的标志位含义是当执行此文件时,将进程的有效用户ID设置为文件所有者的用户ID

测试代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>

int main(int argc, char *argv[])
{
	int fd;
	unsigned char *dev_name = "/dev/input/event0";

	printf("uid = %d, gid = %d euid = %d\n", getuid(), getgid(), geteuid());
	fd = open(dev_name, O_RDONLY);
	if (fd < 0)
		printf("open %s error,errno %d\n", dev_name, errno);
	else {
		printf("open %s ok\n", dev_name);
		close(fd);
	}

	/* 参数0是root用户ID */
	seteuid(0);
	printf("uid = %d, gid = %d euid = %d\n", getuid(), getgid(), geteuid());
	fd = open(dev_name, O_RDONLY);
	if (fd < 0)
		printf("open %s error,errno %d\n", dev_name, errno);
	else {
		printf("open %s ok\n", dev_name);
		close(fd);
	}

	/* 参数2是当前实际用户ID */
	seteuid(2);
	printf("uid = %d, gid = %d euid = %d\n", getuid(), getgid(), geteuid());
	fd = open(dev_name, O_RDONLY);
	if (fd < 0)
		printf("open %s error,errno %d\n", dev_name, errno);
	else {
		printf("open %s ok\n", dev_name);
		close(fd);
	}
}

默认的,我们user是没有 /dev 目录下节点的读取权限的,当我们去打开该节点时,将会出现报错说没有权限,但是,这个时候,如果通过 seteuid() 函数将有效用户ID设置为 root 用户(ID = 0),则可以正常访问 /dev 目录下的节点,当访问结束后,再通过 seteuid() 函数还原即可,注意,是 seteuid() 函数而不是 setuid() 函数。

实际上,上面示例在user用户环境的的工作步骤如下:

  1. 程序文件由root用户拥有且在设置用户ID位已设置,在user用户空间运行的,所以用户ID信息如下:

    实际用户ID = 我们的用户ID
    有效用户ID = 我们的用户ID
    保存的设置用户ID = root

    所以第一次open /dev 节点将会出现没有权限。

  2. 当调用 seteuid(0) 之后,由于我们已经设置了用户ID位,所以这种行为是允许的,用户ID信息将变为以下:

    实际用户ID = 我们的用户ID(未改变)
    有效用户ID = root
    保存的设置用户ID = root(未改变)

    由于当前有效用户ID为root,所以可以正常访问 /dev 节点。

  3. 当调用 seteuid(2) 降权之后,用户ID信息将变为以下:

    实际用户ID = 我们的用户ID(未改变)
    有效用户ID = 我们的用户ID
    保存的设置用户ID = root(未改变)

    降权后访问 /dev 将会无权限。

通过上述的配置,我们可以动态修改用户 ID,但是程序得到了额外的权限,编写这种程序时谨慎处理。

参考

《UNIX环境高级编程第3版》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chengwei_peng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值