http://www.php100.com/html/webkaifa/Linux/2010/0812/6392.html
1、setuid和setgid的解說
setuid和setgid位是讓普通用戶可以以root用戶的角色運行只有root帳號才能運行的程序或命令。比如我們用普通用戶運行passwd命令來更改自己的口令,實際上最終更改的是/etc/passwd文件,我們知道/etc/passwd文件是用戶管理的配置文件,只有root權限的用戶才能更改:
[root@localhost ~]# ls -l /etc/passwd
-rw-r--r-- 1 root root 2379 04-21 13:18 /etc/passwd
作為普通用戶,如果修改自己的口令通過修改/etc/passwd肯定是不可完成的任務,是不是可以通過一個命令來修改呢?答案是肯定的,作為普通用戶可以通過passwd 來修改自己的口令,這歸功於passwd命令的權限。我們來看一下:
[root@localhost ~]# ls -l /usr/bin/passwd
-r-s--x--x 1 root root 21944 02-12 16:15 /usr/bin/passwd
因為/usr/bin/passwd 文件已經設置了setuid 權限位(也就是r-s--x--x中的s),所以普通用戶能臨時變成root,間接的修改/etc/passwd,以修改自己口令的權限。
我們在Linux 系統中的超級權限的控制中有提到過我們知道Linux的用戶管理是極為嚴格的,不同的用戶擁有不同的權限,為了完成只有root用戶才能完成的工作,我們必須為普通用戶提升權 限,最常用的方法就是su或sudo,雖然setuid 和setgid也是讓普通用戶超越自身擁有的普通權限達到root權限的方法,但我不推薦大家使用,因為它能為系統帶來隱患!!
注意:setuid和setgid會面臨風險,所以盡可能的少用,了解了解既可~~~
2、setuid和setgid的實例應用
我們想讓一個普通用戶beinan擁有root用戶擁有超級rm刪除權限,我們除了用su或sudo 臨時切換到 root身份操作以外,還能怎么做呢???
[root@localhost ~]#cd /home 注:進入/home目錄
[root@localhost home]# touch beinantest.txt 注:創建一個文件;
[root@localhost home]# ls -l beinantest.txt 注:查看文件屬性;
-rw-r--r-- 1 root root 0 04-24 18:03 beinantest.txt 注:文件的屬性;
[root@localhost home]# su beinan 注:切換到普通用戶 beinan
[beinan@localhost home]$ rm -rf beinantest.txt 注:以普通用戶身份來刪除beinantest.txt文件;
rm: 無法刪除 beinantest.txt: 權限不夠
那我們怎么才能讓beinan 這個普通用戶也擁有root超級的rm 刪除功力呢?
[root@localhost ~]# ls -l /bin/rm
-rwxr-xr-x 1 root root 93876 02-11 14:43 /bin/rm
[root@localhost ~]# chmod 4755 /bin/rm 注:設置rm的權限為4755 , 就把setuid 位設置好了
[root@localhost ~]# ls -l /bin/rm
-rwsr-xr-x 1 root root 43980 02-11 14:43 /bin/rm
[root@localhost ~]# cd /home/
[root@localhost home]# su beinan 注:切換到beinan用戶身份;
[root@localhost home]$ ls -l beinantest.txt 注:查看文件屬性;
-rw-r--r-- 1 root root 0 04-24 18:03 beinantest.txt 注:文件的屬性;
[beinan@localhost home]$ rm -rf beinantest.txt 注:刪除beinantest.txt文件;
我們只是設置了rm的setuid位,讓普通用戶在rm指令上有超級root的刪除超級權力
通過這個例子,我們應該能明白setuid和setgid位的應用了,如同前面所說,讓普通用戶超越本身的能力,讓普通用戶能執行只有root才能 執行的命令在這一點,我們要和su和sudo 區分開來請參見su和sudo的文檔:Linux 系統中的超級權限的控制
3、setuid和setgid的設置方法
第一種方法:八進制方法:
setuid位是的設置用八進制的4000,setgid占用的是八進制的2000 ;比如我們前面所說的 chmod 4755 /bin/rm 就是設置的setuid位;
至於setuid的設置方法,只是在我們通過chmod設置文件或目錄權限位的八進制方法的前面多加一個數字,也就是4比如:
[root@localhost ~]# chmod 4755 /bin/rm 注:設置rm的權限為4755 , 就把setuid 位設置好了
作為setgid 位占用的是八進制的2000位,我們下面舉個例子;
[root@localhost ~]# cd /home/
[root@localhost home]# mkdir slackdir
[root@localhost home]# ls -ld slackdir/
drwxr-xr-x 2 root root 4096 04-24 18:25 slackdir/
[root@localhost home]# chmod 2755 slackdir/
[root@localhost home]# ls -ld slackdir/
drwxr-sr-x 2 root root 4096 04-24 18:25 slackdir/
我們看到 slackdir這個目錄,經過改變權限后的,目錄所歸屬用戶組的那三個權限位是 r-s 如果我們見到的是小寫的s,表明文件所歸屬的用戶組位有執行權限x因為我們用了2755 ,意思是說文件屬主擁有可讀可寫可執行權限,所歸屬的用戶組擁有可讀可執行權限,並且設置了setuid,所以這時本來文件所歸屬的用戶組擁有r-x,現 在加了setgid位,就把其中的x換成了s如果文件所歸屬的用戶組沒有執行權限,這個權限應該是S同理setuid位的中的大寫的S和小寫的s,也 是這個原理見下面的例子;
[root@localhost home]# chmod 2740 slackdir/
[root@localhost home]# ls -ld slackdir/
drwxr-S--- 2 root root 4096 04-24 18:25 slackdir/
這個例子是因為目錄slackdir所歸屬的組沒有執行權限,這時本來在執行權限位上顯示-,由於有了setuid,所以顯示為S
如果我們為一個文件的權限擁有 屬主可讀可寫可執行所歸的組擁有可讀可執行,其它用戶可讀可執行,並且同時設置setuid和setgid位,我們應該怎么運行命令呢?
[root@localhost ~]# touch gooddoc.txt
[root@localhost ~]# ls -l gooddoc.txt
-rw-r--r-- 1 root root 0 04-24 18:47 gooddoc.txt
[root@localhost ~]# chmod 6755 gooddoc.txt
[root@localhost ~]# ls -l gooddoc.txt
-rwsr-sr-x 1 root root 0 04-24 18:47 gooddoc.txt
所以,同時設置setuid和setgid,就是把setuid和setgid兩個八進位的值相加 (4000 2000=6000),然后加上文件或目錄的權限位的三位數值(上面的例子是755),然后通過chmod 運行就行了所以上面例子中用了6755
第二種方法:通過助記語法;
還是延用chmod的助記語法,通過u+s 或u-s 來增減setuid位,同理,我們可以通過g+s 或g-s 來setgid位;
[root@localhost ~]# touch mydoc.txt 注:創建一個文件;
[root@localhost ~]# ls -l mydoc.txt
-rw-r--r-- 1 root root 0 04-24 19:00 mydoc.txt
[root@localhost ~]# chmod u+s mydoc.txt
[root@localhost ~]# ls -l mydoc.txt
-rwSr--r-- 1 root root 0 04-24 19:00 mydoc.txt
我們也可以用file命令來查看setuid和setgid位,當然也能用file來查看文件的類型;
比如:
[root@localhost ~]# file /usr/bin/passwd
/usr/bin/passwd: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xc101d30ff4513f2dbad17fcc483dcda4a38e1df0, stripped
http://blog.csdn.net/wowricky/article/details/6894538
setuid 和 setgid (全稱分別是:set user ID upon execution 和 set group ID upon execution)是Unix的訪問權限標志位,它允許用戶以可執行文件owner或group的權限來運行這個可執行文件。它們經常適用於:為了運行特定的任務,可以允許用戶暫時的提高權限。用處:暫時的權限提升。
什么情況下需要setuid 和 setgid呢?當task需要的權限高於用戶的權限時,比如修改用戶的登錄密碼。有些任務需要更高的權限可能不會立刻表現出來,比如ping,它需要發送和監聽某個網絡接口的控制包。
1. setuid作用於可執行文件
當一個二進制可執行文件被設置了setuid屬性之后,在所創建的進程內部,有權限執行此文件的用戶將會獲得這個可執行文件的owner的權限(通常是root)。在進程內部,用戶獲取root權限之后,這個用戶將可以做一下常規用戶被限制做的事情,當然有些事情是禁止的:比如使用ptrace 、LD_LIBRARY_PATH, 或者給自己發送信號(但是從終端發送的信號是可以的)。由於潛在競爭條件,如果setuid 作用於shell 腳本,很多操作系統將會忽略掉setuid.
雖然setuid在很多場合是很有用的,但是如果一個可執行程序設計的不夠好並被設置了setuid將會帶來潛在的風險。人們能夠利用有漏洞的程序獲取永久的權限提升,或者讓用戶在無意之間運行一個特洛伊木馬。
setgid能夠改變group的權限,正如setuid改變user權限一樣。
setuid作用於可執行文件解釋了為什么系統調用chroot對於非root用戶是不可用的。
可以通過chmod 來設置setuid 和 setguid的標志位(最高位),
4: for setuid
2: for setguid
1: 這個是粘滯位 //可以參考:http://blog.csdn.net/hzgdiyer/article/details/6788275
"chmod 6711 file" 將會設置setuid 和setguid, bits(6) 即位最高位。
另外還多系統也支持 “chmod ug+s"命令來設置.
下面的演示代碼用來獲取並顯示出進程的real 和 effective 的用戶(user)和組(group)的ID:
1.顯示printid.c的代碼,這段代碼就是打印real/effective user/group ID
2.編譯程序printid
3.運行程序printid,打印出了real/effective user/group ID
4.修改printid的owner為root
5.給文件printid添加setuid和setgid標志位
6.取消文件printid其它用戶(other)的讀r和執行x權限
7.顯示文件printid屬性
8.重新運行printid,
我們發現printid權限:
owner:root, rws
group:staff, r-s
other: ---
雖然other沒有任何權限,但以用戶bobie(對於問價printerid,bobie不是owner,也不是group,屬於other)運行printid,依然可以運行,顯然是添加了setuid的原因。
通過打印信息可以看到effective id 是0,正好是root的id,可以參考/etc/passwd(里面有每個用戶/組對應的id)
//備注:如果這個程序是在volumn上運行且mounte時添加了'nosuid'選項,這個程序將會失敗,沒有打印信息;
//volumn: 可以再磁盤上創建卷(volumn),物理卷(PV)=》邏輯卷(LV)=>卷組(VG),最后將這卷組mounte到指定路徑
[bobie]$ cat printid.c
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(void) {
printf(
" UID GID \n"
"Real %d Real %d \n"
"Effective %d Effective %d \n",
getuid (), getgid (),
geteuid(), getegid()
);
return getegid() ; /* always good to return something */
}
[bobie]$ cc printid.c -o printid
[bobie]$ ./printid
UID GID
Real 1008 Real 1008
Effective 1008 Effective 1008
[bobie]$ sudo chown root printid # to change the owner you need to sudo
Password:
[bobie]$ sudo chmod ug+s printid # SetUID and SetGID flags
[bobie]$ sudo chmod o-rx printid # Don't let Others read or execute it
[bobie]$ ls -l
-rwsr-s--- 1 root staff 6944 2011-10-06 10:22 printid
[bobie]$ ./printid
UID GID
Real 1008 Real 1008
Effective 0 Effective 20
2.setuid/setgid作用於路徑
setuid和setgid作用於路徑時,有完全不同的含義。
給路徑設置setgid(chmod g+s),會導致路徑下新建的文件和子文件夾繼承它的group id, 而不創建文件或文件夾的用戶的primary group id.【只有group id 受影響,owner id 不受影響】。另外,新創建的子文件夾還將繼承setgid位。注意:給路徑設置setgid,僅僅影響新建的文件和文件夾的group id,已經存在的文件和文件夾不受影響。
給已經存在的子文件夾設置setgid,必須手動來做,用如下命令:
[root@foo]# find /path/to/directory -type d -exec chmod g+s {} \;
給路徑設置setuid,將會被Unix 和 Linux系統忽略。
3.安全
被設置setuid/setgid的程序必須小心的設計防止緩存區溢出攻擊。緩存區溢出攻擊成功的后果是:能夠使攻擊者利用進程的權限執行任意的代碼。如果一個有漏洞的程序被設置了setuid,權限提升以root運行,攻擊成功就會使攻擊者獲得root權限,這太可怕了。
4.歷史
setuid 是 Dennis Ritchie發明的,他所在的公司AT&T, 於1972年申請專利,1979年專利獲批,專利號:US 4135240 "Protection of data file contents".
http://waringid.blog.51cto.com/65148/95407
字符 | 含義 |
a | 修改所有用戶的特權 |
g | 修改組用戶的特權 |
o | 修改其它用戶的特權 |
u | 修改所有者的權限 |
字符 | 含義 |
- | 刪除當前的權限 |
= | 替換當前的權限 |
+ | 增加當前的權限 |
字符 | 含義 |
r | 讀訪問 |
w | 寫訪問 |
x | 執行訪問 |
s | SUID或是SGID |
t | 粘附位 |
八進制數 | 權限 |
4000 | SUID |
2000 | SGID |
1000 | 粘附位 |
0400 | 所有者可讀 |
0200 | 所有者可寫 |
0100 | 所有者可執行 |
0040 | 組成員可讀 |
0020 | 組成員可寫 |
0010 | 組成員可執行 |
0004 | 其它用戶可讀 |
0002 | 其它用戶可寫 |
001 | 其它用戶可執行 |
umask | 用戶訪問 | 組訪問 | 其它 |
0000 | 所有 | 所有 | 所有 |
0002 | 所有 | 所有 | 讀,執行 |
0007 | 所有 | 所有 | 無 |
0022 | 所有 | 讀,執行 | 讀,執行 |
0027 | 所有 | 讀,執行 | 無 |
0077 | 所有 | 無 | 無 |
如果在目錄上設置了這個位,那么大多數版本的unix不允許刪除或重新命名該目錄中的文件,除非你是該目錄的屬主,該文件的屬主或超級用戶.在這個目錄上擁有寫入權限是不夠的.這相約定是讓像/tmp之類的目錄變得多少有些隱私性和安全性的一種嘗試.
Solaris和HP-UX在處理粘附位目錄的時候並不那么嚴格.如果對該目錄有寫入權限,即使不是屬主,也能刪除其中的文件.這實際上有許多意義,雖然對實際應用幾乎沒有什么影響。
Linux中的粘滯位
Sticky 位是一個訪問權限標志位,可以用來標示文件和路徑。
歷史:
粘滯位是在1974年Unix的第5版中引入的,用來設置可執行文件。當可執行文件設置粘滯位之后,它能夠指示操作系統在程序退出后,保留程序的代碼段到swap空間。當程序再次執行時,內核只需將程序從swap搬到內存即可,這能夠加速程序的執行。所以,頻繁使用的程序比如編輯器能夠更快的打開。目前,這種應用只是適用於HP-UX, NetBSD和UnixWare,Solaris在2005年放棄了這種應用,linux沒有版本支持過這種行為。
當今使用:
當今,粘滯位最常用是應用於路徑。當路徑被設置粘滯位后,路徑下的文件只有文件的owner, 或者root 才能夠重命名、刪除文件。如果沒有粘滯位,任何用戶,不管是不是owner, 只要有路徑的寫/執行權限就可以重命名、刪除文件。典型的應用就是/tmp路徑,粘滯位可以阻止一般用戶刪除/重命名其他用戶的文件。這種特性首次引入是在1986年4.3BSD, 今天在現在的Unix系統中都可以找到這個特性。另外,Solaris定義了獨有的行為:當粘滯位設置到非執行文件時,當訪問這種文件時,內核將不會緩存。這常用於設置swap文件,用來阻止訪問這些文件時沖刷掉系統緩存中更重要的數據。
Sticky bit在不同系統中的異同
HP-UX:當程序的最后一個用戶退出時,阻止系統丟棄程序段swap-space image. 當下一個用戶執行這個程序時,系統只需要swap in,而不需要重從磁盤新讀入文件到內存,節約程序啟動時間。
[...] prevents the system from abandoningthe swap-space image of the program-text portion of the file when its last userterminates. Then, when the next user of the file executes it, the text need notbe read from the file system but can simply be swapped in, thus saving time.
Linux: 當粘滯位設置到文件時,內核將會忽略。當設置路徑時,路徑中的文件只能夠被root或者文件的owner重命名或者unlinked。
[...] the Linux kernel ignores the stickybit on files. [...] When the sticky bit is set on a directory, files in thatdirectory may only be unlinked or renamed by root or their owner.
舉例:
Sticky bit 設置:
chmod 命令,可以用八進制模式1000或者它的符號t.
比如:添加粘滯位到路徑/usr/local/tmp,
1. chmod +t /usr/local/tmp
2. chmod 1777 /usr/local/tmp
在Unix 文件系統 符號中,sticky bit t 是在最后一位。比如:在Solaris 8, /tmp路徑默認有粘滯位,如下:
$ ls -ld /tmp
drwxrwxrwt 4 root sys 485 Nov 10 06:01 /tmp
如果粘滯位設置的路徑或者文件沒有可執行(x)位,它的符號用T(大寫的t)
# ls -l test
-rw-r--r-- 1 root other 0 Nov 10 12:57 test
# chmod +t test; ls -l test
-rw-r--r-T 1 root other 0 Nov 10 12:57 test
From http://en.wikipedia.org/wiki/Sticky_bit