Linux安全—Setuid特权程序(一)

学习知识需要掌握的三个关键点:what、how、 why.遵循这三个关键点,来对今天的话题进行探讨。

首先,需要回答Set-UID特权程序是什么,有什么样的性质。
在Linux系统中,用户的密码信息是保存在/etc/shadow文件中的,查看其属性,该文件的拥有者是root,而且只有root用户具有读写权限,其他用户没有读写权限。
bingxian@ubuntu:/$ ll /etc/shadow
-rw-r—– 1 root shadow 1481 Dec 20 08:35 /etc/shadow
那么问题来了,当Linux的普通用户需要更新密码时,所用到的命令是passwd(当然,passwd是个程序),在用户更新密码之后肯定是将密码更新后的信息写入到/etc/shadow文件中的,但普通用户并没有对该文件具有写入的权限,这是怎么做到的?
其实,passwd就是传说中的Setuid程序,所谓Setuid,即”Set user ID upon execution”的简称,说得通俗易懂一点,其实就是在给程序的权限表上打上一个能以该程序的拥有者的权限运行的标签,那么,当程序在运行时,就以该程序的拥有者的权限执行。
来看一下passwd的属性:
bingxian@ubuntu:/$ ll /usr/bin/passwd
-rwsr-xr-x 1 root root 41284 Sep 13  2012 /usr/bin/passwd*
我们知道,Linux中对文件的访问控制策略采取的方法是9bit位机制。但注意passwd前面有一个s位的标识,这个就是setuid的标识了。其实,除了9bit外,Linux还有另外3个bit,其中一个bit就是标记了该程序是否属于setuid特权程序。PS:这个setuid标识是由C语言的创建者Dennis Ritchie发明的。
那么,也就容易理解为什么passwd能够修改用户的密码了:普通用户虽然没有权限去修改/etc/passwd文件的权限,但是当执行passwd命令时,该程序会以root权限执行,对该文件进行了修改。
一般的程序不是setuid的程序,例如cat:
bingxian@ubuntu:/$ ll /bin/cat
-rwxr-xr-x 1 root root 46764 Nov 20  2012 /bin/cat*
cat虽然是属于root用户,但没有s标志位,所以普通用户使用时不会按root的权限执行。
所以,当以普通用户bingxian访问/etc/shadow文件时,会出现如下的提示:
bingxian@ubuntu:/$ cat  /etc/shadow
cat: /etc/shadow: Permission denied
此时没有权限进行访问。那么,怎样能够让普通用户能够访问该文件。通过上面的知识,答案就很明了,即将cat设置成setuid的程序,普通用户使用cat命令时,cat就以root用户权限进行运行,肯定就能够访问/etc/shadow文件了。在root用户下执行下面的命令:
[12/20/2014 15:35] root@ubuntu:/# chmod u+s /bin/cat
接着查看其属性:
12/20/2014 15:36] root@ubuntu:/# ll /bin/cat
-rwsr-xr-x 1 root root 46764 Nov 20  2012 /bin/cat
已经含有s的标识,说明将cat设置成setuid特权命令成功,再次转到bingxian用户下,使用cat命令查看/etc/shadow文件,看是否具有权限:
bingxian@ubuntu:/$ cat /etc/shadow
root:$6$012BPz.K$fbPkT6H6Db4/B8cLWbQI1cFjn0R25yqtqrSrFeWfCgybQWWnwR4ks/.rjqyM7Xwh/pDyc5U1BWOzkWh7T9ZGu.:15933:0:99999:7:::
(以下的内容略去)
通过上面的例子,就可以大致了解setuid的特征了。在这里做一个比喻吧,皇帝(root)比较忙,所以不可能全国各地到处巡视。于是,他派出了钦差大臣。钦差大臣本身没有掌控生杀大权,但得到了御赐的上方宝剑(setuid权限),于是他便有了皇帝的权利。在办完公事后,上方宝剑交还,钦差大臣的特权也就没有啦。
虽然setuid特权程序以root权限执行是暂时的,但其带来的安全隐患却不容忽视。就如同上面的cat程序,root用户随意设置setuid程序,就会导致用户能够访问到敏感信息。
这里再举一个例子:在root用户下,将/bin/sh拷贝到一个tmp文件夹,将其设置为setuid程序,然后以普通用户登录,执行该程序,就会得到root权限:
[12/20/2014 16:01] root@ubuntu:/# cp /bin/sh tmp/
[12/20/2014 16:01] root@ubuntu:/# cd tmp/
[12/20/2014 16:01] root@ubuntu:/tmp# chmod u+s sh
[12/20/2014 16:01] root@ubuntu:/tmp# ll sh
-rwsr-xr-x 1 root root 100284 Dec 20 16:01 sh
[12/20/2014 16:01] root@ubuntu:/tmp# su bingxian
bingxian@ubuntu:/tmp$ ./sh
 # whoami

root

这样的方法简直是满满的恶意啊`(*∩_∩*)′,如果您读到这里的话,请发散您的思维吧。
本文以上的内容已经解释了what和why,接下来将是解答how。
要全面理解setuid程序,需要理解有效用户ID(effective UID)和真实用户ID(real UID)。
系统查看当前进程对客体的访问权限,使用的是有效用户ID(访问控制是基于有效用户ID和组ID的);真实用户ID即是指该进程真正的拥有者,即创建该进程的用户。
例如,对于setuid的程序,有效用户ID是该程序的拥有者,而真实用户ID是使用该程序的用户。
而非setuid的程序,有效用户和真实用户都是使用该程序的用户。
在用户登录系统的时候,登录进程的有效用户ID,真实用户ID和暂存用户ID都设置成登录用户的ID。当进程调用exec函数家族执行一个程序时,与该进程相关联的用户和组ID就可能会改变。如果执行的程序是一个setuid程序,有效用户ID和暂存用户ID会被设置成为该程序的拥有者。如果该文件被标识为set-group-id标识,那么该文件的有效和暂存用户ID会被设置成为执行该程序的用户组ID。如果以上两种都不是的话,则暂存用户ID,有效用户ID都不会改变。
对于setuid的漏洞利用,以及如何提高set-uid程序的安全性问题,下一节将进行讲述。
                   http://zh.wikipedia.org/wiki/用户ID