2019-2020-1 20199307 "Linux kernel principle and Analysis" in the twelfth week job

SET-UID program vulnerabilities experiment

About experiments

Set-UID is an important safety mechanism for Unix systems. When a Set-UID program is running, it is assumed to have the owner's permission. For example, if the owner of the program is the root, so when anyone running this program will receive the owner's permission procedures. Set-UID allows us to do a lot of very interesting things, but unfortunately, it's also a lot of bad things culprit.
Therefore, this experiment has two goals:
1. to appreciate the bright side, to understand why the Set-UID is needed, and how it is executed.
2. Note the bad side, understand its potential security issues.

Content Experiments

This is an exploratory experiment, and your task is to Set-UID mechanism "play the game", you need to complete the following experimental tasks in Linux In a Linux environment:

Set-UID mechanism is not the case

Guess why "passwd", "chsh", "su", and "sudo" command requires a Set-UID mechanism, these mechanisms if they do not, then what will happen.
If you are not familiar with these programs, they can be familiar by reading the manual. If you copy these commands to its own directory, these programs would not be Set-UID program.

$ cp /usr/bin/passwd /tmp/passwd
$ ls -la /usr/bin/passwd
$ ls -la /tmp/passwd
$ /tmp/passwd #shiyanlou密码可以通过点击右侧工具栏SSH直连看到
$ /usr/bin/passwd

As can be seen from the above screenshot: Copy the passwd to / tmp / under the authority change (suid bit is set in the original directory), permission to modify the copy without the password.
For "chsh", "su", and "sudo" command, these programs are copied to the user directory, no longer has the same root.

Run Set-UID program

Set-UID program run in the linux environment, and describe and explain your observations.
Login as root, copy / usr / bin / zsh to / tmp, and set the copy to zsh tmp directory is set-uid root privileges, then a normal user login, run / tmp / zsh. You'll get root privileges? Please describe your results.

Copy / bin / bash to / tmp directory, and set the bash in the / tmp directory for Set-UID root privileges, then log in as a normal user, run the / tmp / bash. You'll get root privileges? Please describe your results.

Visible, the same operation, run zsh copy can gain root privileges, but can not bash.

bash internal protection mechanisms

As can be seen from the above steps, / bin / bash has some inherent protection mechanisms can prevent misuse Set-UID mechanism. To be able to experience the situation before this inner protective mechanism occurs, we plan to use another shell program - / bin / zsh. In some of the linux distributions (such as Fedora and Ubuntu), / bin / sh is actually the / bin / bash symbolic link. In order to use zsh, we need to / bin / sh linked to the / bin / zsh.
The following instructions will point to the default shell zsh:

$ sudo su
# cd /bin
# rm sh
# ln -s zsh sh

PATH environment variable settings

system(const char * cmd)系统调用函数被内嵌到一个程序中执行一个命令,system()调用/bin/sh来执行shell程序,然后shell程序去执行cmd命令。但是在一个Set-UID程序中system()函数调用shell是非常危险的,这是因为shell程序的行为可以被环境变量影响,比如PATH;而这些环境变量可以在用户的控制当中。通过控制这些变量,用心险恶的用户就可以控制Set-UID程序的行为。
下面的Set-UID程序被用来执行/bin/ls命令;然后程序员可以为ls命令使用相对路径,而不是绝对路径。在 /tmp 目录下新建 test.c 文件:

int main()
{
   system("ls");
   return 0;
}

你能够设置这个Set-UID程序运行你自己的代码而不是/bin/ls吗?如果你能的话,你的代码具有root权限吗?描述并解释你的观察。
可以具有root权限,把/bin/sh拷贝到/tmp目录下面重命名为ls(先要确保/bin/目录下的sh 符号链接到zsh,而不是bash),将环境变量PATH设置为当前目录/tmp,运行编译的程序test。就可以获得root权限:
[](https://img2018.cnblogs.com/blog/1800808/201912/1800808-20191204115447787-1018327717.png" width="650" height="500"/>

先恢复环境变量 PATH ,然后修改/bin/sh使得其返回到/bin/bash,重复上面的攻击,你仍然可以获得root权限吗?描述并解释你的观察。

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

可见修改sh连接回bash,运行test程序不能使普通用户获得 root 权限。

system()和execve()的不同

首先确保/bin/sh指向zsh:

$ sudo su
# cd /bin
# rm sh
# ln -s zsh sh

然后使用如下命令恢复 PATH:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

背景:Bob 在一家审计代理处工作,他正在调查一家公司是否存在诈骗行为。为了这个目的,他需要阅读这家公司在 Unix 系统中的所有文件。为了保护系统的可靠性,他不能修改任何一个文件。为了达到这个目的,Vince——系统的超级用户为他写了一个SET-ROOT-UID程序,并且给了Bob可以执行它的权限。这个程序需要Bob在命令行中打出一个文件名,然后运行/bin/cat命令显示这个文件。既然这个程序是以root权限运行的,它就可以显示Bob想看的任何一个文件。然而,既然这个程序没有写操作,Vince很确信Bob不能用这个程序修改任何文件。首先在 /tmp 目录下新建 SRU.c 文件,内容如下:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
   char *v[3];
   if(argc < 2)
   {
   printf("Please type a file name.\n");
   return 1;
   }
   v[0] = "/bin/cat"; v[1] = argv[1]; v[2] = 0;
  //Set q = 0 for Question a, and q = 1 for Question b
   int q = 0;
   if (q == 0)
   {
      char *command = malloc(strlen(v[0]) + strlen(v[1]) + 2);
      sprintf(command, "%s %s", v[0], v[1]);
      system(command);
  }
  else execve(v[0], v, 0);
  return 0 ;
}

程序中有 q=0。程序会使用system()调用命令行。这个命令安全吗?如果你是Bob,你能对系统的完整性妥协吗?你能重新移动一个对你没有写权限的文件吗?
这个命令不安全,Bob可能会出于好奇或者个人利益驱使阅读或者修改只有root用户才可以运行的一些文件。
比如截图中:file文件只有root用户有读写权限,但普通用户通过运行该程序,阅读并重命名了file文件:

如果令q=1;刚才的攻击还会有效吗?请描述并解释你的观察。
修改为q=1后,不会有效。前面步骤之所以有效,是因为system()函数调用/bin/sh,链接至zsh,具有root权限执行了cat file文件后,接着执行mv file file_new命令。
而当令q=1, execve()函数会把file; mv file file_new 看成是一个文件名,系统会提示不存在这个文件:

LD_PRELOAD环境变量

为了保证Set-UID程序在LD_PRELOAD环境的操纵下是安全的,动态链接器会忽略环境变量,但是在某些条件下是例外的,在下面的任务中,我们猜测这些特殊的条件到底是什么。
1、让我们建立一个动态链接库。把下面的程序命名为mylib.c,放在/tmp目录下。在函数库libc中重载了sleep函数:

#include <stdio.h>
void sleep (int s)
{
    printf("I am not sleeping!\n");
}

2、我们用下面的命令编译上面的程序(注意区别l和1):

gcc -fPIC -g -c mylib.c

gcc -shared -Wl,-soname,libmylib.so.1 \
-o libmylib.so.1.0.1 mylib.o –lc

3、把下面的程序命名为myprog.c,放在/tmp目录下:

int main()
{
   sleep(1);
   return 0;
}

请在下面的条件下运行这些程序,并观察结果。基于这些观察告诉我们链接器什么时候会忽略LD_PRELOAD环境变量,解释原因。
把myprog编译成一个普通用户下的程序在普通用户下运行
可见,它会使用LD_PRELOAD环境变量,重载sleep函数:

把myprog编译成一个Set-UID root的程序在普通用户下运行

把myprog编译成一个Set-UID root的程序在root下运行
在这种情况下,使用LD_PRELOAD环境变量,使用重载的sleep函数:

消除和清理特权

为了更加安全,Set-UID程序通常会调用setuid()系统调用函数永久的清除它们的root权限。然而有些时候,这样做是远远不够的。在root用户下,在/tmp目录新建一个空文件zzz。在root用户下将下面代码命名为test2.c,放在/tmp目录下,编译这个程序,给这个程序设置root权限。在一个普通的用户下,运行这个程序。描述你所观察到的情况,/tmp/zzz这个文件会被修改吗?解释你的观察。

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>

int main(){

    int fd;
    fd = open("/tmp/zzz",O_RDWR|O_APPEND);
    sleep(1);
    setuid(getuid());
    pid_t pid ;

    if( ( pid = fork() ) < 0 )
        perror("fork error");
    else if( pid == 0 ){
        // child process
        write( fd , "shiyanlou!" , 10 );
    }

    int status=waitpid(pid,0,0);
    close(fd);

    return 0;
}

结果如图:

如图所示文件被修改了,原因在于设置uid前,zzz文件就已经被打开了。只要将语句setuid(getuid())移至调用open函数之前,就能避免这个问题。

实验总结

本次实验是这学期最后一次实验了,和上一次一样是属于探究性的实验,按照实验楼的提示将每一步都做了出来。本实验共分为7个小节,让我对之前所学的好多linux的知识结合了起来,比如文件的权限管理等。实验完成后,我对SET-UID程序漏洞有了一个深刻的认识,了解到它好的一面与坏的一面,对我linux的学习帮助极大,我也希望我可以在学习linux的道路上再接再厉。

Guess you like

Origin www.cnblogs.com/j1551163790/p/11981917.html