
mykaneki
2022/09/20阅读:69主题:凝夜紫
SEED-Labs
lab 1 Set-UID
Task 1: Manipulating Environment Variables
控制环境变量
-
查看环境变量
-
printenv
orenv
-
-
导出和清除变量
-
export命令显示当前导出成用户变量的shell变量 -
unset命令用于删除已定义的shell变量(包括环境变量)和shell函数。unset命令不能够删除具有只读属性的shell变量和环境变量
-
-
实验截图
-
image-20220831113813559 -
[08/30/22]seed@VM:~$ declare var1=1 var2=2 var3=3
[08/30/22]seed@VM:~$ echo $var1 $var2 $var3 $var4
1 2 3
[08/30/22]seed@VM:~$ unset var2
[08/30/22]seed@VM:~$ echo $var1 $var2 $var3 $var4
1 3
[08/30/22]seed@VM:~$ export | grep var
declare -x XDG_DATA_DIRS="/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop"
declare -x var1="1"
declare -x var3="3"
[08/30/22]seed@VM:~$ env |grep var
var1=1
var3=3
XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
[08/30/22]seed@VM:~$ set -a var
[08/30/22]seed@VM:~$ export var2=2
[08/30/22]seed@VM:~$ env |grep var
var1=1
var2=2
var3=3
XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
[08/30/22]seed@VM:~$ readonly var2
[08/30/22]seed@VM:~$ unset var2
bash: unset: var2: cannot unset: readonly variable
-
Task 2: Passing Environment Variables from Parent Process to Child Process
将环境变量从父进程传递给子进程
-
运行文件
image-20220831120457012 -
注释①,取消注释②,再重新运行文件
image-20220831121146030 -
比较两个文件
image-20220831122252137 -
结论
输出结果相同,父子进程的环境变量相同,子进程会完全继承父进程的环境变量
Task 3: Environment Variables and execve()
研究当一个新程序通过 Execve ()执行时,环境变量是如何受到影响的,例如:它们是否会被新程序自动继承
-
请编译并运行程序myenv.c,并描述您的观察结果。这个程序只是执行一个名为/usr/bin/env 的程序,它打印出当前进程的环境变量
[08/31/22]seed@VM:~/.../Labsetup$ gcc myenv.c
[08/31/22]seed@VM:~/.../Labsetup$ a.out > env1.txt
[08/31/22]seed@VM:~/.../Labsetup$ vim env1.txt结果:无输出
-
修改
execve("/usr/bin/env", argv, NULL);
为execve("/usr/bin/env", argv, environ);
image-20220831210758674 -
比较两次结果
-
第一次无结果,第二次结果和env命令运行结果相同,如图
image-20220831213607172 -
查询 execve()
原型及其功能:
int execve(const char *filename, char *const argv[],
char *const envp[]);execve()执行程序由 filename决定。 filename必须是一个二进制的可执行文件,或者是一个脚本以#!格式开头的解释器参数参数。如果是后者,这个解释器必须是一个可执行的有效的路径名,但是不是脚本本身,它将调用解释器作为文件名。
argv是要调用的程序执行的参数序列,也就是我们要调用的程序需要「传入的参数」。
envp 同样也是参数序列,一般来说他是一种键值对的形式 key=value. 作「为我们是新程序的环境」。
-
结论:第一次未传入新程序的环境,因此无结果;第二次传入「动态」环境,作为env命令的参数,打印出来。因此,一个新程序通过execve()运行时,环境不会自动继承,需要手动传入。
-
补充:为什么前面说的是「动态」环境?与environ相似的是envp。
environ是全局变量,若程序执行过程中环境变量发生变化,则上述execve会采用最新的环境变量。envp是main函数运行时导入,若在main函数执行过程中环境变量发生修改,envp并不会修改,则execve函数使用旧版的环境变量,需要putenv(),setenv()重新获取。
-
Task 4: Environment Variables and system()
在这个任务中,我们研究了当一个新程序通过 system ()函数执行时,环境变量是如何受到影响的。这个函数用于执行命令,但是不同于 Executive ()直接执行命令,system ()实际上执行“/bin/sh-c 命令”,也就是说,它执行/bin/sh,并请求 shell 执行命令。如果查看 system ()函数的实现,您将看到它使用 Execl ()来执行/bin/sh; Execl ()调用 Execve () ,并将环境变量数组传递给它。因此,使用 system ()将调用进程的环境变量传递给新程序/bin/sh。请编译并运行以下程序来验证这一点

Task 5: Environment Variable and Set-UID Programs
Set-UID 是 Unix 操作系统中一种重要的安全机制。当 Set-UID 程序运行时,它假定拥有者的特权。例如,如果程序的所有者是 root 用户,当任何人运行该程序时,程序在执行期间获得 root 用户的特权。Set-UID 允许我们做许多有趣的事情,但是由于它提高了用户的权限,所以风险很大。虽然 Set-UID 程序的行为是由程序逻辑决定的,而不是由用户决定的,但是用户确实可以通过环境变量影响程序的行为。为了「理解 Set-UID 程序是如何受到影响的」,让我们首先弄清楚环境变量是否由 Set-UID 程序的进程从用户的进程继承
-
第一步:创建程序task5.c,并运行,观察
image-20220901212139683 -
第二步:编译程序,修改所有者并提权,运行观察
image-20220901212714336 -
第三步:在非root用户下修改环境,再次运行程序,观察
-
普通变量修改后依旧可以显示
image-20220901213451492 -
修改变量
PATH
和新增变量LD_LIBRARY_PATH
的测试情况image-20220901214743866 PATH修改结果显示,但是LD_LIBRARY_PATH没有显示(经测试,直接在shell查看该环境可以显示出来)。
-
结论:「LD_LIBRARY_PATH」主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。动态链接器的保护机制,为了使 Set-UID 程序更加安全,不受LD_LIBRARY_PATH环境变量的影响。如果程序是个 Set-UID 程序 ,运行时的链接器或加载器(ld.so)会忽略该环境变量,在编译后设置了该程序的有效ID为root,而在普通用户shell中运行时,真实用户为seed,因此此处设置的环境变量被忽略,没有起作用。
-
Task 6: The PATH Environment Variable and Set-UID Programs
由于调用的是 shell 程序,因此在 Set-UID 程序中调用 system ()非常危险。这是因为 「shell 程序的实际行为可能受到环境变量(如 PATH)的影响; 这些环境变量由可能是恶意的用户提供。通过更改这些变量,恶意用户可以控制 Set-UID 程序的行为」。在 Bash 中,您可以按照以下方式更改 PATH 环境变量(本示例将目录/home/種添加到 PATH 环境变量的开头
-
修改PATH
image-20220904160420189 -
尝试运行恶意代码
[09/04/22]seed@VM:~/.../Labsetup$ touch task6.c
[09/04/22]seed@VM:~/.../Labsetup$ vim task6.c
[09/04/22]seed@VM:~/.../Labsetup$ touch fake_ls.c
[09/04/22]seed@VM:~/.../Labsetup$ vim fake_ls.c
[09/04/22]seed@VM:~/.../Labsetup$ gcc task6.c -o task6.out
task6.c: In function ‘main’:
task6.c:3:1: warning: implicit declaration of function ‘system’ [-Wimplicit-function-declaration]
3 | system("ls");
| ^~~~~~
[09/04/22]seed@VM:~/.../Labsetup$ sudo chown root task6.out
[09/04/22]seed@VM:~/.../Labsetup$ sudo chmod 4755 task6.out
[09/04/22]seed@VM:~/.../Labsetup$ export PATH=/home/seed/SEEDLabs/lab1/Labsetup:$PATH
[09/04/22]seed@VM:~/.../Labsetup$ sudo ln -sf /bin/zsh /bin/sh
[09/04/22]seed@VM:~/.../Labsetup$ gcc fake_ls.c -o ls
[09/04/22]seed@VM:~/.../Labsetup$ ./task6.out
fakels!!! -
总结:设置PATH最高优先搜索路径,可以改变
system("ls")
的执行程序
Task 7: The LD PRELOAD Environment Variable and Set-UID Programs
在本课题中,我们研究 Set-UID 程序如何处理一些环境变量。几个环境变量(包括
LD_PRELOAD
、LD_LIBRARY_PATH
和其他LD_*
)影响动态加载程序/链接程序的行为。动态加载器/链接器是操作系统(OS)的一部分,操作系统加载(从持久存储到 RAM)并链接运行时可执行文件所需的共享库。在 Linux 中,ld.so
或ld-Linux.so
。因此,动态加载程序/链接器也是如此(每个加载程序/链接器用于不同类型的二进制文件)。在影响其行为的环境变量中,LD_LIBRARY_PATH
和LD_PRELOAD
是本实验所关注的两个变量。在 Linux 中,LD LIBRARY PATH 是一组用冒号分隔的目录,在这些目录中,应该首先搜索库,然后才是标准目录集。LD_PRELOAD
指定要在所有其他库之前加载的用户指定的附加共享库列表。在这个任务中,我们将只研究LD_PRELOAD
。
-
环境变量在运行普通程序时如何影响动态加载程序/链接程序的行为
-
创建动态链接库,覆盖libc的sleep()
/*mylib.c*/
#include <stdio.h>
void sleep (int s)
{
/* If this is invoked by a privileged program,
you can do damages here! */
printf("I am not sleeping!\n");
} -
用以下代码编译
mylib.c
$ gcc -fPIC -g -c mylib.c
$ gcc -shared -o libmylib.so.1.0.1 mylib.o -lc -
设置
LD_PRELOAD
$ export LD_PRELOAD=./libmylib.so.1.0.1
-
最后,在上面的动态链接库
libmylib.so.1.0.1
的相同目录下编译以下程序myprog.c
/* myprog.c */
#include <unistd.h>
int main()
{
sleep(1);
return 0;
}
-
-
请在以下条件下运行
myprog
,并观察发生的情况。-
在seed用户下运行myprog
异常
-
在seed用户下运行Set-UID root myprog
正常
-
使用root用户(密码重新修改为:root),添加上述环境,运行Set-UID root myprog
异常
-
新建用户user1,添加上述环境,使用seed运行Set-UID user1 myprog
正常
-
使用user1运行Set-UID user1 myprog
异常
-
-
编写程序验证子进程在什么情况才会继承 LD * 环境变量
-
使用
myprintenv.c
的副本task73_printenv.c
-
程序为常规程序。以seed用户更改环境变量,以seed用户执行程序。
image-20220908094545149 子进程继承了用户进程的LD_PRELOAD环境变量
-
程序为所有者为root的Set-UID 程序。以seed用户更改环境变量,以seed用户执行程序。
image-20220908100227920 父进程和子进程都没有继承该变量
-
程序为所有者为root的Set-UID 程序。以root用户更改环境变量,以root用户执行程序
image-20220908101113375 -
程序为所有者为user1的Set-UID程序。以seed用户执行程序。
-
作者介绍
