1.问题的引入
普通用户是无法查看/etc/shadow文件的,但是当普通用户使用命令passwd去修改自己的口令的时候,确实可以成功的。修改口令一定会改变/etc/shadow文件,那么是如何做到的呢?
2.查看passwd
注意在用户属性上面有一个S , 那就是set uid
是为了让一般用户在执行某些程序的时候,能够暂时具有该程序拥有者的权限
SUID仅 可用在“二进制文件(binary file)”,SUID因为是程序在执行过程中拥有文件拥有者的权限,因此,它仅可用于二进制文件,不能用在批处理文件(shell脚本)上。这是因为 shell脚本只是将很多二进制执行文件调进来执行而已。所以SUID的权限部分,还是要看shell脚本调用进来的程序设置,而不是shell脚本本 身。当然,SUID对目录是无效的。这点要特别注意
3.G+S
Set GID
进一步而言,如果s的权限是在用户组,那么就是Set GID,简称为SGID.SGID可以用在两个方面。
文件:如果SGID设置在二进制文件上,则不论用户是谁,在执行该程序的时候,它的有效用户组(effective group)将会变成该程序的用户组所有者(group id)。
目录:如果SGID是设置在A目录上,则在该A目录内所建立的文件或目录的用户组,将会是此A目录的用户组。
一般来说,SGID多用在特定的多人团队的项目开发上,在系统中用得较少
4.一个用户的ID分为
①实际用户ID
②有效用户ID
③保存的设置用户ID
只有超级用户才能改变实际用户的ID,当我们在登录的时候,login进程就是一个超级用户进程,它接受你输入的用户名和密码,当你输入校验完成后,他fork出一个shell,并且将当前的所有用户ID全部设置为你输入的用户
若不是超级用户,只能将有效用户ID设置为UID不更改其他两个ID
5.四个函数
SYNOPSIS
#include <unistd.h>
#include <sys/types.h>
uid_t getuid(void);
uid_t geteuid(void);
DESCRIPTION
getuid() returns the real user ID of the calling process.
geteuid() returns the effective user ID of the calling process.
SYNOPSIS
#include <unistd.h>
#include <sys/types.h>
gid_t getgid(void);
gid_t getegid(void);
DESCRIPTION
getgid() returns the real group ID of the calling process.
getegid() returns the effective group ID of the calling process.
SYNOPSIS
#include <sys/types.h>
#include <unistd.h>
//交换Real uid和 Effective uid
int setreuid(uid_t ruid, uid_t euid);
int setregid(gid_t rgid, gid_t egid);
setreuid() sets real and effective user IDs of the calling process.
6.setuid
SYNOPSIS
#include <sys/types.h>
#include <unistd.h>
int setuid(uid_t uid);
DESCRIPTION
setuid() sets the effective user ID of the calling process.
If the effective UID of the caller is root,
the real UID and saved set-user-ID are also set.
7.一个demo
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char**argv)
{
pid_t pid;
if(argc < 3)
{
fprintf(stderr, "No Enough argc\n");
exit(1);
}
pid = fork();
if(pid < 0)
{
perror("fork()");
exit(1);
}
if(0 == pid)
{
setuid(atoi(argv[1]));
execvp(argv[2], argv+2);
perror("execvp()");
exit(1);
}
wait(NULL);
return 0;
}
注意这个必须是一个具有s属性的文件