文章转载至:http://tech.ccidnet.com/art/2583/20071030/1258885_1.html 如果你对SUID和SGID还很困惑,可以参考一下!由于用户在UNIX下经常会遇到SUID和SGID的概念,而SUID和SGID涉及到系统安全,因此用户也比较关心这个问题。关于SUID和SGID的问题经常被问到,但答案普遍不够详细。另外,我回答了两位网友的问题并查了一些资料,所以决定整理这篇文章供大家参考。由于本人水平有限,文中如有不妥之处,敬请指正。 1、UNIX下文件权限的表示与分析。 SUID 表示设置用户ID,SGID 表示设置组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代表套接字文件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位,它将分别出现在所有者或同组用户的权限的可执行位中。例如: 1. -rwsr-xr-x 表示设置了SUID 和所有者权限中的可执行位2. -rwSr--r-- 表示设置了SUID,但未设置所有者权限中的可执行位set 3. - rwxr-sr-x 表示设置SGID和同组用户权限中的可执行位。 4、-rw-r-Sr--表示设置了SGID,但未设置同组用户权限中的可执行位。事实上,它是在UNIX中实现的,文件权限由12个二进制位表示。如果该位置的值为1,则表示有对应的权限: 11 10 9 8 7 6 5 4 3 2 1 0S GT r w x r w x r w x第11位是SUID位,第10位是SGID位,第9位是粘性位,位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,包括用户id和组id。用户可以使用id命令查看自己或其他用户的用户id和组id。除了一般的用户id和组id之外,还有两个id称为有效id,即有效id。上面的四个id分别表示为:uid、gid、euid、egid。内核主要根据euid和egid来决定进程对资源的访问权限。如果一个进程没有SUID或SGID位,那么euid=uidegid=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根系统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#includeuid_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======注意位置#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不起作用。为什么需要suid,如何使用suid r -- 读权限w -- 写权限x -- 执行权限s -- SUID/SGID t -- 粘性位那么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应运而生。 ATT也为此申请了专利。呵呵。 SUID和SGID如何解决这个问题呢?首先我们要知道一件事:进程运行时,有一些属性,包括实际用户ID、实际组ID、有效用户ID、有效组ID等。 实际用户ID和实际组ID确定我们是谁以及谁在运行该程序。一般情况下,这两个字段是在登录时确定的。在登录会话期间,这些值基本上不会改变。有效用户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.netping: icmp open socket: Operation not allowedSUID很好地解决了一些问题,但也带来了一些安全隐患。因为如果设置了SUID位的程序受到攻击(通过缓冲区溢出等),那么黑客就可以获得root权限。因此,对于那些设置了SUID的程序,从安全角度来说要特别注意。可以通过以下命令找到系统上所有设置了suid的文件: [root@sgrid5 /]# find/-perm -04000 -type f -ls 至于为什么这里是4000,可以看一下前面的st_mode 的位的含义就清楚了。在这些设置了suid的程序中,如果不使用的话,最好取消程序的suid位。