Linux Setuid(SUID)和Setgid(SGID) sticky bit

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

 

不管是Linux新手还是高手,在使用它的时候不可避免都会遇到Linux权限问题。而这些问题也是初学者问得最多的问题,很多的脚本不能执行的原因就是因为没有设定正确的权限所致。这里我们来看看Linux下的根限到底是怎么一回事。
  当你新建一个文件时,它的最初的权限取决于你的umask值(将在后面说明)。权限可以使用chmod命令或是chmod()系统调用来修改一个文件的权限模式。只有在文件所有者才能修改文件的权限模式。唯一例外的就是超级用户:超级用户可以修改任何文件的权限。下面是chmod命令的格式:
chmod [-Rfh] [agou] [+-=] [rwxXstugol] filelist
Image00001
要修改哪些用户的特权:
字符 含义
a 修改所有用户的特权
g 修改组用户的特权
o 修改其它用户的特权
u 修改所有者的权限
执行什么操作:
字符 含义
- 删除当前的权限
= 替换当前的权限
+ 增加当前的权限
要修改哪一项权限:
字符 含义
r 读访问
w 写访问
x 执行访问
s SUID或是SGID
t 粘附位
  其中X是表示由BSD衍生出来的UNIX系统特有的选项,它的意思是:如果文件是一个目录,或有一些其它执行位已设置,那么就将文件设置为只可执行。而l则是由System V衍生出来的UNX系统特有的选项,它的意思是:允许对文件进行强制加锁。-R选项表示chmod命令会递归执行。如果指定了一个目录filelist,那么目录的权限改变了,目录下所有文件的权限也都改变了。如果该目录包含子目录,那么这一地程会一直向下重复。-f选项表示强制执行,chmod命令不会报告错误。通常在shell中比较有用。
  在某些系统中使用-h选项来改变chmod对符号链接的工作方式。如果指定了-h选项,而其中一个参数据为符号链接的话,那么chmod不会改变符号链接所指向的那个文件或目录的权限。
下图说明了命令的使用方法:
Image00002
计算机八进制的文件权限:
  chmod允许用户使用一个四位八进制数字来指定文件权限模式。用户可以通过将权限相加的方式来计算这一数值。下表说明了每个文件权限对应的八进制数。
八进制数 权限
4000 SUID
2000 SGID
1000 粘附位
0400 所有者可读
0200 所有者可写
0100 所有者可执行
0040 组成员可读
0020 组成员可写
0010 组成员可执行
0004 其它用户可读
0002 其它用户可写
001 其它用户可执行
  因此,一个文件权限如果为“-rwxr-x---”,那么其文件模式为0750,计算过程为:0400+0200+0100+0040+0010=0750。例如常见的/tmp目录的权限就为1777,表示任何用户都可以在该目录下创建文件,但是用户不能删除其它用户的文件。
umask
  umask是“用户文件创建模式掩码”的缩写,是一个四位的八进制数值。用来确定一个新创建文件的权限。每个进程都从父进程那里继承了自己的umask。一般该命令会在.bashrc,.profile,.cshrc或是/etc/profile及/etc/bashrc中。
Image00003
  最常见的umask值是022,027以及077。022让文件所有者拥有对新建文件的读写权限,但是其它人对此只读。例如:0666(默认的文件建立模式)+0022(umask)=0644。计算umask值最简单的方法是记住:umask值中的2屏蔽了写权限,而7屏蔽了读,写及执行权限。
常用的umask设置:
umask 用户访问 组访问 其它
0000 所有 所有 所有
0002 所有 所有 读,执行
0007 所有 所有
0022 所有 读,执行 读,执行
0027 所有 读,执行
0077 所有
  下面的图片是显示新建文件后的权限,大家可以想想看它对应的umask应是多少。
Image00004 
粘附位:
  具有八进制值1000的位叫粘附位,是unix已经发展得不再需要的事物而又不能摆脱其追随的例子.像unix在其上度过它的孩童期的PDP-11/70这样的小内存系统,需要一些程序持续地驻留在内存或交换设备上这个时候粘附位就十分重要了.在今天由于有了25美圆的内存模块和快速磁盘驱动器,在可执行程序上的粘附位已经过时了,现代的内核已经悄然地忽略了它.
  如果在目录上设置了这个位,那么大多数版本的unix不允许删除或重新命名该目录中的文件,除非你是该目录的属主,该文件的属主或超级用户.在这个目录上拥有写入权限是不够的.这相约定是让像/tmp之类的目录变得多少有些隐私性和安全性的一种尝试.
  Solaris和HP-UX在处理粘附位目录的时候并不那么严格.如果对该目录有写入权限,即使不是属主,也能删除其中的文件.这实际上有许多意义,虽然对实际应用几乎没有什么影响。
SUID和SGID
  setuid和setgid的位值是04000和02000。这些位允许程序访问运它们的用户本来无权访问的文件和进程。当某个目录上设置setgid位时,在这个目录中新创建的文件具有该目录的属组权而不是创建该文件的用户的默认属组。这项约定使得在几个用户之间(只要这些用户都属于同一个组)共享一个目录中的文件变得更简单。在使用这些特性之前,请检查自己的系统,因为并不是所有版本的unix都支持这个特性,当然BSD,REDHAT,HP-UX,SOLARIS都是支持的。对setgid位的这种解释跟它在可执行文件上设置时的含义没有什么关系,但不要混淆了这两种意义。一些系统允许在非可执行的纯文本文件上设置setgid位,以在该文件被打开时请求特殊的锁定。有关它的详细说明可以参考:[url]http://www.linuxeden.com/html/unix/20071031/36892.html[/url]。在linux下,有关SUID最常用的一个命令就是ping,下面是关于它的图片,好好看看吧。
Image00005
 
 
 
 
 

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

posted @ 2014-01-02 20:58  baihuahua  阅读(3843)  评论(0编辑  收藏  举报