linux 用户shell 无效,浅谈Linux环境下,为什么设置用户ID位对shell脚本无效

前言:

博主在前不久的一个项目中,项目组的组员需要删除由daemon守护进程创建的缓存文件。但是删除这些缓存文件需要超级用户权限。博主用root用户创建了一个设置用户id的shell脚本来实现此功能。但是此脚本并没有如预期那样工作。今天就浅谈一下设置用户id位,为什么对shell脚本无效。

?

假设我们文件结构如下图所示

627d03ee1a2990f03c13f7441476ce30.png

?Cache文件目录下有3个缓存文件,分别为cache1、cache2、cache3,这三个文件为daemon用户所有

?

下面我们来看一下设置用户id位的两种工作方式。

?

对shell脚本文件设置“设置用户id位”

现在我们有一个名为"d_cache.sh"的shell脚本,脚本的功能是删除Cache文件目录中的所有缓存文件

977cae6157ace1dca0ec3c51d77d158a.png

?

?运行脚本,显示无权操作

3cbcf1d903c7ae5c605e87fd9bc8c55c.png

?

现在我们更改为root用户,并设置设置用户id位,并执行脚本

483a497aa97800aaafbe9a24c1b37354.png

?

结果如图所见,虽然把文件所有者更改为了root,并且设置了设置用户id位,但是“然并卵”。

?

对可执行二进制文件设置“设置用户id位”

现在我们在一个名为system.c的C程序中通过execl函数,exec“d_cache.sh”脚本,然后看看会发生什么。

#include

#include

#include

#include

#include

int main(void)

{

pid_t pid;

if ((pid = fork()) < 0) {

printf("fork error: %s\n", strerror(errno));

exit(0);

} else if (pid == 0) { /* 子进程 */

/* 将实际用户id,有效用户id,保存的设置用户id都设置为0(也就是超级用户) */

setuid(0);

if (execl("/home/paul/test/d_cache.sh", "d_cache.sh", (char *)0) < 0) {

printf("execl error: %s\n", strerror(errno));

exit(0);

}

}

exit(0);

}

?

?编译system.c文件,生成可执行二进制文件a.out,运行结果如下图

748de3ecf2e36621ff8fdf380cd2f3d0.png

?

把a.out的所有者更改为root,并且启用设置用户id位,然后运行结果如下图

cae09fe67ec4b1da870f5c919bcdb26c.png

?

成功的把Cache文件目录中的缓存文件删除掉了。

?

警告:这种实现方法存在巨大的安全隐患,在文件d_cache.sh中的任何命令都将以root权限执行。最好把d_cache.sh文件的访问权限改为755,并且文件所有者改为root所有,即普通用户不能修改此文件。

?

?

为什么会出现这种区别呢?

?

这就涉及与进程相关的三个用户ID(暂不讨论组ID)

实际用户ID(登陆ID)

有效用户ID(用于检查文件的权限)

保存设置用户ID(由exec复制有效用户ID得来)

以上面的二进制可执行文件a.out为例,我们来分析一下,程序在运行中三个用户ID的变化

e0d1cf1c7a1b16640171c0d734dca835.png

?进入main后,fork之前,父进程中的三个用户ID

实际用户ID = paul(登陆ID)

有效用户ID = root (由于设置了设置用户ID位,exec把有效用户ID设置为文件的所有者即root)

保存设置用户ID = root(exex复制有效用户ID)

在子进程中,调用setuid(0)之前。子进程继承父进程的属性,这时子进程中三个用户ID

实际用户ID = paul

有效用户ID = root?

保存设置用户ID = root

子进程中调用setuid(0)后,子进程的三个用户ID

实际用户ID = root

有效用户ID = root?

保存设置用户ID = root

此后,子进程中的所有操作都将具有root权限。

在子进程中execl函数定位到文件"/home/paul/test/d_cache.sh",但该文件不是一个由连接编辑器产生的机器可执行文件,于是execl就认为该文件是一个shell脚本,于是接着调用/bin/sh,并以路径"/home/paul/test/d_cache.sh"作为shell的输入。当/bin/sh是bash版本2以上时,如果有效用户ID不等于实际用户ID时,bash会把有效用户ID设置为实际用户ID。所以在sysyem.c程序子进程中,如果在execl之前没有语句setuid(0),那么后续执行的d_cache.sh脚本就不具有root权限。

7640c4d0bb0e10568dec6f0b6a9b4993.png

[email protected]:~/test$ ls -l d_cache.sh

-rwsrwxr-x 1 root root 49 Dec 27 16:09 d_cache.sh

[email protected]:~/test$ ./d_cache.sh

rm: cannot remove ‘/home/paul/test/Cache/cache1’: Permission denied

rm: cannot remove ‘/home/paul/test/Cache/cache2’: Permission denied

rm: cannot remove ‘/home/paul/test/Cache/cache3’: Permission denied

[email protected]:~/test$

?

结束语:以上为本人对setuid为什么对shell脚本无效的一点浅薄认识。由于本人水平所限,如有错误,欢迎批评指正。

?

参考文献:

?

版权声明:本文为博主原创文章,未经博主允许不得转载。

原文:http://tangl163.iteye.com/blog/2267297

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值