`

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

阅读更多

前言:

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

 

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


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

 

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

 

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

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

 

 运行脚本,显示无权操作


 

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

 

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

 

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

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

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,运行结果如下图

 

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

 

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

 

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

 

 

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

 

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

  • 实际用户ID(登陆ID)
  • 有效用户ID(用于检查文件的权限)
  • 保存设置用户ID(由exec复制有效用户ID得来)

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

 进入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权限。


 由于存在巨大的安全漏洞Linux忽略所有解释器文件(首行以#!开始)的设置用户ID位。这也就是设置用户ID位,对shell脚本无效的原因。

paul@localhost:~/test$ ls -l d_cache.sh 
-rwsrwxr-x 1 root root 49 Dec 27 16:09 d_cache.sh
paul@localhost:~/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
paul@localhost:~/test$ 

 

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

 

参考文献:

1. UNIX环境高级编程(第二版)第八章 进程控制

2. http://unix.stackexchange.com/questions/364/allow-setuid-on-shell-scripts/2910#2910

3. http://www.faqs.org/faqs/unix-faq/faq/part4/section-7.html

4. https://en.wikipedia.org/wiki/Setuid

 

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

  • 大小: 26.6 KB
  • 大小: 30.5 KB
2
1
分享到:
评论

相关推荐

    LinuxShell脚本编程实例.doc

    Linux Shell脚本编程实例 Linux Shell脚本编程实例是指使用Linux操作系统的Shell来编写脚本程序,实现自动化任务、批处理和system administration等功能。本文将通过实例讲解Linux Shell脚本编程的基本概念、语法和...

    Shell脚本中获取进程ID的方法

    提问: 我想要知道运行中脚本子shell的进程id。我该如何在shell脚本中得到PID。 当我在执行shell脚本时,它会启动一个叫子shell的进程。作为主shell的子进程,子shell将shell脚本中的命令作为批处理运行(因此称为...

    Linux Shell 脚本攻略

    ** Shell是Linux操作系统中的一个命令解释器,它为用户提供了一个与操作系统内核交互的接口。 - **常见的Shell类型**:Bash(Bourne-Again SHell)、Sh、Csh、Ksh、Zsh等,其中Bash是最常用的一种。 - **Shell脚本...

    linux 安装tomcat shell脚本

    Shell脚本是Linux系统中的一种批处理程序,它允许用户编写一系列命令并将其保存为一个文件,通过执行这个文件来完成自动化任务。编写Shell脚本通常涉及变量定义、条件判断、循环结构、函数定义等元素。在我们的场景...

    linux常用命令与Unix Shell脚本

    Linux操作系统是许多企业和个人开发者的首选,因为它提供了强大的命令行工具和Shell脚本来管理系统。在本文中,我们将深入探讨一些最常用的Linux命令以及Unix Shell脚本的基本概念。 首先,让我们看看那些常用的...

    linux shell脚本通讯录

    linux shell写的通讯录脚本,有增删改查,id自增长功能,

    linux-shell脚本语言讲义

    Linux Shell脚本是一种强大的自动化工具,它允许用户编写批处理程序来执行一系列命令,类似于Windows环境中的批处理文件。在Linux环境中,Shell脚本比DOS批处理文件更加强大和灵活,支持更多的编程特性。本文主要...

    android系统中调用shell脚本

    在Android系统中,由于安全性和权限的限制,直接调用shell脚本并不像在Linux或Unix环境下那样简单。然而,对于非root用户来说,确实有一些方法可以实现对shell脚本的调用,尤其是在开发和调试过程中。下面我们将深入...

    linux shell脚本开发记事本

    在Linux环境中,Shell脚本是一种重要的自动化工具,它允许用户通过一系列命令来执行复杂的任务。Shell脚本不仅能够简化日常管理任务,还能提高系统的灵活性和效率。本文将详细介绍Shell脚本中的一些关键概念和技术,...

    Linux shell编程 验证身份证号码(15/18)

    根据给定的Linux shell脚本,我们可以深入探讨与身份证号码验证相关的知识点,特别是针对中国身份证号码的15位和18位格式的处理方法。以下是对脚本中关键部分的详细解析: ### Linux Shell编程验证身份证号码 ####...

    高级Shell脚本编程.zip

    本资源"高级Shell脚本编程.zip"包含了一个CHM(Compiled Help Manual)格式的中文文档,这对于运维人员和对Shell脚本感兴趣的人员来说,是一个非常有价值的参考资料。CHM文件是微软开发的一种帮助文档格式,它将多个...

    shell编程用户信息管理(模拟)课程设计说明书

    该课程设计旨在掌握 Linux 操作系统中 shell 脚本编程技术的变量定义、变量使用、循环控制结构、条件选择结构、用户交互、文件读写、文本内容分析以及 Linux 重要命令的使用等,以验证学生对于 shell 脚本编程的掌握...

    Shell脚本批量添加CSV数据到MySQL

    在Unix/Linux环境中,Shell脚本允许我们编写一系列命令来执行自动化任务。这个脚本的目的就是读取`prov.csv`中的数据,并将其插入到MySQL数据库中的相应表中。脚本可能包含如下步骤: 1. 使用`cat`或`head`命令查看...

    shell脚本初学者使用

    由于提供的文件信息中包含了OCR扫描的错误和乱码,因此我将会尽量从提供的信息中提炼和重构出知识点,并尽可能地补充解释和详细说明,...不过,按照上述构建的知识点,初学者应该能够对Shell脚本有一个全面的基础认识。

    Shell脚本创建SFTP和FTP账户

    Shell脚本,尤其是对于Linux运维人员,是日常工作中不可或缺的工具,能够帮助执行批量任务,如创建用户账户、配置权限以及设置服务。以下我们将详细探讨这个主题。 首先,`FtpManageAcc.sh`可能是用于创建和管理FTP...

    shell脚本编程100例.doc

    Shell脚本编程是一种在Linux和Unix系统中广泛使用的编程方式,它允许用户通过编写脚本来自动化执行一系列系统命令。在本文中,我们将深入探讨几个关键的Shell脚本知识点,包括基本语法、变量、条件判断、循环、进程...

    强力推荐Shell 脚本教程 ppt

    本教程主要针对Linux系统下的Shell脚本编程,适用于初学者。它不仅涵盖了基础概念,还深入探讨了Shell变量的管理和操作技巧,是理解并掌握Shell脚本编程的一个很好的起点。 #### 核心知识点详解 ##### Linux操作...

    ipa批量打包shell脚本

    Shell脚本是Unix或Linux操作系统中的命令行解释器,可以执行一系列命令。通过编写shell脚本,我们可以自动化重复性的任务,如编译、测试和打包等。对于iOS开发者来说,创建一个批量打包ipa的shell脚本能极大地提高...

    技巧高超的Shell脚本 101个Linux_Mac OS X_Unix系统的脚本.zip

    该压缩包包含一本电子书(No.Starch.Press.Wicked.Cool.Shell.Scripts-101.Scripts.for.Linux.Mac.OS.X.and.Unix.Systems.eBook-LiB.chm)、文件标识(file_id.diz)、书籍信息(LiB.nfo)、相关公告(atom.nfo)...

    在Linux系统中批量建立用户的shell

    总的来说,这个shell脚本提供了一个有效且可定制的解决方案,帮助管理员在Linux环境中快速批量创建用户账户,从而简化了校园网络服务的管理和维护工作。在实际操作中,需要根据不同的Linux发行版和系统环境进行必要...

Global site tag (gtag.js) - Google Analytics