實際用戶ID,有效用戶ID和設置用戶IDlinux
看UNIX相關的書時常常能遇到這幾個概念,但一直沒有好好去理清這幾個概念,以至對這幾個概念一直只知其一;不知其二。今天好好區分了一下這幾個概念並總結以下。說白了這幾個UID引出都是爲了系統的權限管理。git
下面分別用RUID, EUID,SUID來表示實際用戶ID,有效用戶ID,設置用戶ID。另外用戶ID是個整型數,爲了說明方便真接使用了用戶名來表明不一樣的UID。先解釋一下這幾個ID的做用:shell
RUID, 用於在系統中標識一個用戶是誰,當用戶使用用戶名和密碼成功登陸後一個UNIX系統後就惟一肯定了他的RUID.編程
EUID, 用於系統決定用戶對系統資源的訪問權限,一般狀況下等於RUID。vim
SUID,用於對外權限的開放。跟RUID及EUID是用一個用戶綁定不一樣,它是跟文件而不是跟用戶綁定。安全
說明SUID的時候不少書都簡略的提了一下passwd這個程序,下面就拿這個例子來分析。咱們知道linux系統的密碼都存在了/etc/shadow這個文件裏。這個文件是如此的重要,在作任何修改以前最好先備份一下。查看/etc/shadow文件的屬性以下:網絡
[root@localhost ~]# ll /etc/shadowsocket
-r-------- 1 root root 1144 Jul 20 22:33 /etc/shadow編輯器
從上能夠看出/etc/shadow文件是一個屬於root用戶及root組的文件,而且只有EUID爲root的用戶具備讀的權限,其它全部EUID都沒有任何權限。當你在steve用戶(EUID此時也爲steve)的shell下試圖用vim打開這個文件時會提示權限不容許。至於連root用戶也只有讀的權限我猜是爲了避免鼓勵root用戶使用vim類的編輯器去直接修改它,而要採用passwd命令來修改這個文件。若是你非要直接修改它,那麼你可使用chmod命令修改成屬性爲root可寫,而後就能夠修改了。函數
用過UNIX系統的人都知道,任何一個用戶均可以使用passwd這個命令來得新設定本身的密碼。但從上面已經知道,非root用記是沒法讀這個文件的,那麼普通用戶是如何作到修改這個文件的呢?咱們知道passwd這個命令實際執行的程序是/usr/bin/passwd, 查看這個文件屬性以下:
-r-s--x--x 1 root root 21944 Feb 12 2006 /usr/bin/passwd;
對應文件存取標誌的s位就是一般說的SUID位,另外能夠看到全部用戶都有執行的這個程序權力。當steve用戶執行passwd命令的時候。Shell會fork出一個子進程,此時進程的EUID仍是steve,而後exec程序/usr/bin/passwd。exec會根據/usr/bin/passwd的SUID位會把進程的EUID設成root, 此時這個進程都得到了root權限, 獲得了讀寫/etc/shadow文件的權限, 從而steve用戶可完成密碼的修改。 exec退出後會恢復steve用戶的EUID爲steve.這樣就不會使steve用戶一直擁有root權限。
咱們能夠測試一下,用root用戶把/usr/bin/passwd的SUID位去掉,以下:
[root@localhost ~]# ll /usr/bin/passwd
-r-s--x--x 1 root root 21944 Feb 12 2006 /usr/bin/passwd
[root@localhost ~]# chmod u-s /usr/bin/passwd
[root@localhost ~]# ll /usr/bin/passwd
-r-x--x--x 1 root root 21944 Feb 12 2006 /usr/bin/passwd
而後steve用戶用命令passwd去更新密碼會提示以下錯誤:
[steve@localhost ~]$ passwd
Changing password for user steve.
Changing password for steve
(current) UNIX password:
passwd: Authentication token manipulation error
[steve@localhost ~]$
這就是由於/usr/bin/passwd程序的SUID去掉後,steve用戶雖然能夠執行該程序,但由於/usr/bin/passwd/的SUID沒有設置,這樣exec後進程的EUID仍爲steve的緣由。
也許有人會發現root用戶卻仍可使用該用命修改密碼,那是由於root用戶自己的EUID時就是root (也有可能只要發現是RUID是root就不檢查EUID了,直接可讀寫,root就是老大嘛), 能夠讀取密碼文件。
另外也許有人會發現普通的文件文件普通的文本文件會也能夠設置SUID位, 但這是沒有意義的,由於文件文件沒有地方執行seteuid()的系統調用來改變當用用戶的EUID。
最後,這裏的對用戶ID的規則一樣也適用了組ID。
1、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和-:
p表示命名管道文件
d表示目錄文件
l表示符號鏈接文件
-表示普通文件
s表示socket文件
c表示字符設備文件
b表示塊設備文件
第8-6位、5-3位、2-0位分別表示文件全部者的權限,同組用戶的權限,其餘用戶的權限,其形式爲rwx:
r表示可讀,能夠讀出文件的內容
w表示可寫,能夠修改文件的內容
x表示可執行,可運行這個程序
沒有權限的位置用-表示
例子:
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位,會分別表如今全部者或同組用戶的權限的可執行位上。例如:
一、-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位。
11 10 9 8 7 6 5 4 3 2 1 0
上面的-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位權限表示法也很簡單。
2、SUID和SGID的詳細解析
因爲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位,那麼若是任何一個用戶對這個目錄有寫權限的話,他在這個目錄所創建的文件的組都會自動轉爲這個目錄的屬主所在的組,而文件全部者不變,仍是屬於創建這個文件的用戶。
3、關於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是該程序的全部者。舉個例子:
[root@sgrid5 bin]# 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位來解決。
[root@sgrid5 bin]# ls -l /bin/ping
-rwsr-sr-x 1 root root 28628 Jan 25 2003 /bin/ping
咱們能夠測試一下,若是去掉ping的SUID位,再用普通用戶去運行命令,看會怎麼樣。
[root@sgrid5 bin]#chmod u-s /bin/ping
[root@sgrid5 bin]# ls -l ping
-rwxr-xr-x 1 root root 28628 Jan 25 2003 ping
[root@sgrid5 bin]#su test
[test@sgrid5 bin]$ ping byhh.net
ping: icmp open socket: Operation not permitted
SUID雖然很好了解決了一些問題,可是同時也會帶來一些安全隱患。
由於設置了 SUID 位的程序若是被攻擊(經過緩衝區溢出等方面),那麼hacker就能夠拿到root權限。
所以在安全方面特別要注意那些設置了SUID的程序。
經過如下的命令能夠找到系統上全部的設置了suid的文件:
[root@sgrid5 /]# find / -perm -04000 -type f -ls
對於這裏爲何是4000,你們能夠看一下前面的st_mode的各bit的意義就明白了。
在這些設置了suid的程序裏,若是用不上的,就最好取消該程序的suid位。