SetUID程序漏洞

实验目的

      本次实验目的是深入的了解SetUID程序,了解SetUID程序解决的问题。设计SetUID程序需要注意的地方。了解其潜在的安全问题。

实验内容

      在Unix操作系统中,Set-UID是一个重要的安全机制。 Set-UID程序运行时,它被假设为具有拥有者的权限。例如,如果该程序的所有者是root,那么当任何人运行这个程序时,该程序都能获得root的权限。在执行过程中,Set-UID允许我们做很多有趣的事情,但不幸的是,它也是许多不好的事情的罪魁祸首。因此,本实验的目的有两方面:

(1)欣赏其好的一面:明白,为什么设置UID是必要的,它是如何实现的。

(2)要注意其不好的一面,了解其潜在的安全问题。

实验步骤

      这是一个探索性的实验,你的任务在Linux环境中和Set-UID机制玩游戏,写一份报告描述你的发现,你被要求在Linux中完成以下的实验。

      1. 弄清楚为什么“passwd”,“chsh”,“su”,和“sudo”命令需要Set-UID机制,如果它们没有这些机制的话,会发生什么,如果你不熟悉这些程序,你可以通话阅读使用手册来熟悉它,如果你拷贝这些命令到自己的目录下,这些程序就不会是Set-UID程序,运行这些拷贝的程序,观察将会发生什么。

wps_clip_image-7748

图1 拷贝程序到自己的目录下

      从上面可以看出passwd、su、sudo、chsh被拷贝到lab1目录下后,就不再是setuid程序了。而这些程序在原目录下是Set-UID程序。

wps_clip_image-26654

图2 测试passwd chsh su sudo命令的作用

      从上面可以看出,passwd是用来修改当前用户密码的,chsh是用来修改默认的sh的,su是用来获取管理员权限的,sudo是用来执行一个需要管理员权限的命令的。

wps_clip_image-13778

图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程序时,需要非常的小心,不然可能会产生漏洞危害系统的安全。

      2、在linux环境下运行Set-UID 程序,同时描述并且解释你的观察结果

      以root方式登录,拷贝/bin/zsh 到/tmp, 同时设置拷贝到tmp目录下的zsh为set-uid root权限,然后以普通用户登录,运行/tmp/zsh。你会得到root权限吗?请描述你的结果。

(我是拷贝到了lab1下)

wps_clip_image-21917

图4 测试zsh是否可以获得root权限

      发现zsh是能获得root权限的,可见zsh是不安全的。接下来测试bash。

wps_clip_image-31607

图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:

wps_clip_image-23145

图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命令使用相对路径,而不是绝对路径。

wps_clip_image-27521

图7 a.c的源代码

wps_clip_image-4129

图8 进行对a.c的攻击

      可见,在上述操作中,攻击者可以利用system查找程序时PATH的顺序来攻击。可见这样的程序是存在漏洞的。

      Q: 现在,修改/bin/sh使得其返回到/bin/bash,重复上面的攻击,你仍然可以获得root权限吗?描述并解释你的观察。

      A: 不可以。bash有某种内在的保护机制可以防止这种攻击。

wps_clip_image-13683

图9 sh符号链接到bash

wps_clip_image-31512

图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上,否则攻击很可能失败。

wps_clip_image-31691

图11 重新连接sh到zsh

      编辑b.c,代码如下:

wps_clip_image-28028

图12 编辑b.c的代码

      Q:令q = 0。这种方式,程序会使用system()调用命令行。这个命令安全码?如果你是Bob,你能对系统的完整性妥协吗?你能重新移动一个对你没有写权限的文件吗?

      A: 不安全。因为Bob可以通过攻击,删改无权限访问的一些文件。攻击过程如下。

      现在进行攻击模拟:

wps_clip_image-17150

图13 编辑b.c的代码

      可以看到,rootfile.dat不属于Bob,但是Bob能成功利用漏洞将其删除。

      Q: 如果令q=1;在(a)中的攻击还会有效吗?请描述并解释你的观察。

      A:无效,观察如下。

wps_clip_image-28902

图14 编辑b.c的代码,把q赋值为1

      重复上述攻击。

wps_clip_image-4434

图15 对execve进行攻击

      由此,可见system工作方式是,将后续的命令字符都传递给shell,交由shell来执行,这样很可能被攻击者利用shell的漏洞进行攻击。

      而execve则是创建子进程,参数是传递给子进程的,因此可以防止此类攻击。

6. LD_PRELOAD环境变量

      为了保证Set-UID程序在LD_PRELOAD环境的操纵下是安全的,动态链接器会忽略环境变量,但是在某些条件下是例外的,在下面的任务中,我们猜测这些特殊的条件到底是什么。

      我们建立一个动态链接库。把下面的程序命名为mylib.c。在函数库libc中重载了sleep函数。

wps_clip_image-20817

图16 伪造sleep函数

      用下面的命令编译上面的程序。

wps_clip_image-3706

图17 编译上面的程序

      编写myprog.c

wps_clip_image-31936

图18 编写myprog.c

      编译myprog.c

wps_clip_image-10527

图19 编译myprog.c

      在普通用户下运行,myprog,发现链接到的是mylib。

wps_clip_image-17693

图20 普通用户下编译普通用户下执行

      在root下编译myprog.out,并设置成SetUID程序。在普通用户下执行。

wps_clip_image-14788

图21 root下编译普通用户下执行

      发现是连接到真正的libc当中。

      在root下编译myprog.out,并设置成SetUID程序。在root下执行。

wps_clip_image-15900

图21 root下编译root下执行

      发现,链接到的是mylib.c

      在普通下编译myprog.out,并设置成SetUID程序。在其他用户下执行。

wps_clip_image-5534

图21普通用户下编译

      在其他用户下运行

wps_clip_image-32549

图22其他普通用户下运行

      可见,只有用户自己创建的程序自己去运行,才会使用LD_PRELOAD环境变量,链接到自己的sleep函数,否则的话忽略LD_PRELOAD环境变量,不会链接到自己的sleep函数。

7. 消除和清理特权

      为了更加安全,Set-UID程序通常会调用setuid()系统调用函数永久的清除它们的root权限。然而有些时候,这样做是远远不够的。编译接下来的这个程序,给这个程序设置root权限。在一个普通的用户下,运行这个程序。

      Q: 描述你所观察到的情况,/etc/zzz这个文件会被修改吗?解释你的观察。

      A: 会被修改。因为代码中的fork函数会在创建子进程。子进程拥有父进程的数据、堆栈的拷贝。同时拥有的父进程的SetUID权限。在实际编程中,SetUID的程序往往会存在类似的漏洞,子进程可以获得父进程的相关的权限,比如打开的文件,因此在设计SetUID程序时需要注意这些细节信息。防止被攻击者利用。

wps_clip_image-22875

图23 编辑7.c的源代码

wps_clip_image-4492

图24 运行后/etc/zzz文件内容

实验总结

      通过本次实验,对SetUID产生了较为初步的认识。同时,对以往编写的代码进行了思考。感觉只有学习了信息安全,才能升入的把握程序内在的各种机制。从攻击的角度能更加细致的看待编程。因为只有懂得了程序正常工作的逻辑,才能从供给的角度对其进行破坏。因此更多的夯实基础,才是真正掌握信息安全的正确途径。不可能一簇而就,没有好的基础就能学习好信息安全的知识。

原文地址:https://www.cnblogs.com/sj20082663/p/3021834.html