漏洞挖掘——实验2 Environment_Variable_and_SetUID
漏洞挖掘前言
题目
lab
Environment_Variable_and_SetUID
pre
1、linux下用open函数打开文件时,要是采用O_WRONLY模式为何容易产生竞争条件漏洞?
换成O_WRONLY | O_CREAT | O_EXCL 模式后情况会如何?
2、(不需要完全搞懂全部流程)阅读一篇文章“从一个漏洞谈到ptrace的漏洞发现及利用方法”,地址为http://www.nsfocus.net/index.php?act=magazine&do=view&mid=1795。描述其中的竞争条件漏洞出现的原因。
3、(选做)上网搜索CVE-2016-5195漏洞的相关资料。描述其中的整数溢出和竞争条件漏洞
出现的原因。
4、echo "crack:"$(openssl passwd -1 -salt a3g1 123456)":0:0:,,,:/root:/bin/bash"的输出
结果是什么?root用户把输出的这一行加入/etc/passwd末尾会产生什么效果?(提前备份该文件,之后恢复)
解答
Lab
1.Task 1: Manipulating environment variables
(1)使用printenv命令输出环境变量输入命令printenv,得到如下结果(截取部分):
使用printenv命令查看PATH环境变量,得到如下结果:
(2)使用export和unset设置或删除环境变量
使用export设置环境变量,使用echo显示,$符号实际作用是将变量转换成字符,方便输出。
使用unset删除环境变量。
2. Task 2: Inheriting environment variables from parents
(1)编译C文件,将结果保存为a.out文件将代码保存为demo.c文件并放在桌面。进入桌面路径,编译C文件。
执行保存结果的a.out文件,查看代码的运行结果,发现为各个环境变量的值(截取部分)。
(2)按题意,将child process中printenv()注释,将process中parent printenv()取消注释,重新保存编译C文件。
执行保存结果的b.out文件,查看代码的运行结果,发现为各个环境变量的值(截取部分)。
(3)比较两者结果
将a.out、b.out文件的结果分别保存为child和parent文件,再使用diff命令比较,发现两者除了文件名外完全相同。这说明子进程环境变量会继承父环境变量。进一步查阅资料了解到,子进程自父进程继承到进程的资格、环境、堆栈、内存等,但子进程所独有的是不同的父进程号、自己的文件描述符和目录流的拷贝、在tms结构中的系统时间、不继承异步输入和输出等
3.Task 3: Environment variables and execve()
(1)编译并运行以下程序。描述观察到的实验结果。该程序简单地调用了/usr/bin/env,该系统调用能够打印出当前进程的环境变量。
重新保存和编译文件,发现执行结果为空。
查询函数execve()的作用,其调用格式如下:
int execve(const char * filename,char * const argv[],char * const envp[])
第一个参数为一个可执行的有效的路径名。第二个参数系利用数组指针来传递给执行文件,argv是要调用的程序执行的参数序列,也就是我们要调用的程序需要传入的参数。
envp则为传递给执行文件的新环境变量数。
所以在此处,我们赋予新进程的环境变量为空,自然印出环境变量结果为空。
(2)把execve()的调用改为以下内容,观察结果
将原语句换为:execve("/usr/bin/env", argv, environ); 重新保存和编译文件,得到如下结果。
(3)描述实验结论
从以上实验可以看出,execve()产生的新进程的环境变量又调用时重新赋予,而fork()则是直接继承父进程环境变量。
4.Task 4: Environment variables and system()
重新保存和编译文件
得到如下结果(截取部分):
查阅资料得system()的调用格式如下:
int system(const char * string)
system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命>令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
具体个描述为这样三个步骤:调用fork()函数新建一个子进程;在子进程中调用exec函数去执行command;在父进程中调用wait去等待子进程结束。
返回值 =-1:出现错误 =0:调用成功但是没有出现子进程 >0:成功退出的子进程的id 如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值>。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。
5.Task 5: Environment variable and Set-UID Programs
(1)在当前进程中打印出所有的环境变量
重新保存、编译和执行给出的代码,得到如下结果(截取部分),此结果就是当前所有环境变量:
(2)将上述程序的所有权改为root,并使它成为一个Set-UID程序
先切换为root账户,使用chown root:root demo5.c将此c文件权限改为root权限
(3)使用一般用户登录终端,使用export命令设置如下环境变量:PATH 、LD_LIBRARY_PATH、ANY_NAME
export PATH="$PATH:/usr/local/"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/"
export LXJ="/usr/local"
执行已经赋予Set-UID的demo5.c程序,得到如下结果:
可以看到,以上三个被定义的环境变量全部被包括在shell中。
6.Task 6: The PATH Environment variable and Set-UID Programs
保存代码为demo6.c文件,切换为root用户,将其编译为demo6,并设置其所有者为root,赋予SUID特殊权限。
使用ls -l demo6语句查看文件的权限,验证操作确实成功完成,符合题设条件
将bin/sh复制到当前目录并命名为ls,执行demo6就会获得root权限。详细分析,先看一下PATH环境变量,它的命令找寻顺序是先找寻当前目录,而当前目录我们自己编造了一个ls,所以程序就会直接执行伪造的ls。sh原本的作用是创建一个新shell,在执行此命令后我们就会一直停留在子进程中,知道我们主动退出这个程序,我们才会回到原来的权限。
8.Task 8: Invoking external programs using system() versus execve()
(1)编译上面的程序,把它的所有者变成它的所有者,并将它更改为一个Set-UID程序。该程序将使用system()来调用该命令。如果你是鲍勃,你能破坏系统的完整性吗?例如,您能删除一个不能写入的文件吗?
保存代码为demo8.c文件,切换为root用户,将其编译为demo8,并设置其所有者为root,赋予SUID特殊权限。
新建一个名为MY的文件,并设置其权限为仅root用户可读、写、执行。
执行demo8,发现原本只有root用户才具有读、写、执行的MY文件,已经更名为my
(2)注释掉system(command)语句,并取消execve()语句;该程序将使用execve()来调用该命令。编译程序,并使之成为Set-UID(由root拥有)。你在步骤1中的攻击仍然有效吗?请描述并解释你的观察。
重新编译demo8文件,并设置其所有者为root,赋予SUID特殊权限。新建一个名为MY的文件,并设置其权限为仅root用户可读、写、执行。
执行demo8,发现上一步的攻击方法已经失效
分析其原因,是因为execve()函数会把file; mv file file_new 看成是一个文件名,系统会提示不存在这个文件,system()则不会。
9.Task 9: Capability Leaking
先切换为root用户,创建/etc/zzz,设置其为只有root用户可以写入。保存代码为demo9.c文件,将其编译为demo9,并赋予SUID特殊权限。
执行demo9,查看内容,发现被写入信息
分析其原因是因为其在取消权限前并没有关闭文件,导致seed用户任然可以进行root用户才可以执行的写入操作。
Pre
1.linux下用open函数打开文件时,要是采用O_WRONLY模式为何容易产生竞争条件漏洞?换成O_WRONLY | O_CREAT | O_EXCL 模式后情况会如何?
open 函数用于打开和创建文件。open()的调用格式为
int open(const char *pathname, int oflag, ... );
返回值:成功则返回文件描述符,否则返回 -1
O_WRONLY的含义是只写打开;O_CREAT含义是文件存在则使用,不存在则新建 ;O_EXCL含义是检查文件是否存在,不存在则新建,存在则返回错误信息
如果只采用O_WRONLY模式,root总是可以创建文件,即便锁文件已经存在。换成O_WRONLY | O_CREAT | O_EXCL 模式后,就将权限设置为0,使同一用户的其他进程无法获得锁。
2.阅读一篇文章“从一个漏洞谈到ptrace的漏洞发现及利用方法”。描述其中的竞争条件漏洞出现的原因。
current指向这个内核线程exec_modprobe()的task_struct结构,而与创建这个线程时的current不同,那时候的current指向当时的当前进程,即exec_modprobe()的父进程。内核线程exec_modprobe()从其父进程继承了绝大部分资源和特性。但是这些特性在这个函数里大多被拚弃了,不过在拚弃这些特性之前之前,我们的父进程,或同组进程却是可以调试该内核线程的。
当进程请求的功能在模块中的情况下,内核就会派生一子进程,并把子进程的euid和egid设置为0并调用execve("/sbin/modprobe")。问题是在子进程euid改变为0前可以被ptrace()挂接调试,因此攻击者可以插入任意代码到进程中并以root用户的权限运行。
3.上网搜索CVE-2016-5195漏洞的相关资料。描述其中的整数溢出和竞争条件漏洞出现的原因。
脏牛漏洞(DirtyCOW)是由于Linux内核的内存子系统在处理copy-on-write(COW)时出现竞争条件,导致私有只读存储器映射被破坏,可利用此漏洞非法获得读写权限,进而提升权限。
在网上并没有找到赃牛漏洞的整数溢出和竞争条件漏洞出现的具体细节,大多都是泛泛而谈。
4.echo "crack:"$(openssl passwd -1 -salt a3g1 123456)":0:0:,,,:/root:/bin/bash"的输出结果是什么?root用户把输出的这一行加入/etc/passwd末尾会产生什么效果?(提前备份该文件,之后恢复)
echo "crack:"$(openssl passwd -1 -salt a3g1 123456)":0:0:,,,:/root:/bin/bash"的输出结果:
更多推荐
所有评论(0)