歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> UNIX文件的SUID/SGID

UNIX文件的SUID/SGID

日期:2017/2/28 11:28:51   编辑:關於Unix


  一、 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
  
  
QUOTE:#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