管理环境变量
(1) env命令输出环境变量。
(2) 输出特定的环境变量
printenv PWD方法
env | grep PWD方法
(3)使用export命令设置环境变量
2.将环境变量从父进程传递给子进程
(1)使用vim编辑器编写程序
(2)编译运行程序,并将结果保存在child.txt文件中,可见已经成功的将子进程的环境变量输出并保存。
(3)利用vi命令进行编辑,将子进程的printenv()注释掉,父进程printenv()取消注释。重新编译源文件并运行,将结果保存到parent.txt文件中,使用diff进行父/子进程环境变量的对比,发现没有输出结果,说明两次输出的环境变量完全相同,子进程与父进程共享环境变量。
编译源文件并运行
环境变量对比
环境变量与execve()函数
(1)执行/usr/bin/enc程序,并打印当前进程的环境变量,添加包含execve()函数所在的头文件unistd.h,发现输出为空
(2)修改函数参数,并编译运行,将示例代码中的NULL改为environ,编译运行,此时输出了当前进程的环境变量:
环境变量与system()函数
(1) system()使用fork创建子进程,子进程继承父进程的环境变量,子进程通过execl()来启动/bin/sh,并调用execve()函数,将环境变量数组传递给新程序;所以调用进程的环境变量可以被传递给新程序/bin/sh
(3)编译运行实验代码
环境变量与Set-UID程序
Set-UID程序是指使文件对任何可以执行此文件的用户执行时以文件所有者的权限执行。Set-UID程序的行为由程序逻辑决定,但用户可以通过环境变量来影响Set-UID程序的行为。编写代码测试:
编译代码,打印当前进程的所有环境变量
更改所有权为Root账户并使其成为一个Set-UID程序,通过task5和task4的属性对比,说明操作成功
在普通用户Shell中设置环境变量并运行Set-UID程序
设置PATH
设置LD_LIBRARY_PATH 1
设置ANY_NAME
运行Set-UID程序,输出当前进程的环境变量
PATH环境变量与Set-UID程序
在Set-UID进程中调用system函数执行ls命令,需要通过修改环境变量执行我们自己设定的程序。编译代码如下,使用命令将/bin/sh链接到zsh,修改环境变量PATH,编译示例代码,修改所有者为Root,并将其设置为Set-UID程序,运行上述编译好的task6,发现执行的是ls命令:
修改环境变量,使得system调用的shell执行自己设定的程序
将/bin/sh 拷贝为当前目录下的文件ls,将当前目录添加到环境变量PATH中,然后执行exec就可以获得一个具有root权限的shell
LD_PRELOAD环境变量与Set-UID程序
(1)创建mylib.c文件编译以下程序,设置LD_PRELOAD环境变量,编译myprog.c文件,并放在与libmylib.so.1.0.1相同目录下
在以下四个不同场景中运行myprog可执行文件
普通用户下执行myprog
将myprog设置为Set-UID根程序,在普通用户下执行
3.将myprog设置为Set-UID根程序,并在root下设置LD_PRELOAD环境变量并运行。
首先我们需要登入root账户,并设置环境变量
① 以root用户运行
② 以普通用户运行
将myprog设置为Set-UID user1程序,并在seed用户下设置环境变量。
①在root用户下,建立新的用户user1
②设置myprog和环境变量
③在seed用户下运行Set-UID程序,发现正常执行程序,sleep 1秒,然后退出程序。
(1)设计实验并解释上述现象
- 分别在上述四种场景中,将用户进程和子进程的环境变量输出为文件,并进行对比,找出不同(重点关注LD_PRELOAD),在整个实验过程中,seed用户下始终设置LD_PRELOAD环境变量。编译代码命名为test.c,编译为test可执行文件
- 普通用户下执行test程序,root用户下修改环境变量,这里可见test程序与用户进程的环境变量一致,然后分别查看二者的环境变量中是否有LD_PRELOAD变量。发现一样,可见子进程继承了用户进程的LD_PRELOAD环境变量。
- 普通用户下执行
将test设置为Set-UID根程序,并在seed用户下执行,此时输出子进程的环境变量;将test设置为普通程序,在seed用户下执行,此时输出父进程的环境变量。通过diff命令发现二者在LD*环境变量上有差异,当我们打开父进程的环境变量可以发现LD*环境变量,而在子进程的环境变量中找不到。可见,子进程并没有继承父进程的LD*环境变量。
- root用户下运行,发现此时二者的环境变量一致,分别查看二者的环境变量一致,父进程和子进程均为:export LD_PRELOAD=./libmylib.so.1.0.1
- 使用system与execve调用外部程序
观察代码,在命令行执行此程序时,会输出command命令,command命令由v[0] + v[1]组成也就是进行了字符串的拼接,而v[1]是通过我们在命令行的输入来决定的,所以我们可以控制我们的输入来达到对命令的控制。Argc 统计发送给main函数的参数个数,Argv为字符串数组。V[1]是输入的第一个字符串。
(1)使用system()调用外部程序,删除根用户拥有的文件
- 编译并设置为Set-UID根程序
- 在root用户下创建一个home1目录,在该目录下创建一个名为为hello.c的文件,并在seed下删除。一开始没有创建home1目录,直接创建了hello.c文件。执行task8程序,删除hello.c文件。结果:显示文件内容,并且成功删除不可写文件。
(2)修改task8.c文件,重新编译,设置为Set-UID根程序,将system注释掉,execve反注释掉。编译发现少了头文件unistd.h,加上头文件重新编译并设置为Set-UID根程序
(3)在root用户下创建一个home1目录,在该目录下创建一个名为为hello.c的文件,并在根用户下删除。执行task8程序,删除hello.c文件,结果如下
- 权限泄露
(1)编译代码
根据注释,我们首先需要创建一个权限为0644且为根用户所有的文件。然后模拟使用root权限;任务完成后,不再需要根权限,通过setuid(getuid())放弃根权限,恢复进程的拥有者为真实执行该进程的用户ID;然后通过fork创建一个子进程,父进程关闭打开的文件,子进程向创建的新文件中写入字符串。
- root下创建一个etc文件夹,文件夹内创建zzz文件,并设置其权限为0644, zzz文件内容:helloWord
- . 编译示例代码,将文件设置为我们创建的zzz文件,编译出现多个warning,添加头文件,然后重新编译并设置为Set-UID根程序,在root用户下运行代码,发现字符串成功写入zzz文件,而zzz文件是root下的只读文件。
标签:Set,UID,程序,编译,Linux,进程,环境变量 From: https://www.cnblogs.com/yuuwx/p/17371078.html