SET-UID程式漏洞實驗

來源:互聯網
上載者:User

標籤:

 20125133 馬國祥

 SET-UID程式漏洞實驗一、實驗描述

Set-UID 是Unix系統中的一個重要的安全機制。當一個Set-UID程式啟動並執行時候,它被假設為具有擁有者的許可權。例如,如果程式的擁有者是root,那麼任何人運行這個程式時都會獲得程式擁有者的許可權。Set-UID允許我們做許多很有趣的事情,但是不幸的是,它也是很多壞事情的罪魁禍首。

因此本次實驗的目標有兩點:

1.欣賞好的方面,理解為什麼Set-UID是需要的,以及它是如何被執行的。

2.注意壞的方面,理解它潛在的安全性問題。

二、實驗內容

這是一個探索性的實驗,你的任務是在Linux環境中和Set-UID機制”玩遊戲“,你需要在Linux中完成接下來的實驗任務:

2.1 猜測為什麼“passwd”,“chsh”,“su”,和“sudo”命令需要Set-UID機制,如果它們沒有這些機制的話,會發生什麼,如果你不熟悉這些程式,你可以通話閱讀使用手冊來熟悉它們,如果你拷貝這些命令到自己的目錄下,這些程式就不會是Set-UID程式,運行這些拷貝的程式,觀察將會發生什麼。

從上面的可以看出:將passwd拷貝到/tmp/下,許可權發生了變化(在原目錄下suid位被設定),複件沒有了修改密碼的許可權。

對於“chsh”,“su”,和“sudo”命令,把這些程式拷貝到使用者目錄下,同樣不再具有root許可權。

2.2 在linux環境下運行Set-UID 程式,同時描述並且解釋你的觀察結果2.2.1 以root方式登入,拷貝/bin/zsh 到/tmp, 同時設定拷貝到tmp目錄下的zsh為set-uid root許可權,然後以普通使用者登入,運行/tmp/zsh。你會得到root許可權嗎?請描述你的結果。 2.2.2 拷貝/bin/bash到/tmp目錄,同時設定/tmp目錄下的bash為Set-UID root許可權,然後以普通使用者登入,運行/tmp/bash。你會得到root許可權嗎?請描述你的結果。

可見,同樣的操作,運行複製的zsh可以獲得root許可權,而bash不能。

2.3 從上面步驟可以看出,/bin/bash有某種內在的保護機制可以阻止Set-UID機制的濫用。為了能夠體驗這種內在的保護機制出現之前的情形,我們打算使用另外一種shell程式——/bin/zsh。在一些linux的發行版中(比如Redora和Ubuntu),/bin/sh實際上是/bin/bash的符號連結。為了使用zsh,我們需要把/bin/sh連結到/bin/zsh。

下面的指令將會把預設的shell指向zsh:

$sudo suPassword:#cd /bin#rm sh#ln -s zsh sh

2.4 PATH環境變數的設定

system(const char * cmd)系統調用函數被內嵌到一個程式中執行一個命令,system()調用/bin/sh來執行shell程式,然後shell程式去執行cmd命令。但是在一個Set-UID程式中system()函數調用shell是非常危險的,這是因為shell程式的行為可以被環境變數影響,比如PATH;而這些環境變數可以在使用者的控制當中。通過控制這些變數,用心險惡的使用者就可以控制Set-UID程式的行為。

下面的Set-UID程式被用來執行/bin/ls命令;然後程式員可以為ls命令使用相對路徑,而不是絕對路徑。

int main(){   system("ls");   return 0;}
2.4.1 你能夠設定這個Set-UID程式運行你自己的代碼而不是/bin/ls嗎?如果你能的話,你的代碼具有root許可權嗎?描述並解釋你的觀察。

可以具有root許可權,把/bin/sh拷貝到/tmp目錄下面重新命名為ls(先要確保/bin/目錄下的sh 符號連結到zsh,而不是bash),將環境變數PATH設定為目前的目錄/tmp,運行編譯的程式test。就可以獲得root許可權:  

2.4.2 修改/bin/sh使得其返回到/bin/bash,重複上面的攻擊,你仍然可以獲得root許可權嗎?描述並解釋你的觀察。

可見修改sh串連回bash,運行test程式不能使普通使用者獲得root許可權。

2.5 sytem()和execve()的不同

首先確保/bin/sh指向zsh

背景:Bob在為一家審計代理處工作,他正在調查一家公司是否存在詐騙行為。為了這個目的,他需要閱讀這家公司在Unix系統中的所有檔案;另一方面,為了保護系統的可靠性,他不能修改任何一個檔案。為了達到這個目的,Vince——系統的超級使用者為他寫了一個SET-ROOT-UID程式,並且給了Bob可以執行它的許可權。這個程式需要Bob在命令列中打出一個檔案名稱,然後運行/bin/cat命令顯示這個檔案。既然這個程式是以root許可權啟動並執行,它就可以顯示Bob想看的任何一個檔案。然而,既然這個程式沒有寫操作,Vince很確信Bob不能用這個程式修改任何檔案。

#include <string.h>#include <stdio.h>#include <stdlib.h>int main(int argc, char *argv[]){   char *v[3];   if(argc < 2)   {   printf("Please type a file name.\n");   return 1;   }   v[0] = "/bin/cat"; v[1] = argv[1]; v[2] = 0;  //Set q = 0 for Question a, and q = 1 for Question b   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 ;}
2.5.1 程式中有 q=0。程式會使用system()調用命令列。這個命令安全碼?如果你是Bob,你能對系統的完整性妥協嗎?你能重新移動一個對你沒有寫入權限的檔案嗎?

這個命令不安全,Bob可能會出於好奇或者個人利益驅使閱讀或者修改只有root使用者才可以啟動並執行一些檔案。比如中:file檔案只有root使用者有讀寫權限,但普通使用者通過運行該程式,閱讀並重新命名了file檔案:

2.5.2 如果令q=1;剛才的攻擊還會有效嗎?請描述並解釋你的觀察。

修改為q=1後,不會有效。前面步驟之所以有效,是因為system()函數調用/bin/sh,連結至zsh,具有root許可權執行了cat file檔案後,接著執行mv file file_new命令。

而當令q=1, execve()函數會把file; mv file file_new 看成是一個檔案名稱,系統會提示不存在這個檔案:

2.6 LD_PRELOAD環境變數

為了保證Set-UID程式在LD_PRELOAD環境的操縱下是安全的,動態連結器會忽略環境變數,但是在某些條件下是例外的,在下面的任務中,我們猜測這些特殊的條件到底是什麼。

1、讓我們建立一個動態連結程式庫。把下面的程式命名為mylib.c,放在/tmp目錄下。在函數庫libc中重載了sleep函數:

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

2、我們用下面的命令編譯上面的程式(注意區別l和1):

gcc -fPIC -g -c mylib.cgcc -shared -Wl,-soname,libmylib.so.1 -o libmylib.so.1.0.1 mylib.o –lc

3、把下面的程式命名為myprog.c,放在/tmp目錄下:

int main(){   sleep(1);   return 0;}

請在下面的條件下運行這些程式,並觀察結果。基於這些觀察告訴我們連結器什麼時候會忽略LD_PRELOAD環境變數,解釋原因。

2.6.1 把myprog編譯成一個普通使用者下的程式在普通使用者下運行

可見,它會使用LD_PRELOAD環境變數,重載sleep函數:

2.6.2 把myprog編譯成一個Set-UID root的程式在普通使用者下運行

在這種情況下,忽略LD_PRELOAD環境變數,不重載sleep函數,使用系統內建的sleep函數:

2.6.3 把myprog編譯成一個Set-UID root的程式在root下運行

在這種情況下,使用LD_PRELOAD環境變數,使用重載的sleep函數:

2.6.4在一個普通使用者下把myprog編譯成一個Set-UID 普通使用者的程式在另一個普通使用者下運行

在這種情況下,不會重載sleep函數:

由以上四種情況可見:只有使用者自己建立的程式自己去運行,才會使用LD_PRELOAD環境變數,重載sleep函數,否則的話忽略LD_PRELOAD環境變數,不會重載sleep函數。

2.7 消除和清理特權

為了更加安全,Set-UID程式通常會調用setuid()系統調用函數永久的清除它們的root許可權。然而有些時候,這樣做是遠遠不夠的。在root使用者下,在/tmp目錄建立一個空檔案zzz。在root使用者下將下面代碼命名為test.c,放在/tmp目錄下,編譯這個程式,給這個程式設定root許可權。在一個普通的使用者下,運行這個程式。描述你所觀察到的情況,/tmp/zzz這個檔案會被修改嗎?解釋你的觀察。

代碼:

#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>void main(){  int fd;  //Assume that /tmp/zzz is an important system file,  //and it is owned by root with permission 0644  fd = open("/tmp/zzz", O_RDWR | O_APPEND);  // 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, "shiyanlou!", 10);  close (fd);  }}

結果

檔案被修改了,原因在於設定uid前,zzz檔案就已經被開啟了。只要將語句setuid(getuid())移至調用open函數之前,就能避免這個問題。

三、練習

在實驗樓環境安步驟進行實驗,並

四、總結

  Set-UID 是Unix系統中的一個重要的安全機制。當一個Set-UID程式啟動並執行時候,它被假設為具有擁有者的許可權。例如,如果程式的擁有者是root,那麼任何人運行這個程式時都會獲得程式擁有者的許可權。 通過本次實驗,對Set_UID產生了較為初步的認識。同時,也對資訊安全方面的保障有了新的認識。這次實驗過程中遇到了很多問題,在同學的協助下一一克服困難完成了實驗。希望今後自己多多努力。

 

SET-UID程式漏洞實驗

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.