网络攻防--环境变量与Set_UID
一、实验内容:
本实验室的学习目标是让学生了解环境变量如何影响程序以及系统行为。环境变量是一组动态命名值,可以影响正在运行的进程将在计算机上运行。大多数操作系统都使用它们,因为它们是1979年引入Unix。尽管环境变量会影响程序行为,但它们是如何实现的这一点很多程序员都不太理解。因此,如果程序使用环境变量程序员不知道它们被使用,程序可能有漏洞。
在本实验室中,学生将了解环境变量是如何工作的,它们是如何从父进程到子进程,以及它们如何影响系统/程序行为。我们特别感兴趣的是如何环境变量影响Set-UID程序的行为,这些程序通常是特权程序。
本实验室涵盖以下主题:
?环境变量
?SET-UID程序
?安全地调用外部程序
?能力泄漏
?动态加载程序/链接器?
二、实验步骤及结果
Task1:Manipulating environment variables
1.使用printenv命令查看环境变量。
使用Printenv PWD命令指定查看环境变量PWD。
2.使用Export test=100命令添加环境变量,查看环境变量可以看到我们已经成功添加test环境变量。
3.使用Unset test命令删除刚才添加的环境变量。尝试打印,可以看到环境变量已经被删除。
Task2:Pasding Environment Variables from Parent Process to Child Process
1.编译myprintenv程序,并且执行生成的二进制文件a.out并将结果保存在1.txt文件中。
查看1.txt文件的内容:
2.注释掉和①printenv函数语句,执行②处的printenv函数。
再次编译执行,将结果输出到文件2.txt中。
查看文件2.txt的内容:
3.diff 1.txt 2.txt,比较两个文件,可以看到两个文件没有差别,子进程继承了父进程的环境变量信息。
Task3:Environment Variables and execve()
1.编译并运行程序myenv.c。可以看到程序运行成功,但是并没有打印出环境变量信息。这是因为此时execve()函数传递的环境变量为NULL,所以没有输出值。
2.修改代码,将execve()修改为execve(“/usr/bin/env”,argv,environ),第三个位置传递了环境变量environ(全局变量)。编译运行,观察结果。
修改了execve()参数后,成功打印出当前环境变量。
3.观察打出结论,第一次没有打印内容是因为没有传递环境变量,第二次因为传递了环境变量environ所以可以成功输出环境变量。
Task4:Encironment Variables and system()
1.创建程序并且编译执行。
分析:system()函数实质上时使用execl()函数生成子进程/bin/sh,然后在子进程中执行命令。相当于调用了execve()函数,参数/usr/bin/env相当于把环境变量传递给了execve()函数,因此可以成功打印出环境变量。
Task5:Environment Variables and Set-UID Programs
1.编写程序如下,依次打印出environ中的环境变量。
2.编译该程序,先查看可执行文件的用户及模式。
3.将该文件的有效用户为root,并且设置Set-UID的比特位,再次查看可执行文件的用户及模式
4.修改环境变量前,查看当前环境变量。
使用export方法添加环境变量如下:
使用task5打印环境变量,并过滤出其中含有PATH的环境变量。
观察结果:ADD_PATH PATH均成功加入子程序,但是LD_LIBRARY_PATH并没有成功传入。
Task6:The PATH Environment Variable and Set-UID Programs
1.编写如下程序,使用system()调用ls方法
根据提示,我们需要将/bin/sh链接到/bin/zsh绕过安全检查机制。
未进行Set_UID之前,task6正常执行 ls,结果如下:
将程序设置为root用户下的进行Set_UID程序。
我们将要执行我们的恶意指令,这里使用pwd。首先查看/bin文件下的pwd指令,找到它的位置。我们将pwd的命令程序复制到我们的目录下,并为其取名为ls。再修改PATH,再环境变量PATH的开始添加我们的目录,这样一来,再执行程序时,将先到我们的目录下查找到我们包装过的恶意指令。
执行程序,可以看到此时该程序已经运行我们包装过的恶意指令pwd。
Task7:The LD PELOAD Environment Variable and Set-UID Programs
1.编写mylib.c程序如下
将mylib.c编译成动态链接库,并且设置LD_PRELOAD环境变量为我们的动态链接库。
2.编写myprog.c程序如下,并且直接编译运行。
可以看到很短的时间内直接打印处结果,说明我们成功将sleep函数和我们定义的链接库链接到了一起。
3.将myprog程序的有效使用者修改为root,设置为Set-UID程序。重新运行程序,程序运行了大概一秒,但没有输出任何结果。
4.升级为root用户,在root用户下修改环境变量。此时再在root用户下执行该代码,可以看到很短的时间内就输出了结果。
5.使用sudo adduser命令新建用户***:
查看此时的myprog的有效用户,仍然时root,我们将其修改为新创建的用户***,再次执行代码,程序运行了大概一秒钟后没有输出任何结果。
分析:
1中,有效用户和真实用户均为seed,因此并没有忽略自定义的环境变量LD_PRELOAD,此时链接到的是自定义的动态链接库,ibmylib.so.1.0.1,输出打印结果。
2中,有效用户为root,真实用户为seed,真实用户与有效用户不同。此时环境变量LD_PRELOAD就被屏蔽(这正是动态链接器的防御机制),链接到的是原先的标准库libc,此时执行了sleep()没有输出。
3中,有效用户和真实用户均为root,因此并没有忽略自定义的环境变量LD_PRELOAD,保护机制没有生效。此时链接到的是自定义的动态链接库,ibmylib.so.1.0.1,输出打印结果。
4中,有效用户为***,真实用户为seed,真实用户与有效用户不同。此时环境变量LD_PRELOAD就被屏蔽,链接到的就不是自定义的动态链接库,而是原先的标准库,此时执行了sleep()没有输出。
Task8:Invoking External Programs Using system() versus execve()
1.修改catall代码,使得程序执行system(command);
编译catall.c程序并且运行,将程序设置为root用户下的进行Set_UID程序。
可以看到程序成功运行并且成功打印出catall.c的内容。
在root用户下,在目录中创建一个myfile文件,此文件的所有者是root,只有他对文件又执行修改权限。
返回seed用户,在catall的参数后面添加想要执行的指令,我们发现普通用户也可以对该文件执行删除操作。
回到root用户下,发现刚才创建的myfile已经被删除。在catall的帮助下我们可以成功删除。
2.修改代码,使得代码执行execve()函数。
编译catall.c程序并且运行,将程序设置为root用户下的进行Set_UID程序。
可以看到程序成功运行并且成功打印出catall.c的内容。
切换到root用户下,新建测试文件test.txt,回到seed用户,使用与之前相同的方法删除该文件,发现无法删除。
分析:这是因为system()本质上是调用shell执行指令,没有对代码和数据做区分,可以将两条指令分开执行,但是execve()函数实现了数据和代码的分离,他将我们输入的字符串理解为一个文件名,所以返回错误,并不存在这样的文件或者目录。
Task9:Capability leaking
1.修改代码,使得其能够向文件中写入新的信息。
2.创建文件/etc/zzz,并向其中写入信息” this is an import file!”。
编译cap_leak.c程序,并设置他的有效用户为root,设置为Set-UID程序。
运行cap,在程序执行成功后,再次查看文件的内容,发现已经被篡改。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!