软件安全-环境变量攻防

Environment Variable and Set-UID Program Lab

Manipulating environment variables

打印环境变量:
pirntenv env
设置/取消设置环境变量:
export unset

Inheriting environment variables from parents

如果进程需要启动另一个程序的可执行文件,它先fork创建一个自身的副本,
然后由该副本调用exec系统调用,用其他程序覆盖自身。当一个进程调用fork时,它被认为是父进程,新创建的进程称作子进程。fork操作会为子进程创建一个单独的地址空间,子进程拥有父进程所有内存段的副本。

include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

extern char** environ;
void printenv()
{
    int i = 0;
    while(environ[i] != NULL)
        printf("%s\n",environ[i++]);
}
void main()
{
    pid_t childPid;
    switch(childPid = fork())
    {
        case 0:
        printenv();
        exit(0);
    default:
        //printenv();
        exit(0);
}
}

先后取消父进程和子进程的注释,将打印的文本信息保存,
然后对比父进程和子进程的环境变量,结果完全一样。

Environment varibales and execve()

int execve(const char* filename,char* const argv[],char* const envp[]);
execve()用来执行参数filename字符串所代表的文件路径,

参数2是利用指针数组来传递给执行文件,并且需要以空指针结束,

参数3是传递给执行文件的新环境变量数组。

成功不会返回,失败返回-1。

include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
extern char** environ;

int main()
{
    char* argv[2];
    argv[0] = "/usr/bin/env";
    argv[1] = NULL;
    execve("/usr/bin/env",argv,NULL);
    //execve("/usr/bin/env",argv,environ);
    return 0;
}

当execve()函数的参数3:新的环境变量数组,设置为NULL的时候,打印信息为空。
当设置为environ时,打印出环境变量信息。

Environment variables and system()

int system(const char* string);
system()会调用fork()产生子进程,由子进程来调用/bin/sh来执行参数string字符串所代表的命令,
此命令执行完成后随即返回原调用的进程。
如果执行成功则返回子shell的终止状态。
如果fork()失败,返回-1。
如果exec()失败,表示不能执行shell,返回值相当于shell执行了exit。

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

编译运行,结果打印环境变量。

Environment variables and Set-UID Programs

#include <stdio.h>
#include <stdlib.h>
extern char **environ;
void main()
{
    int i = 0;
    while (environ[i] != NULL)
        printf("%s\n", environ[i++]);
}

root用户编译,设置Set-UID。
普通用户下,使用export设置环境变量:

PATH
LD_LIBRARY_PATH
运行上面的程序,发现环境变量发生变化
PATH变成刚刚设置的
LD_LIBRARY_PATH没有找到
The PATH Environment variable and Set-UID Programs

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

将/bin/sh复制到程序当前目录,命令为ls。

cp /bin/sh ~/ls

设置环境变量PATH=~:$PATH。

root用户编译上面的程序,设置Set-UID。

普通用户运行,结果显示获取到root权限。

The LD_PRELOAD environment variable and Set-UID Programs

#include <stdio.h>
void sleep(int s)
{
    printf("i am not sleeping \n");
}

gcc -fPIC -g -c mylib.c
gcc -shared -o libmylib.so.1.0.1 mylib.o -lc
export LD_PRELOAD=./libmylib.so.1.0.1

/* myprog.c */
int main()
{
    sleep(1);
    return 0;
}

myprog普通程序,普通用户运行
//输出 i am not sleeping
myprog Set-UID root程序,普通用户运行
//输出空
myprog Set-UID root程序,设置root用户环境变量LD_PRELOAD,root用户运行
//输出 i am not sleeping
myprog普通用户1程序,设置普通用户2环境变量LD_PRELOAD,普通用户2运行
//输出空
只有用户自己创建的程序自己去运行,才会使用LD_PRELOAD环境变量,
否则忽略LD_PRELOAD环境变量。

Invoking external programs using system() versus execve()

/*  bob.c */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    char *v[3];
    char *command;
    if(argc < 2) {
        printf("Please type a file name.\n");
    return 1;
}
    v[0] = "/bin/cat"; v[1] = argv[1]; v[2] = NULL;
    command = malloc(strlen(v[0]) + strlen(v[1]) + 2);
    sprintf(command, "%s %s", v[0], v[1]);
    // Use only one of the followings.
    system(command);
    // execve(v[0], v, NULL);
    return 0 ;
}

system(command);
bob可以实现删除指定文件。
root用户,编译上述程序,设置Set-UID。
攻击者bob可以通过:
./bob “111.txt;rm 111.txt -rf”
实现将没有写权限的的文件111.txt删除。
因为system()调用了shell,由于本程序设置了Set-UID,
将会以root身份去执行字符串。
execve(v[0],v,NULL);
无法删除指定文件。
./bob “111.txt;rm 111.txt -rf”
execve()将”111.txt;rm 111.txt -rf”当作文件名,
自然显示找不到文件。
Capability Leaking

#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 == -1) {
        printf("Cannot open /etc/zzz\n");
        exit(0);
    }
    /* Simulate the tasks conducted by the program */
    sleep(1);
    /* 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(0);
    } 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", 15);
    close (fd);
    }
}

root用户编译,设置Set-UID,普通用户运行。

结果成功写入:“Malicious Data\n”

由于文件fd是root权限打开的,导致降权不彻底。

需要遵循最小权限原则,用完就释放权限。


Set-UID Program Vulnerability Lab
实验目的:
理解掌握为什么需要Set-UID程序
理解掌握潜在的安全隐患

问题1

当我们在普通用户下输入su时,会发生什么?
需要我们输入密码,进入root账户
当我们把su程序复制到另一个目录下的时候,运行该目录下的su passwd会发生什么?
输入密码无效,因为复制的程序丢失了Set-UID
问题2

root用户登录,复制/bin/zsh到/tmp,设置s位,切换到普通用户下,运行/tmp/zsh,你会获得root权限吗?
进入zsh,普通用户可以获得root权限
复制/bin/bash试一试?
进入普通bash,bash程序中有Set-UID保护机制
问题3

更改/bin/sh符号链接指向/bin/zsh?

$ su
Password: (enter root password)cd /bin
rm sh
ln -s zsh sh

问题4

PATH环境变量

在问题3的基础上
普通用户下设置环境PATH=/tmp:$PATH
root用户将zsh复制到/tmp,设置s位,重命名为ls

#include <unistd.h>
#include <stdlib.h>
int main()
{
    system("ls");
    return 0;
}

普通用户编译运行上面的程序,即可获得root shell。

如果sh软链接指向的是bash,结果会怎样?
只能获得普通shell
问题5

system()和execve()
背景:BOB是一个代码审计员,他需要看一家公司的全部文件,但是不能修改任何文件。
为此,系统管理员写了一个Set-UID的小程序,并且给了BOB可执行权限。
这个小程序允许BOB输入一个文件名,让运行/bin/cat查看文件内容。
小程序运行期间,具有root权限,因此可以查看任何文件内容。
又因为这个小程序没有写权限,因为BOB不能修改任何文件。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc,char* argv[])
{
    char* v[3];
    if(argc <2)
    {
        pirntf("Please type a file name.\n");
        return 1;
    }
}
v[0] = "/bin/cat";
v[1] = argv[1];
v[2] = 0;
int q = 0;
if(q ==0)
{
    char* command = malloc(strlen(v[0])+strlen(v[1])+2);
    sprintf(command,"%s %s",v[0],v[1]);
    system(command);
}
else
{
    execve(v[0],v,0);
}
return 0;

q = 0 如果你是BOB,你可以删除文件吗?
能。程序使用system()函数,调用/bin/sh程序,修改环境变量。
q = 1 如果你是BOB,你可以删除文件吗?
不能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容