因爲用戶在UNIX下常常會遇到SUID、SGID的概念,並且SUID和SGID涉及到系統安全,因此用戶也比較關心這個問題。關於SUID、SGID的問題也常常有人提問,但回答的人通常答得不夠詳細,加上曾經回答過兩個網友的問題,還查了一些資料,決定整理成本文,以供你們參考。限於本人的水平問題,文章中若是有不當之處,請廣大網友指正。git
一. UNIX下關於文件權限的表示方法和解析
SUID是Set User ID, SGID是Set Group ID的意思。 UNIX下能夠用‘ls -l’命令來看到文件的權限。用ls命令所獲得的表示法的格式是相似這樣的:-rwxr-xr-x。下面解析一下格式所表示的意思。這種表示方法一共有十位:編程
9 8 7 6 5 4 3 2 1 0 - r w x r - x r - x
第9位表示文件類型,能夠爲p、d、l、s、c、b和-:安全
第8-6位、5-3位、2-0位分別表示文件全部者的權限,同組用戶的權限,其餘用戶的權限,其形式爲rwx:bash
# 示例 $ls -l myfile -rwxr-x--- 1 foo staff 7734 Apr 05 17:07 myfile
-表示文件myfile是普通文件,文件的全部者是foo用戶,而foo用戶屬於staff組,文件只有1個硬鏈接,長度是7734個字節,最後修改時間4月5日17:07。全部者foo對文件有讀寫執行權限,staff組的成員對文件有讀和執行權限,其餘的用戶對這個文件沒有權限。網絡
若是一個文件被設置了SUID或SGID位,會分別表如今全部者或同組用戶的權限的可執行位上。例如:socket
-rwsr-xr-x 表示SUID和全部者權限中可執行位被設置 -rwSr--r-- 表示SUID被設置,但全部者權限中可執行位沒有被設置 -rwxr-sr-x 表示SGID和同組用戶權限中可執行位被設置 -rw-r-Sr-- 表示SGID被設置,但同組用戶權限中可執行位沒有被設置
其實在UNIX的實現中,文件權限用12個二進制位表示,若是該位置上的值是1,表示有相應的權限:函數
11 10 9 8 7 6 5 4 3 2 1 0 S G T r w x r w x r w x
第11位爲SUID位,第10位爲SGID位,第9位爲sticky位,第8-0位對應於上面的三組rwx位。測試
-rwsr-xr-x的值爲: 1 0 0 1 1 1 1 0 1 1 0 1 -rw-r-Sr--的值爲: 0 1 0 1 1 0 1 0 0 1 0 0
# 給文件加SUID和SUID的命令以下: chmod u+s filename 設置SUID位 chmod u-s filename 去掉SUID設置 chmod g+s filename 設置SGID位 chmod g-s filename 去掉SGID設置
另一種方法是chmod命令用八進制表示方法的設置。若是明白了前面的12位權限表示法也很簡單。ui
二. SUID和SGID的詳細解析.net
因爲SUID和SGID是在執行程序(程序的可執行位被設置)時起做用,而可執行位只對普通文件和目錄文件有意義,因此設置其餘種類文件的SUID和SGID位是沒有多大意義的。 首先講普通文件的SUID和SGID的做用。
例子: 若是普通文件myfile是屬於foo用戶的,是可執行的,如今沒設SUID位,ls命令顯示以下:
-rwxr-xr-x 1 foo staff 7734 Apr 05 17:07
myfile任何用戶均可以執行這個程序。UNIX的內核是根據什麼來肯定一個進程對資源的訪問權限的呢?
答:是這個進程的運行用戶的(有效)ID,包括User ID和Group ID。 用戶能夠用id命令來查到本身的或其餘用戶的User ID和Group ID。
除了通常的User ID和Group ID外,還有兩個稱之爲effective 的ID,就是有效ID,上面的四個ID表示爲:uid,gid,euid,egid。內核主要是根據euid和egid來肯定進程對資源的訪問權限。
一個進程若是沒有SUID或SGID位,則euid=uid, egid=gid,分別是運行這個程序的用戶的uid和gid。
例如kevin用戶的uid和gid分別爲204和202,foo用戶的uid和gid爲200,201,kevin運行myfile程序造成的進程的euid=uid=204,egid=gid=202,內核根據這些值來判斷進程對資源訪問的限制,其實就是kevin用戶對資源訪問的權限,和foo不要緊。
若是一個程序設置了SUID,則euid和egid變成被運行的程序的全部者的uid和gid,例如kevin用戶運行myfile,euid=200,egid=201,uid=204,gid=202,則這個進程具備它的屬主foo的資源訪問權限。
SUID的做用就是這樣:讓原本沒有相應權限的用戶運行這個程序時,能夠訪問他沒有權限訪問的資源。passwd就是一個很鮮明的例子。
SUID的優先級比SGID高,當一個可執行程序設置了SUID,則SGID會自動變成相應的egid。
下面討論一個例子:
UNIX系統有一個/dev/kmem的設備文件,是一個字符設備文件,裏面存儲了核心程序要訪問的數據,包括用戶的口令。因此這個文件不能給通常的用戶讀寫,權限設爲:
cr--r----- 1 root system 2, 1 May 25 1998 kmem
但ps等程序要讀這個文件,而ps的權限設置以下:
-r-xr-sr-x 1 bin system 59346 Apr 05 1998 ps
這是一個設置了SGID的程序,而ps的用戶是bin,不是root,因此不能設置SUID來訪問kmem,但你們注意了,bin和root都屬於system組,並且ps設置了SGID,通常用戶執行ps,就會得到system組用戶的權限,而文件kmem的同組用戶的權限是可讀,因此通常用戶執行ps就沒問題了。但有些人說,爲何不把ps程序設置爲root用戶的程序,而後設置SUID位,不也行嗎?這的確能夠解決問題,但實際中爲何不這樣作呢?由於SGID的風險比SUID小得多,因此出於系統安全的考慮,應該儘可能用SGID代替SUID的程序,若是可能的話。下面來講明一下SGID對目錄的影響。SUID對目錄沒有影響。若是一個目錄設置了SGID位,那麼若是任何一個用戶對這個目錄有寫權限的話,他在這個目錄所創建的文件的組都會自動轉爲這個目錄的屬主所在的組,而文件全部者不變,仍是屬於創建這個文件的用戶。
三. 關於SUID和SGID的編程
和SUID和SGID編程比較密切相關的有如下的頭文件和函數:
#include #include uid_t getuid(void); uid_t geteuid(void); gid_t getgid (void); gid_t getegid (void); int setuid (uid_t UID); int setruid (uid_t RUID); int seteuid (uid_t EUID); int setreuid (uid_t RUID,uid_t EUID); int setgid (gid_t GID); int setrgid (gid_t RGID); int setegid (git_t EGID); int setregid (gid_t RGID, gid_t EGID);
具體這些函數的說明在這裏就不詳細列出來了,要用到的能夠用man查。
SUID/SGID :
假如你有文件a.txt
$ls -l a.txt -rwxrwxrwx $ chmod 4777 a.txt -rwsrwxrwx #注意s位置 $ chmod 2777 a.txt -rwxrwsrwx #注意s位置 $ chmod 7777 a.txt -rwsrwxswt #出現了t,t的做用在內存中儘可能保存a.txt,節省系統再加載的時間.
如今再看前面設置 SUID/SGID做用:
$ cd /sbin # ./lsusb ... $ su aaa(普通用戶) $./lsusb ... # 是否是如今顯示出錯? $ su $ chmod 4755 lsusb $ su aaa $ ./lsusb
如今明白了嗎?原本是隻有root用戶才能執行的命令,加了SUID後,普通用戶就能夠像root同樣的用,權限提高了。上面是對於文件來講的,對於目錄也差很少!
目錄的S屬性使得在該目錄下建立的任何文件及子目錄屬於該目錄所擁有的組,目錄的T屬性使得該目錄的全部者及root才能刪除該目錄。還有對於s與S,設置SUID/SGID須要有運行權限,不然用ls -l後就會看到S,證實你所設置的SUID/SGID沒有起做用。
why we need suid,how do we use suid?
r -- 讀訪問 w -- 寫訪問 x -- 執行許可 s -- SUID/SGID t -- sticky位
那麼 suid/sgid是作什麼的? 爲何會有suid位呢?
要想明白這個,先讓咱們看個問題:若是讓每一個用戶更改本身的密碼?
用戶修改密碼,是經過運行命令passwd來實現的。最終必需要修改/etc/passwd文件,而passwd的文件的屬性是:
$ ls -l /etc/passwd -rw-r--r-- 1 root root 2520 Jul 12 18:25 passwd
咱們能夠看到passwd文件只有對於root用戶是可寫的,而對於全部的他用戶來講都是沒有寫權限的。那麼一個普通的用戶如何可以經過運行passwd命令修改這個passwd文件呢?
爲了解決這個問題,SUID/SGID便應運而生。並且AT&T對它申請了專利。 呵呵。
SUID和SGID是如何解決這個問題呢?
首先,咱們要知道一點:進程在運行的時候,有一些屬性,其中包括 實際用戶ID,實際組ID,有效用戶ID,有效組ID等。 實際用戶ID和實際組ID標識咱們是誰,誰在運行這個程序,通常這2個字段在登錄時決定,在一個登錄會話期間, 這些值基本上不改變。 而有效用戶ID和有效組ID則決定了進程在運行時的權限。內核在決定進程是否有文件存取權限時,是採用了進程的有效用戶ID來進行判斷的。
知道了這點,咱們來看看SUID的解決途徑:
當一個程序設置了爲SUID位時,內核就知道了運行這個程序的時候,應該認爲是文件的全部者在運行這個程序。即該程序運行的時候,有效用戶ID是該程序的全部者。舉個例子:
$ ls -l passwd -r-s--s--x 1 root root 16336 Feb 14 2003 passwd
雖然你以test登錄系統,可是當你輸入passwd命令來更改密碼的時候,因爲passwd設置了SUID位,所以雖然進程的實際用戶ID是test對應的ID,可是進程的有效用戶ID則是passwd文件的全部者root的ID,所以能夠修改/etc/passwd文件。
讓咱們看另一個例子。
ping命令應用普遍,能夠測試網絡是否鏈接正常。ping在運行中是採用了ICMP協議,須要發送ICMP報文。可是隻有root用戶才能創建ICMP報文,如何解決這個問題呢?一樣,也是經過SUID位來解決。
$ ls -l /bin/ping -rwsr-sr-x 1 root root 28628 Jan 25 2003 /bin/ping
咱們能夠測試一下,若是去掉ping的SUID位,再用普通用戶去運行命令,看會怎麼樣。
$ chmod u-s /bin/ping $ ls -l ping -rwxr-xr-x 1 root root 28628 Jan 25 2003 ping $ su test $ ping byhh.net ping: icmp open socket: Operation not permitted
SUID雖然很好了解決了一些問題,可是同時也會帶來一些安全隱患。由於設置了 SUID 位的程序若是被攻擊(經過緩衝區溢出等方面),那麼hacker就能夠拿到root權限。 所以在安全方面特別要注意那些設置了SUID的程序。
經過如下的命令能夠找到系統上全部的設置了suid的文件:
$ find / -perm -04000 -type f -ls
對於這裏爲何是4000,你們能夠看一下前面的st_mode的各bit的意義就明白了。 在這些設置了suid的程序裏,若是用不上的,就最好取消該程序的suid位。