第一部分:实验描述

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


第二部分:实验任务

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. mysql MHA高可用测试

    [环境介绍] 系统环境:Red Hat Enterprise Linux 7 + 5.7.18 + MHA version 0.57 [测试步骤:自动切换] 当前数据库状态: 系统 IP 主机名 备注 ...

  2. SSH框架之hibernate《四》

    hibernate第四天     一.JPA相关概念         1.1JPA概述             全称是:Java Persistence API.是sun公司推出的一套基于ORM的规范 ...

  3. mui-选项卡+scroll滚动

    详细操作见代码: <!doctype html> <html> <head> <meta charset="UTF-8"> < ...

  4. 本地图片上传与H5适配知识

    最近用到本地图片上传作为API的参数,在网上看了许多,记录一下,以后可能用的着(仅自己记录用,看不清请绕路) function getObjectURL(file) { var url = null ...

  5. C++ 变长模板参数

    转载自: http://www.cnblogs.com/liyiwen/archive/2013/04/13/3018608.html C++11 语言核心的改进中,最为关注的有 rvalue ref ...

  6. html-webpack-template, 一个更好的html web service插件

    源代码名称:html-webpack-template 源代码网址:http://www.github.com/jaketrent/html-webpack-template html-webpack ...

  7. Hadoop cloudera版和Apache(原生态)的区别

    ---------------------------------------------------------------------------------------------------- ...

  8. 《剑指offer》整数中1出现的次数

    本题来自<剑指offer> 反转链表 题目: 思路: C++ Code: Python Code: 总结:

  9. Vulnerability Scanning

    1.Vulnerability scanning with Nmap Scripting Engine the Nmap Script Engine provide a alrge number of ...

  10. Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...