第一部分:实验描述

该实验的学习任务是理解环境变量是如何影响程序和系统行为的。环境变量是一组动态命名的变量


第二部分:实验任务

2.1 任务一:操作环境变量

在这个任务中,我们研究可以用来设置和取消设置环境变量的命令。我们在seed实验环境中使用Bash。用户使用的默认shell在/etc/passwd文件(每个条目的最后一个字段)中设置。您可以使用命令chsh 将其更改为另一个shell程序(请不要在该实验中实现)。执行以下任务:

  • 使用printenv或env命令打印出环境变量。也可以单独打印出某个感兴趣的环境变量的值。例如:PWD,可以用如下命令:”printenv PWD “或者“env | grep PWD”单独打印出来。
  • 使用export或者unset命令设置或去掉环境变量。需要注意的是,这两个命令是Bash内部分命令。

2.2  任务二:继承环境变量

在这个任务中,我们学习环境变量是如何通过子进程完成继承机制。在Unix操作系统中,fork()通过负值调用进程建立一个新的进程。新的进程称为子进程,与其父进程完全相同。但是,子进程没有继承父进程的某些特性。(man fork)。在该任务中,我们会了解原坏境变量是否被子进程继承。

  • 步骤一:编译并运行程序:

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h> extern char **environ; void printenv()
    {
    int i = ;
    while (environ[i] != NULL) {
    printf("%s\n", environ[i]);
    i++;
    }
    } void main()
    {
    pid_t childPid; switch(childPid = fork()) {
    case : /* child process */
    printenv();
    exit();
    default: /* parent process */
    //printenv();
    exit();
    }
    }

    运行的结果(保存在child文件中):

  • 步骤二:在代码的switch语句中,子进程的情形下,注释掉printenv语句;父进程保持不变。编译并运行程序,将结果保存在child2文件中。
  • 步骤三:比较child和child2文件,写出结论。

2.3 任务三:环境变量和execve()

在该任务中,我们研究当通过execve()执行新程序时环境变量如何受到影响。函数execve()调用系统调用来加载新的命令并执行它。该函数不会返回,也咩没有新的过程被创建。相反,调用进程的文本,数据,bss和堆栈被加载的程序覆盖。基本上,execve()函数在调用进程内运行新的程序。我们对环境变量会发生什么感兴趣;他们是否自动继承了新程序?

  • 步骤一:编译并运行以下程序。描述观察到的实验结果。该程序简单地调用了/usr/bin/env,该系统调用能够打印出当前进程的环境变量。
  • 步骤二:现在,改变execve()函数的参数,描述你观察到的结果。
  • 步骤三:请得出关于新程序如何获取其环境变量的结论。

2.4 任务四:环境变量和system()

在该任务中,我们研究当通过system()执行新程序时华环境变量如何受到影响。system()函数被用于执行命令,但是不像execve()那样直接执行一个命令。system()函数实际上执行的是如下命令:“/bin/sh -c command”,例如执行“/bin/sh”,即请求一个shell。

如果你看system()函数的实现,你会看到它使用execl()执行/bin/sh;excel()调用execve(),传递给它的环境变量数组。因此,使用system(),调用进程的环境变量被传递被新的程序/bin/sh。请编译并运行以下程序来验证这一点。

#include <stdio.h>
#include <stdlib.h> int main()
{
system("/usr/bin/env"); return ;
}

2.5 任务五:环境变量和Set-UID程序

Set-UID是一种重要的安全机制。当一个Set-UID程序运行时,它会获得程序所有者的特权。例如,如果程序所有者是root用户,那么任何人运行该程序时,该程序都会获得root用户的特权。Set-UID允许我们做许多有趣的事情,但是当它运行时,会升级用户的权限,会带来很大的风险。尽管Set-UID程序的行为是由代码逻辑决定的,而不是用户,用户能够通过环境变量来影响行为。为了理解Set-UID程序是如何被影响的,让我们首先指出哪些环境变量是否由用户进程的Set-UID程序的进程继承。

  • 步骤一:在当前步骤中写一个能够输出所有环境变量的程序
#include <stdio.h>
#include <stdlib.h> extern char **environ; void main()
{
int i = ;
while (environ[i] != NULL) {
printf("%s\n", environ[i]);
i++;
}
}
  • 步骤二:编译以上程序,将其权限改为roo权限,使其成为一个Set-UID程序。
  • 步骤三:使用一般用户登录终端,使用export命令设置如下环境变量:PATH LD_LIBRARY_PATH ANY_NAME

这些环境变量被设置在终端进程中。运行该Set-UID程序。在终端输入程序的名字后,终端会建立一个子进程,并用该子进程去运行程序。请检查上一步骤中设置的环境变量是否在子进程的shell中。描述观察到的结果。

2.6 任务六:PATH环境变量和Set-UID程序

由于调用了shell程序,所以在set-UID程序中调用system()是非常危险的。这是因为shell程序的实际行为可能受到环境变量的影响,如PATH这些环境变量由恶意用户提供。

通过改变这些变量,恶意用户可以控制Set-UID程序的行为。在Bash中,您可以通过以下方式更改PATH环境变量(此示例将目录/home/seed添加到PATH环境变量的开头):

$ export PATH=/home/seed:$PATH

以下Set-UID程序应该执行/bin/ls命令。但是,程序员只能使用ls命令的相对路径,而不是绝对路径:

 int main()
{
system("ls");
return ;
}

编译上述程序,并将其所有者改为root,将其设置为Set-UID程序。你可以让这个Set-UID程序运行你的代码而不是/bin/ls吗?描述和解释你的观察。

任务七:LD_PRELOAD环境变量和Set-UID程序

在这个任务中,我们研究Set-UID程序如何处理环境变量。一些影响动态链接器的环境变量,包括LD_PRELOAD、LD_LIBRARY_PATH和其他LD_*。一个动态装载器/链接器是操作系统的一部分,用于下载并链接可执行文件运行过程中需要的公共库。

ld.so或者ld-linux.so是动态加载器/链接器。在那些影响他们行为的环境变量中,LD_LIBRARY_PATH和LD_PRELOAD是该实验涉及到的两个环境变量。在linux中,LD_LIBRARY_PATH是一个冒号分隔的目录集,首先需要在标准的目录集之间搜索库。LD_PRELOAD指定要在所有其他库之前加载的其他用户指定的共享库列表。在这个任务中,我们只研究LD_PRELOAD。

  • 步骤一:首先,我们通过一个正常的程序理解环境变量如何影响动态加载器/链接器的行为。请按照以下步骤执行:

  1.我们新建一个动态链接库。命名下面的代码为mulib.c,该程序基本上覆盖了libc中的sleep函数:

#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");
}

  2.用下列命令编译mylib.c:

% gcc -fPIC -g -c mylib.c
% -shared -o libmylib.so.1.0.1 mylib.o -lc

  3.设置LD_PRELOAD环境变量:

% export LD_PRELOAD=./libmylib.so.1.0.

  4.编译myprog程序,在链接库libmylib.so.1.0.1的相同目录下:

 /* myprog.c */
int main()
{
sleep();
return ;
}
  • 步骤二:在以下情况中运行myprog程序,观察发生了什么。

    1.以普通用户的身份运行myprog程序。

    2.以普通用户运行拥有root权限的myprog程序。

    3使myprog成为一个Set-UID user1程序,在user2用户(非root用户)中再次设置PD_PRELOAD环境变量,运行myprog程序。

  • 步骤三:观察以上三次程序的执行结果,理解导致他们不同的原因。环境变量起了作用。设计实验证明主要因素,并解释第二步中行为的不同。

任务八:使用system()和execve()调用外部程序

虽然system()和execve()都可以用于运行新程序,但是如果在特权程序(如Set-UID程序)中使用,则system()非常危险。我们已经看到PATH环境变量是如何影响system()的行为,因为该变量会影响shell的工作原理。execve()没有问题,因为它没有调用shell。调用shell会导致非常危险的后果,而这与环境变量无关。来看下面这种情况:鲍勃为一家审计机构工作,他需要调查一家公司是否有涉嫌欺诈。为了调查目的,鲍勃需要能够读取该公司Unix系统中的所有文件;另一方面,为了保护系统的完整性,鲍勃不能修改任何文件。为了实现这一目标,系统超级用户文斯写了一个特殊的设置root-UID程序(见下文),然后给出了对鲍勃的可执行权限。该程序要求鲍勃在命令行中键入文件名,然后运行/bin/cat显示了指定的文件。由于程序在root权限下运行,它可以显示鲍勃指定的任何文件。然而,由于程序没有写操作的权限,所以文斯非常确定鲍勃不能使用这个特殊的程序来修改任何文件。

#include <string.h>
#include <stdio.h>
#include <stdlib.h> int main(int argc, char *argv[])
{
char *v[];
char *command; if(argc < ) {
printf("Please type a file name.\n");
return ;
} v[] = "/bin/cat"; v[] = argv[]; v[] = NULL; command = malloc(strlen(v[]) + strlen(v[]) + );
sprintf(command, "%s %s", v[], v[]); // Use only one of the followings.
system(command);
// execve(v[0], v, NULL); return ;
}
  • 步骤一:编译上面的程序,赋予其root用户权限,并将其变为SET-UID程序。该程序将会使用system()来调用命令。如果你是鲍勃,你能否打破系统的完整性吗?例如,你可以删除不可写文件吗?
  • 步骤二:注释掉system(command)语句,并取消注释execve()语句;程序将使用execve()来调用命令。编译程序,并使其成为Set-UID程序。那么在步骤一中的攻击是否仍然有效?

任务九:权能泄露

遵循最低权限原则,如果不再需要这种特权,Set-UID程序通常会永久放弃其root权限。此外,有时程序需要将其控制权交给用户,在这种情况下,root权限必须被撤销。setuid()系统调用可以用来撤销权限。根据手册,setuid()设置调用进程的有效用户ID。如果调用程序的有效UID是root,真实的UID和保存的set-user-id也被设置“。因此,如果一个有有效UID的set-uid程序没有调用setuid(n),则该进程将成为正常进程,其所有的UID都设置为n。当撤销权限的时候,最常见的错误就是权能泄露。这个进程在获得一些特权的时候可能已经获得了一些特权。当特权降级时,如果程序没有清理这个功能,则它们仍然可以由非特权进程访问。换句话说,虽然进程的有效用户ID变为非特权,但是该进程仍具有特权,因为它具有特权能力。

编译以下程序,将其所有者更改为root,并将其设置为Set-UID程序。以普通用户身份运行程序,并描述您所观察到的内容。文件/etc/zzz是否被修改?

请解释你的观察过程。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> void main()
{ int fd; /* Assume that /etc/zzz is an important system file,
* and it is owned by root with permission 0644.
* Before running this program, you should creat
* the file /etc/zzz first. */
fd = open("/etc/zzz", O_RDWR | O_APPEND);
if (fd == -) {
printf("Cannot open /etc/zzz\n");
exit();
} /* Simulate the tasks conducted by the program */
sleep(); /* After the task, the root privileges are no longer needed,
it's time to relinquish the root privileges permanently. */
setuid(getuid()); /* getuid() returns the real uid */ if (fork()) { /* In the parent process */
close (fd);
exit();
} else { /* in the child process */
/* Now, assume that the child process is compromised, malicious
attackers have injected the following statements
into this process */ write (fd, "Malicious Data\n", );
close (fd);
}
}

SEED实验——Environment Variable and Set-UID Program实验描述与实验任务的更多相关文章

  1. SEED实验——Environment Variable and Set-UID Program实验报告

    任务一:操作环境变量 实验过程一: 用printenv或env打印出环境变量. 在终端输入命令,显示结果如下图所示: 经过实验发现,printenv和env均可输出当前系统的环境变量.不同的是prin ...

  2. JRE_HOME environment variable is not defined correctly This environment variableis needed to run this program

    已经安装了JDK1.7 和对应JRE 安装了tomcat8 都是解压版 并设置了JAVA_HOME.JRE_HOME 但Tomcat在启动过程中找不到 错误: the JRE_HOME environ ...

  3. 普通用户操作tomcat项目时报:Neither the JAVA_HOME nor the JRE_HOME environment variable is defined At least one of these environment variable is needed to run this program

    在使用普通用户更新tomcat项目适合出现这个信息,Neither the JAVA_HOME nor the JRE_HOME environment variable is defined At ...

  4. TOMCAT-报错The BASEDIR environment variable is not defined correctly

    <span style="font-size:18px;">The BASEDIR environment variable is not defined correc ...

  5. [转]Tomcat----Neither the JAVA_HOME nor the JRE_HOME environment variable is defined

    对于使用IDE开发的程序员来讲,并不是所有人都对自己用来吃饭的工具了如指掌.常在阴沟跑,哪能不翻船.为此我把自己使用Tomcat/Eclipse的一些经验教训整理了一下,会陆续的贴出来,也许会帮到和我 ...

  6. tomcat启动报错:Neither the JAVA_HOME nor the JRE_HOME environment variable is defined At least one of these environment variable

    linux 下 启动tomcat 报: Neither the JAVA_HOME nor the JRE_HOME environment variable is definedAt least o ...

  7. 【TOMCAT启动异常】The BASEDIR environment variable is not defined correctly

    <span style="font-size:18px;">The BASEDIR environment variable is not defined correc ...

  8. linux安装tomcat Neither the JAVA_HOME nor the JRE_HOME environment variable is defined

    这两天我们的开发机重启了好几次,发现每次重启后我的tomcat总是没有启动.检查java路径,配置正确,后来拿普通账号启动tomcat时报如下的错: Neither the JAVA_HOME nor ...

  9. [Tomcat]The JRE_HOME environment variable is not defined correctly

    在tomcat的bin目录下,双击startup.bat,闪一下,就没了,后来仔细看了一下黑屏闪的内容如下: the JRE_HOME environment variable is not defi ...

随机推荐

  1. java8 按对象属性值排序

    //按id从小到大 List<User> sortUser = list.stream().sorted((u1, u2) -> u1.getId().compareTo(u2.ge ...

  2. artDialog记录

    //在子页面加按钮的方式 var api = frameElement.api, W = api.opener; api.button({ id: 'valueOk', name: '确定', cal ...

  3. Leetcode#191. Number of 1 Bits(位1的个数)

    题目描述 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量). 示例 : 输入: 11 输出: 3 解释: 整数 11 的二进制表示为 000000 ...

  4. Subsequence(序列自动机模板题)

    题目链接:https://nanti.jisuanke.com/t/38232 题目大意:给你一个字符串,然后再给你m个字符串,然后问你在第一个字符串中不连续的子串能不能构成输入的子串. 具体思路:构 ...

  5. 分布式系列四: HTTP及HTTPS协议

    分布式系列四: HTTP及HTTPS协议 非常全面的一篇HTTP的文章: 关于HTTP协议,一篇就够了 还有一个帮助理解HTTPS的文章: 也许,这样理解HTTPS更容易 本文的一些描述摘自这篇文章 ...

  6. GMM与EM共舞

    GMM,即高斯混合模型(Gaussian Mixture Model),简单地讲,就是将多个高斯模型混合起来,作为一个新的模型,这样就可以综合运用多模型的表达能力.EM,指的是均值最大化算法(expe ...

  7. Mysql -- 数据类型(2)

    掌握char类型和varchar类型 掌握枚举类型和集合类型 字符类型 #官网:https://dev.mysql.com/doc/refman/5.7/en/char.html #注意:char和v ...

  8. 【原创】大叔问题定位分享(6)Dubbo monitor服务iowait高,负载高

    一 问题 Dubbo monitor所在服务器状态异常,iowait一直很高,load也一直很高,监控如下: iowait如图: load如图: 二 分析 通过iotop命令可以查看当前系统中磁盘io ...

  9. Java框架之spring框架的优点,为什么要学习spring框架

    为什么要学习Spring的框架a: 方便解耦,简化开发    Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理 b:AOP编程的支持      Spring提供面向切 ...

  10. Java的家庭记账本程序(K)

    日期:2019.3.10 博客期:043 星期日 呕吼~这里是编程菜鸟小Master,今天加油的把第二个模板套用了,更改了许多的设定,我想这一个程序的网页版也就到这里结束了,下面是一部分的展示图,想要 ...