歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

UNIX文件的SUID/SGID

  一、 SUID/SGID概述  有時,沒有被授權的用戶需要完成某項任務。一個例子是passwd程序,它允許用戶改變口令,這就要求改變/etc/passwd文件的口令域。然而系統管理員決不允許普通用戶擁有直接改變這個文件的權利,因為這絕對不是一個好主意。  為了解決這個問題,SUID/SGID便應運而生。UNIX允許程序被授權,當程序被執行的時候,擁有超級用戶的權限,完成時又回到普通用戶的權限。這個主意很好,所以AT&T對它申請了專利。    二、 UNIX下的一些名詞簡介  1.文件權限。確定用戶讀取、修改或執行文件的權力。  r -- 讀訪問  w -- 寫訪問  x -- 執行許可  s -- SUID/SGID  t -- sticky位  2.進程。進程是程序運行一次的過程,以完成預定的任務,它不同於程序。每個進程都有一個唯一的進程ID。此外,每個進程還有一些其他標識符:實際用戶ID、實際組ID、有效用戶ID、有效組ID。超級用戶進程的實際用戶ID和有效用戶ID為0。  3.超級用戶root。超級用戶擁有系統的完全控制權。    三、 SUID/SGID的思路  SUID的程序在運行時,將有效用戶ID改變為該程序的所有者ID,使得進程在很大程度上擁有了該程序的所有者的特權。如果被設置為SUID root,那麼這個進程將擁有超級用戶的特權(當然,一些較新版本的UNIX系統加強了這一方面的安全檢測,一定程度上降低了安全隱患)。當進程結束時,又恢復為原來的狀態。    執行時的Real Uid可以通過函數setuid()改變    四、一個SUID程序  下面的程序是用來演示UNIX文件的SUID,取名為parent.c    #include 〈stdio.h〉  #include 〈stdlib.h〉  #include 〈unistd.h〉  #include 〈sys/types.h〉  int  main(int argc,char **argv)  {  int i;  char **argu;  uid_t uid;  uid=geteuid(); //獲取調用進程的有效用戶ID  if(argc<2){  fprintf(stderr,"usage: %s \n",argv[0]);  exit(0);  }  if(setuid(uid)<0){  fputs("setuid error.\n",stderr);  exit(1);  } //將調用進程的實際用戶ID設置為有效用戶ID  if((argu=(char**)malloc(argc*sizeof(char*)))==NULL){  fputs("malloc error.\n",stderr);  exit(1);  } //為execvp的參數指針數組分配內存空間  for(i=0;i     argu[argc-1]=(char *)0; //參數指針數組以空指針結尾  if(execvp(argv[1],argu)<0){  fputs("exec error.\n",stderr);  exit(1);  } //用execvp調用命令行參數指定的程序  exit(0);  }    該程序將一個SUID的進程轉變為一個超級用戶進程。將此程序編譯成可執行目標文件parent ,用另一個簡單的程序進行檢驗    int main(void){  printf("real uid=%d, effective uid=%d\n",getuid(),geteuid());  exit(0);  }    編譯為printuids。運行程序得到下列結果:    $ ./parent printuids //正常執行,無特權  real uid=506, effective uid=506  $ su root  PassWord:  # chown root parent //更改所有者  # chmod u+s parent //添加SUID  # exit  $ ./parent printuidsv   real uid=0, effective uid=0 //該進程轉變為超級用戶進程    某一進程一旦轉變為超級用戶進程,將擁有系統的完全控制權。比如,我們可以這樣執行演示程序:   $ ./parent useradd hacker  $ ./parent passwd hacker  故而,SUID的程序往往伴隨著一定的安全問題。在早期的UNIX環境中,SUID/SGID的程序調用system()函數就存在著安全性漏洞。    五、 再談SUID/SGID程序的安全問題  有時,一個SUID程序與一個系統程序(或庫函數)之間的交互作用會產生連程序的編制者也不知道的安全漏洞。一個典型的例子是/usr/lib/preserve程序。它被vi和ex編輯器使用,當用戶在寫出對文件的改變前被意外與系統中斷時,它可以自動制作一個正被編輯的文件的拷貝。這個保存的(preserve)程序將改變寫到在一個專門的目錄內的一個臨時文件上,然後利用/bin/mail程序發送給用戶一個"文件已經被存"的通知。  由於人們可能正在編輯一個私人的或一個機密的文件,被preserve程序(舊版)使用的那個目錄不能被一般用戶訪問。為了使preserve程序可以寫入那個目錄,以及使recover程序可以從那裡讀,這些程序被設置為SUID root。 這個preserve程序有三個特點值得注意:  1. 這個程序被設置為SUID root。  2. 該程序以root用戶的身份運行/bin/mail程序。  3. 該程序調用system()函數調用mail程序。  由於system()函數調用shell對命令字符串進行語法分析,而shell則使用IFS變量作為其輸入字段的分割符。早期的shell版本在被調用是時不將此變量恢復為普通字符集。如果先將IFS設置為"/",然後調用vi程序,繼而調用preserve程序,就有可能使usr/lib/preserve程序執行一個在當前目錄下的bin程序(/bin/mail被解析為帶有參數mail的bin程序)。  如果我們利用前面的演示程序編寫一個簡單的shell script文件命名為bin,它就有可能通過上面的安全漏洞被執行:    # shell script to make an SUID-root  shell  #  chown root parent  chmod 4755 parent    那麼它的後果將是……




Copyright © Linux教程網 All Rights Reserved