实验一
Linux 系统文件和目录权限设置与辨识 setuid 程序 uid 差异
1、修改文本文件流星雨.txt,该用户允许别人下载:
1)用户 goku 具有文本文件流星雨.txt,该用户允许别人下载;
查看 流星雨.txt 的权限:
goku@goku-VPCS138EC:~$ ls -l 流星雨.txt
-rw-r----- 1
goku goku 0 11 月 23
2011 流星雨.txt
2)此时不允许别人下载,例如切换 到实现建立好的用户 zxc:
goku@goku-VPCS138EC:~$ su zxc
3)切换用户之后再试试将 流星雨.txt 下载到其他文件夹下,就会显示权限不够:
$ cp 流星雨.txt 下载
cp: 无法打开"流星雨.txt" 读取数据: 权限不够
4)若该用户允许别人下载,则需要在 other 中授予 流星雨.txt 读的权限(注意此时先要授
予下载这个文件夹 other 的 w 权限):
goku@goku-VPCS138EC:~$ chmod 644 流星雨.txt
goku@goku-VPCS138EC:~$ ls -l 流星雨.txt
rw-r--r-- 1
goku goku 0 11 月 23
2011 流星雨.txt
再设置下载这个文件夹 other 的 w 权限:
goku@goku-VPCS138EC:~$ chmod 753 下载
设置好了就是这样
drwxr-x-wx 2 goku goku 4096 11 月 2 21:56 下载
此时流星雨.txt 已经可以被其他用户下载了。进入用户 zxc:
$ cp 流星雨.txt 下载
$
表示复制成功!
2.用户 A 有编译了一个可执行文件 cal.exe,该用户想在系统启动时运行
1)开机是由于是以 root 身份运行 cal.exe,所以要设置 owner 的执行权限。
goku@goku-VPCS138EC:~$ chmod 744 cal.exe
goku@goku-VPCS138EC:~$ ls -ll cal.exe
-rwxr--r-- 1 goku goku 0 11 月 23
2011 cal.exe
3.用户 A 有起草了文件 demo.txt,想让同组的用户帮其修改文件;
goku@goku-VPCS138EC:~$ ls -l demo.txt
-rw----r-- 1 goku goku 0 11 月 23
2011 demo.txt
进入事先建立好的与 lenovo-xq 同组的用户 asd:
$ id asd
uid=1005(asd) gid=1005(asd) 组=1005(asd),1000(goku) (从这里可以看出 asd 与
goku 一组)
goku@goku-VPCS138EC :~$ su asd
密码:
$ vim demo.txt
进入 vim 编辑的时候就会出现
E138: 无法写入 viminfo 文件 /home/asd/.viminfo!
修改 demo.txt 组内的读和写的权限,文件就可以编辑和修改了:
goku@goku-VPCS138EC:~$ chmod 664 demo.txt
goku@goku-VPCS138EC :~$ ls -l demo.txt
-rw-rw-r-- 1 goku goku 0 11 月 23
2011 demo.txt
4.设计并实现 setuid 程序的使用,并分析不同用户 fork 调用 setuid 程序后
euid、ruid、suid 的差别,以及用户调用 execl 执行 setuid 程序后 euid、ruid、
suid 的差别。
real user ID 表示的是实际上进程的执行者是谁,effective user ID 主要用于校验该进程
在执行时所获得的文件访问权限,也就是说当进程访问
文件时检查权限时实际上检查的该进程的"effective user ID",saved set-user-ID 仅在
effective user ID 发生改变时保存.
一般情况下,real user ID 就是进程的 effective user ID,但是当要运行的可执行程序设置
了"set-user-ID"位之后,进程的 effective user ID
变成该文件的属主用户 id,同时该进程的"saved set-user-ID"变成此时进程的"effective
user ID",也就是该可执行程序的属主用户 ID,该进程
在执行一些与文件访问权限相关的操作时系统检查的是进程的 effective user ID.
当进程没有超级用户权限的时候,进程在设置"effective user ID"时需要将需要设置的 ID
和该进程的"real user ID"或者"saved set-user-ID"进行比较.
也就是说:
1)当用户具有超级用户权限的时候,setuid 函数设置的 id 对三者都起效.
2)否则,仅当该 id 为 real user ID 或者 saved set-user-ID 时,该 id 对 effective user ID
起效.
3)否则,setuid 函数调用失败.
这个 saved set-user-ID 更多的作用是在进程切换自己的 effective user ID 起作用.
举一个例子说明问题,假设这样的一种情况,系统中有两个用户 A,B,还有一个由 B 创建的可
执行程序 process,该可执行程序的 set-user-id 位已经进行了设置.
当 A 用户执行程序 process 时,
程序的 real user ID = A 的用户 ID,effective user ID = B 的用户 ID,
saved
set-user-ID=B 的用户 ID.
假如在该进程结束了对某些限制只能由用户 B 访问的文件操作后,程序将 effective user ID
设置回 A,也就是说此时:
程序的 real user ID = A 的用户 ID,effective user ID = A 的用户 ID,
saved
set-user-ID=B 的用户 ID.
以只能通过两种途径获得(可能还有别的途径):
setuid(设置真实的用户识别码)
相关函数 getuid,setreuid,seteuid,setfsuid
表头文件 #include
定义函数 int setuid(uid_t uid)
函数说明 setuid()用来重新设置执行目前进程的用户识别码。不过,要让
此函数有作用,其有效的用户识别码必须为 0(root)。在 Linux
下,当 root 使用 setuid()来变换成其他用户识别码时,root 权
限会被抛弃,完全转换成该用户身份,也就是说,该进程往后将
不再具有可 setuid()的权 利,如果只是向暂时抛弃 root 权限,
稍后想重新取回权限,则必须使用 seteuid()。
返回值 执行成功则返回 0,失败则返回-1,错误代码存于 errno。
附加说明 一般在编写具 setuid root 的程序时,为减少此类程序带来的系
统安全风险,在使用完 root 权限后建议马上执行
setuid(getuid());来抛弃 root 权限。此外,进程 uid 和 euid 不
一致时 Linux 系统将不会产生 core dump。
普通用户:goku
1.getresuid()
2.setresuid(getuid,0,getuid)
3.setresuid(getuid,getuid,0)
4.setresuid(0,0,getuid)
5.setresuid(getuid,getuid,getuid)
6.setresuid(0,0,0)
return 0;
#include
#include
#define _GNU_SOURCE
#include
#include
#include
int main()
{
int r,e,s;
getresuid(&r,&e,&s);
int euid;
printf("R:%d\tE:%d\tS:%d\t\n",r,e,s);
if(!fork())
{
printf("not root\n");
if(!setresuid(geteuid(),0,geteuid()))
{
printf("sucess\n");
getresuid(&r,&e,&s);
printf("now\tR:%d\tE:%d\tS:%d\t\n",r,e,s);
}
else
{
printf("error\n");
}
if(!setresuid(geteuid(),geteuid(),0))
{
printf("sucess\n");
getresuid(&r,&e,&s);
printf("now\tR:%d\tE:%d\tS:%d\t\n",r,e,s);
}
else
{
}
printf("error\n");
if(!setresuid(geteuid(),0,0))
{
printf("sucess\n");
getresuid(&r,&e,&s);
printf("now\tR:%d\tE:%d\tS:%d\t\n",r,e,s);
}
else
{
}
printf("error\n");
if(!setresuid(geteuid(),geteuid(),geteuid()))
{
printf("sucess\n");
getresuid(&r,&e,&s);
printf("now\tR:%d\tE:%d\tS:%d\t\n",r,e,s);
}
else
printf("error\n");
{
}
}
wait(NULL);
return 0;
}
root@goku-VPCS138EC:/home/goku# gcc -o yan yan.c
root@goku-VPCS138EC:/home/goku# su goku
goku@goku-VPCS138EC:~$ ./yan
R:1000
E:1000
S:1000
not root
error
error
error
sucess
S:1000
E:1000
now R:1000
经过测试得出,当用户为普通用户时,srtresuid 只能设置为 ruid,euid,suid 中的一个,
而不能设置为 0,或者其他 uid,并且子进程完全继承父进程的 uid。非 root 用户是不可能
通过 setresuid 取得其他权限(包括 root 权限)的,它只能恢复原来的权限。允许通过
setresuid 取得 root 权限是非常危险的,这样就可以在程序的后边做任何想做的事了(包
括 kill 掉你的进程,系统)。
root 用户:
1.getresuid()
2.id=GetPasswdId(char *name)
3.setresuid(id,id,0)
4.setresuid(id,0,id)
5.setresuid(id,id,id)
6.setresuid(0,0,0)
return 0;
#include
#include
#define _GNU_SOURCE
#include
#include
#include
int GetPasswdId(const char *name)
{