实验目的
本次实验目的是深刻的了解SetUID程序,了解SetUID程序解决的问题。设计SetUID程序须要注意的地方。了解其潜在的安全问题。linux
实验内容
在Unix操做系统中,Set-UID是一个重要的安全机制。 Set-UID程序运行时,它被假设为具备拥有者的权限。例如,若是该程序的全部者是root,那么当任何人运行这个程序时,该程序都能得到root的权限。在执行过程当中,Set-UID容许咱们作不少有趣的事情,但不幸的是,它也是许多很差的事情的罪魁祸首。所以,本实验的目的有两方面:程序员
(1)欣赏其好的一面:明白,为何设置UID是必要的,它是如何实现的。shell
(2)要注意其很差的一面,了解其潜在的安全问题。编程
实验步骤安全
这是一个探索性的实验,你的任务在Linux环境中和Set-UID机制玩游戏,写一份报告描述你的发现,你被要求在Linux中完成如下的实验。bash
1. 弄清楚为何“passwd”,“chsh”,“su”,和“sudo”命令须要Set-UID机制,若是它们没有这些机制的话,会发生什么,若是你不熟悉这些程序,你能够通话阅读使用手册来熟悉它,若是你拷贝这些命令到本身的目录下,这些程序就不会是Set-UID程序,运行这些拷贝的程序,观察将会发生什么。 ide
图1 拷贝程序到本身的目录下函数
从上面能够看出passwd、su、sudo、chsh被拷贝到lab1目录下后,就再也不是setuid程序了。而这些程序在原目录下是Set-UID程序。 学习
图2 测试passwd chsh su sudo命令的做用测试
从上面能够看出,passwd是用来修改当前用户密码的,chsh是用来修改默认的sh的,su是用来获取管理员权限的,sudo是用来执行一个须要管理员权限的命令的。
图3 运行lab1下的passwd chsh su sudo发现都失败
运行lab1下的passwd chsh su sudo发现都失败了。
思考1:
Q:为何要使用Set-UID程序?
A:由于passwd chsh su sudo都须要使得用户能在普通权限下临时具备root权限。从而能够访问和修改一些root权限下的文件,如shadow。可是,这个权限是受限的,有时还须要对用户的身份进行验证。
Q:SetUID的设计是必要的吗?
A:设想一下,若是没有SetUID程序。那么普通用户将没有权限修改本身的密码,没有权限去运行不少程序。不能安装软件。全部,SetUID是一种相似于对用户权限进行更精确粒度的控制。可是,用户在编写本身的SetUID程序时,须要很是的当心,否则可能会产生漏洞危害系统的安全。
二、在linux环境下运行Set-UID 程序,同时描述而且解释你的观察结果
以root方式登陆,拷贝/bin/zsh 到/tmp, 同时设置拷贝到tmp目录下的zsh为set-uid root权限,而后以普通用户登陆,运行/tmp/zsh。你会获得root权限吗?请描述你的结果。
(我是拷贝到了lab1下)
图4 测试zsh是否能够得到root权限
发现zsh是能得到root权限的,可见zsh是不安全的。接下来测试bash。
图5 测试bash是否安全
测试发现bash在一样的状况下,没法获取root权限。因而可知bash要比zsh更为安全。
3. 从题目2能够看出,/bin/bash有某种内在的保护机制能够阻止Set-UID机制的滥用。为了可以体验这种内在的保护机制出现以前的情形,咱们打算使用另一种/bin/zsh。在一些linux的发行版中(好比Redora和Ubuntu),/bin/sh其实是/bin/bash的符号连接。为了使用zsh,咱们须要把/bin/sh连接到/bin/zsh。
下面的指令将会把默认的shell指向zsh:
图6 将sh替换为zsh
将sh用符号链接到zsh。
4. PATH环境变量
system(const char * cmd)系统调用函数被内嵌到一个程序中执行一个命令,system()调用/bin/sh来执行shell程序,而后shell程序区执行cmd命令。可是在一个Set-UID程序中system()函数调用shell是很是危险的,这是由于shell程序的行为能够被环境变量影响,好比PATH;而这些环境变量能够在用户的控制当中。经过控制这些变量,用心险恶的用户就能够控制Set-UID程序的行为。
Q: 你可以设置这个Set-UID程序运行你本身的代码而不是/bin/ls吗?若是你能的话,你的代码具备root权限吗?描述并解释你的观察。
A:能够,基本思路是:经过修改PATH变量,是的system优先调用本身恶意制造的可执行程序ls。
下面的Set-UID程序被用来执行/bin/ls命令;而后程序员能够为ls命令使用相对路径,而不是绝对路径。
图7 a.c的源代码
图8 进行对a.c的攻击
可见,在上述操做中,攻击者能够利用system查找程序时PATH的顺序来攻击。可见这样的程序是存在漏洞的。
Q: 如今,修改/bin/sh使得其返回到/bin/bash,重复上面的攻击,你仍然能够得到root权限吗?描述并解释你的观察。
A: 不能够。bash有某种内在的保护机制能够防止这种攻击。
图9 sh符号连接到bash
图10 使用bash运行攻击程序
使用bash重复上述的攻击,发现bash没有得到root权限,这说明攻击失败。可见bash有某种内在的保护机制使得针对SetUID的攻击没法生效。
Q: 你可以设置这个Set-UID程序运行你本身的代码而不是/bin/ls吗?若是你能的话,你的代码具备root权限吗?描述并解释你的观察。
A: 能够具备root权限,我是这样作的:首先把/bin/sh拷贝到/lab1目录下面重命名为ls将环境变量PATH设置为当前目录/tmp,运行编译的程序system。就能够得到root权限。首先确保/bin/目录下的sh 符号连接到zsh,若是连接到bash,这种方式是获取不到root权限的,缘由正如上面所叙述的那样,/bin/bash有某种内在的保护机制能够阻止Set-UID机制的滥用。
5 .sytem()和execve()的不一样
在你执行这个任务以前,确保/bin/sh指向zsh,事件背景:Bob在为一家审计代理处工做,他正在调查一家公司是否存在诈骗行为。为了这个目的,他须要阅读这家公司在Unix系统中的全部文件;另外一方面,为了保护系统的可靠性,他不能修改任何一个文件。为了达到这个目的,Vince——系统的超级用户为他写了一个SET-ROOT-UID程序,而且给了Bob能够执行它的权限。这个程序须要Bob在命令行中打出一个文件名,而后运行/bin/cat命令显示这个文件。既然这个程序是以root权限运行的,它就能够显示Bob想看的任何一个文件。然而,既然这个程序没有写操做,Vince很确信Bob不能用这个程序修改任何文件。
作好准备,先把sh连接到zsh上,不然攻击极可能失败。
图11 从新链接sh到zsh
编辑b.c,代码以下:
图12 编辑b.c的代码
Q:令q = 0。这种方式,程序会使用system()调用命令行。这个命令安全码?若是你是Bob,你能对系统的完整性妥协吗?你能从新移动一个对你没有写权限的文件吗?
A: 不安全。由于Bob能够经过攻击,删改无权限访问的一些文件。攻击过程以下。
如今进行攻击模拟:
图13 编辑b.c的代码
能够看到,rootfile.dat不属于Bob,可是Bob能成功利用漏洞将其删除。
Q: 若是令q=1;在(a)中的攻击还会有效吗?请描述并解释你的观察。
A:无效,观察以下。
图14 编辑b.c的代码,把q赋值为1
重复上述攻击。
图15 对execve进行攻击
由此,可见system工做方式是,将后续的命令字符都传递给shell,交由shell来执行,这样极可能被攻击者利用shell的漏洞进行攻击。
而execve则是建立子进程,参数是传递给子进程的,所以能够防止此类攻击。
6. LD_PRELOAD环境变量
为了保证Set-UID程序在LD_PRELOAD环境的操纵下是安全的,动态连接器会忽略环境变量,可是在某些条件下是例外的,在下面的任务中,咱们猜想这些特殊的条件究竟是什么。
咱们创建一个动态连接库。把下面的程序命名为mylib.c。在函数库libc中重载了sleep函数。
图16 伪造sleep函数
用下面的命令编译上面的程序。
图17 编译上面的程序
编写myprog.c
图18 编写myprog.c
编译myprog.c
图19 编译myprog.c
在普通用户下运行,myprog,发现连接到的是mylib。
图20 普通用户下编译普通用户下执行
在root下编译myprog.out,并设置成SetUID程序。在普通用户下执行。
图21 root下编译普通用户下执行
发现是链接到真正的libc当中。
在root下编译myprog.out,并设置成SetUID程序。在root下执行。
图21 root下编译root下执行
发现,连接到的是mylib.c
在普通下编译myprog.out,并设置成SetUID程序。在其余用户下执行。
图21 普通用户下编译
在其余用户下运行
图22 其余普通用户下运行
可见,只有用户本身建立的程序本身去运行,才会使用LD_PRELOAD环境变量,连接到本身的sleep函数,不然的话忽略LD_PRELOAD环境变量,不会连接到本身的sleep函数。
7. 消除和清理特权
为了更加安全,Set-UID程序一般会调用setuid()系统调用函数永久的清除它们的root权限。然而有些时候,这样作是远远不够的。编译接下来的这个程序,给这个程序设置root权限。在一个普通的用户下,运行这个程序。
Q: 描述你所观察到的状况,/etc/zzz这个文件会被修改吗?解释你的观察。
A: 会被修改。由于代码中的fork函数会在建立子进程。子进程拥有父进程的数据、堆栈的拷贝。同时拥有的父进程的SetUID权限。在实际编程中,SetUID的程序每每会存在相似的漏洞,子进程能够得到父进程的相关的权限,好比打开的文件,所以在设计SetUID程序时须要注意这些细节信息。防止被攻击者利用。
图23 编辑7.c的源代码
图24 运行后/etc/zzz文件内容
实验总结
经过本次实验,对SetUID产生了较为初步的认识。同时,对以往编写的代码进行了思考。感受只有学习了信息安全,才能升入的把握程序内在的各类机制。从攻击的角度能更加细致的看待编程。由于只有懂得了程序正常工做的逻辑,才能从供给的角度对其进行破坏。所以更多的夯实基础,才是真正掌握信息安全的正确途径。不可能一簇而就,没有好的基础就能学习好信息安全的知识。