在Linux系统中每一个普通用户均可以更改本身的密码,这是合理的设置。linux
问题是:用户的信息保存在文件/etc/passwd中,用户的密码保存在文件/etc/shadow中,也就是说用户更改本身密码时是修改了/etc/shadow文件中的加密密码,可是,shell
-rw-r--r-- 1 root root 1787 Oct 27 2009 /etc/passwd安全
-r-------- 1 root root 1187 Oct 27 2009 /etc/shadowbash
/etc/passwd文件每一个用户都有读权限可是只有root有写权限,/etc/shadow文件只有超级用户root有读写权限,也就是说普通用户对这两个文件都没有写权限没法写入新密码,为何普通用户能够更改密码呢?ui
PS:在linux中设置或更改用户密码,是先写入到/etc/passwd文件而后经过pwconv命令转换到/etc/shadow文件,执行pwunconv命令可观察到转换前效果,会观察到/etc/shadow文件神奇的消失掉了,而/etc/passwd文件中原来打x的地方变成了真正的加密密码。加密
其实,用户能更改密码真正的秘密不在于文件的权限,而在于更改密码的命令passwd 。spa
-rwsr-xr-x 1 root root 22960 Jul 17 2006 /usr/bin/passwd.net
passwd命令有一个特殊的权限标记s ,存在于文件全部者的权限位上。这是一类特殊的权限SetUID ,能够这样来理解它:当一个具备执行权限的文件设置SetUID权限后,用户执行这个文件时将以文件全部者的身份执行。passwd命令具备SetUID权限,全部者为root(Linux中的命令默认全部者都是root),也就是说当普通用户使用passwd更改本身密码的时候,那一瞬间忽然灵魂附体了,实际在以passwd命令全部者root的身份在执行,root固然能够将密码写入/etc/shadow文件(不要忘记root这个家伙是superuser什么事均可以干),命令执行完成后该身份也随之消失。token
能够试验用root身份修改passwd命令权限去掉SetUID :进程
chmod u-s /usr/bin/passwd
再尝试以普通用户身份登陆后修改密码,就会发现提示:
passwd
Changing password for user samlee.
Changing password for samlee
(current) UNIX password:
passwd: Authentication token manipulation error
普通用户没法修改密码,因此只要可以想明白为何普通用户能够更改密码就能够大概了解SetUID权限的做用。
接下来咱们用两个SetUID的按理来进一步诠释下它的概念——
案例一:SetUID受权示例
为便于深刻理解SetUID ,笔者以touch命令为例作一演示。
普通用户samlee用touch建立文件newfile01 :
touch newfile01
ls -l newfile01
-rw-rw-r-- 1 samlee samlee 0 05-21 01:20 newfile01
文件的建立者默认就是全部者,因此文件newfile01的全部者为samlee 。
管理员root给touch命令添加SetUID权限:
chmod u+s /bin/touch # 或 chmod 4755 /bin/touch
ls -l /bin/touch
-rwsr-xr-x 1 root root 42284 Jul 13 2009 /bin/touch
再用普通用户samlee建立文件newfile02,看到以下结果:
touch newfile02
ls -l newfile02
-rw-rw-r-- 1 root samlee 0 05-21 01:48 newfile02
经过这个例子,咱们能够再诠释下SetUID的定义,当一个可执行文件(命令touch)设置SetUID权限后,当普通用户samlee执行touch建立新文件时,其实是以touch命令全部者root的身份在执行此操做,既然是以root身份执行,固然新建文件的全部者为root ,这就是SetUID的做用。
再看一下与SetUID相似的SetGID权限,看一个例子,给touch命令再授予SetGID :
chmod g+s /bin/touch # 或 chmod 6755 /bin/touch
ls -l /bin/touch
-rwsr-sr-x 1 root root 42284 Jul 13 2009 /bin/touch
此时,再使用touch建立新文件newfile03,会看到以下现象:
touch newfile03
ls -l newfile03
-rw-rw-r-- 1 root root 0 05-21 01:48 newfile02
新建文件的所属组为touch命令的所属组,而不是执行touch命令的普通用户samlee的所属组,这就是SetGID的做用,与SetUID相似,用户在执行具备SetGID的命令时会调用命令所属组的身份。
案例二:危险的SetUID
对于SetUID的使用,能够作一个的比喻:一个绝密机关,要让一些人进来作一些事情,可是不能让他们看见机关内部的状况,因而受权一些特殊的“车辆”(没有窗户,车门紧闭,看不到外面,只有一个小洞容许乘坐的人伸出手臂作事),带着所乘坐的人开到要去的地方,容许它办完事情立刻带他出来。这样是否是很安全?不必定。若是“车辆”没有通过精挑细选,可能有不少“门窗”,那可就危险了,这种相似的场景相信你们在一些警匪电影中已经见过屡次了。
普通用户使用vi编辑/etc/shadow文件会提示“PermissionDenied”,这是合理的设置,可是若是赋予vi以SetUID权限:
chmod u+s /bin/vi
ls -l /bin/vi
-rwsr-xr-x 1 root root 594740 Jun 12 2009 /bin/vi
此时,普通用户使用vi便可以编辑/etc/shadow文件,由于具有root身份,能够进行任意读写操做(好比能够把任何一个用户密码位清空,则用户登陆不须要输入密码)。可是使用more、cat等命令仍然没法查看文件/etc/shadow的内容,只有被授予了SetUID的vi能够查看和修改。一样,vi若是具备了SetUID权限,普通用户能够vi编辑/etc/passwd文件把本身的UID改成0 ,则他的权限就和root同样;能够vi编辑/etc/inittab文件把缺省运行级别改为6 ,则Linux会开机后不停的重启……
再来看一个使人不安的状况,用普通用户尝试关闭Apache服务:
ps -le | grephttpd
140 S 0 8916 1 0 76 0 - 3697 - ? 00:00:00 httpd
kill 8916
-bash: kill: (8916) - Operation not permitted
能够看到,普通用户不能够关闭root启动的进程,可是若是作下面一个动做:
chmod 6555 /bin/kill
如今当普通用户执行kill时,由于kill被授予了SetUID权限,在执行的一瞬间具备了root权限,只要用户不爽想关闭任何服务均可以!
因此,SetUID权限不能随便设置,同时要防止黑客的恶意修改,怎样避免SetUID的不安全影响,有几点建议:
1. 关键目录应严格控制写权限。好比“/”、“/usr”等;
2. 用户的密码设置要足够强壮,8位以上,大小写字母、数字、符号的组合,如:Am@ri31n,且按期更换;
3. 对系统中应该具备SetUID权限的文件做一列表,定时检查有没有这以外的文件被设置了SetUID权限。
能够对系统中应该具备SetUID权限的文件做一列表,定时检查有没有非列表中的命令被设置了SetUID权限。
在Linux安装部署完成后,执行下面命令生成SetUID列表文件:
mkdir /script # 建立目录/script
find / -perm -4000 -o -perm -2000 >/script/setuid.list
命令find选项“-perm”为指定文件权限,SetUID权限位对应数字标识为4 ,SetGID权限位对应数字标识为2 ,后面写为“000”标识对全部者所属组其余人三类用户的权限不限制;“-o”表示or,就是文件具备SetUID或者具备SetGID都在搜索之列,生成的搜索结果存放在文件/script/setuid.list中。
在须要对系统作检查时,执行如下shell程序。也能够放在计划任务中定时检查。
/usr/bin/find / -perm -4000 -o -perm -2000 >/tmp/setuid.check
for file in `/bin/cat /tmp/setuid.check`
do
/bin/grep $file /script/setuid.list > /dev/null
if [ "$?" != "0" ]
then
echo "$file isn't in list! it's danger!!"
fi
done
/bin/rm /tmp/setuid.check
假设命令kill被设置了SetUID ,则会检测提示:
/bin/kill isn't in list! it's danger!!
另外,若是在一些数据存放的分区想禁用SetUID功能,还能够作以下设置,编辑配置文件/etc/fstab ,找到要设置的分区(如/home)所对应的设置行:
vi /etc/fstab
LABEL=/home /home ext3 defaults 1 2
在设置“defaults”后,添加“nosuid”选项,并从新挂载/home分区:
vi /etc/fstab
LABEL=/home /home ext3 defaults,nosuid 1 2
mount -o remount /home
设置后,分区/home上任何可执行文件即便被设置了SetUID权限也没法执行(读者可自行拷贝一个SetUID命令至/home目录下执行试验),在一些存放数据、用来备份等功能的分区上作此设置,能够保护系统安全。
友情提示:请您做完本文中的实验后,别忘把文件的权限恢复原状,以避免带来没必要要的麻烦。
至此相信读者已经对SetUID的做用有所了解,最后,还有一个你们要注意的问题,SetUID只针对具备可执行权限的文件有效,不具备x权限的文件被授予了SetUID会显示标记为S(一会儿由小s变成姐姐了),仔细想一下,若是没有可执行权限的话设置SetUID无任何意义。