博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

setuid seteuid 函数

Posted on 2015-05-20 10:55  bw_0927  阅读(1761)  评论(0)    收藏  举报

uid=real uid =用户登录shell时的用户id  执行程序的用户id

euid = effective uid = 执行该程序的用户id  可执行程序的属主id 

通过whoami 或 id命令可以查看

setuid()用来重新设置执行目前进程的用户识别码。不过,要让此函数有作用,其有效的用户识别 码必须为0(root)。在Linux下,当root使用setuid()来变换成其他用户识别码时,root权限会被抛弃,完全转换成该用户身份,也就 是说,该进程往后将不再具有可setuid()的权利,如果只是向暂时抛弃root 权限,稍后想重新取回权限,则必须使用seteuid()。

执行成功则返回0,失败则返回-1,错误代码存于errno。

 

一般在编写具setuid root的程序时,为减少此类程序带来的系统安全风险,在使用完root权限后建议马上执行setuid(getuid());来抛弃root权限。此外,进程uid和euid不一致时Linux系统将不会产生core dump。

 

 

int setuid(uid_t uid)

 

 

 

1)       若进程具有超级用户权限(以root用户来执行文件),则setuid将实际用户ID、有效用户ID及保存的设置用户ID设置为uid

 

2)       若进程没有超级用户权限(用普通用户来执行文件),但是uid等于实际用户ID或保存的设置用户ID,则setuid只将有效用户ID设置为uid

 

 

 

int seteuid(uid_t uid)

 

1)       若进程具有超级用户权限,则setuid只将有效用户ID设置为uid

 

2)       若进程没有超级用户权限,则setuid只将有效用户ID设置为uid, 但是uid必须等于实际用户ID或保存的设置用户ID,

 

 

 

int setreuid(uid_t ruid, uid_t euid)

 

1)       针对设置用户ID位的程序: 交换有效用户ID和保存的设置用户ID

 

2)       针对没有设置用户ID位的程序: 交换有效用户ID和实际用户ID

 

===============================================

http://hubingforever.blog.163.com/blog/static/171040579201372932033844/

本文参照自:
linux系统中每个进程都有2个ID,分别为用户ID和有效用户ID,UID一般表示进程的创建者(属于哪个用户创建),而EUID表示进程对于文件和资源的访问权限(具备等同于哪个用户的权限)。可以通过函数getuid()和geteuid()来取得他们。另外可以通过setuid()来设置它们。
setuid()设置实际用户 UID ,并同时设置有效用户 UID。
setgid() :设置实际组 ID ,并同时设置有效组 ID
系统中的用户信息

[root@10:25:48 c]>>> id root
uid=0(root) gid=0(root) groups=0(root)

[root@10:26:16 c]>>> id bwei
uid=500(bwei) gid=500(bwei) groups=500(bwei)

[root@10:26:29 c]>>> id bwei2
uid=501(bwei2) gid=501(bwei2) groups=501(bwei2)

两个函数声明如下: 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void show_ids()
{
        uid_t uid = getuid();
        uid_t euid = geteuid();

        printf("real userid :%d, effective uerid:%d\n", uid, euid);
}

int main()
{
        show_ids();

        if(setuid(501) < 0)
        {
                perror("setuid error");
        }

        show_ids();

        return 0;
}

  

 在使用该函数时会遇到以下情况:
1. 若进程有 root 权限(以root用户执行该文件),则函数将实际用户 ID、有效用户 ID 设置为参数 uid 。使用 root 运行上面代码:
 
运行输出:

real userid :0, effective uerid:0
real userid :501, effective uerid:501

由此可见,在 root 下,实际用户 ID 和有效用户 ID 均被设为 setuid() 的参数 uid 的值。
对此也可参照《setuid()与setgid()的使用 (中)》中实例1
2. 若进程不具有 root 权限(以普通用户执行该文件),那么普通用户使用 setuid() 时参数 uid 只能是自己的,没有权限设置别的数值,否则返回失败:

 

[root@10:28:05 c]>>> su bwei

[bwei@10:28:13 c]>>> ./a.out
real userid :500, effective uerid:500
setuid error: Operation not permitted    //普通用户不能setuid(其他用户id)
real userid :500, effective uerid:500

 

切换到root用户,设置强制位

[bwei@10:35:18 c]>>> su

[root@10:35:40 c]>>> chmod +s a.out

-rwsr-sr-x 1 root root 7108 May 20 10:22 a.out

再以普通用户执行

[root@10:35:58 c]>>> su bwei
[bwei@10:36:03 c]>>> ./a.out

输出:

real userid :500, effective uerid:0
real userid :501, effective uerid:501

由 以上可以看出,只有超级用户进程才能更改实际用户 ID 。所以一个非特权用户进程(普通用户)不能通过 setuid(0) 或 seteuid 得到特权用户权限
普通用户执行一个设置了 "set_uid"强制 位的程序时,内核将进程的有效用户 ID 设置为文件属主的 ID(root 的 ID)。所以普通用户现在能setuid(其他用户id)了。
但从此该进程就不具有超级用户权限了。所以此后程序已经被降权为普通用户,想再  seteuid (0) 已经不可能。
内核检查一个进程是否具有某权限时,是使用进程的有效用户 ID 来进行检查的。su 程序的文件属主是 root,普通用户运行 su 命令时,su 进程的权限是 root 权限。 
 
关于文件的"set_uid" 位的更多内容请阅读《chmod命令高级篇( SetUID与SetGID标识位)
对此可以参照《setuid()与setgid()的使用 (下)》中的实例3
 
使用 stuid() 函数降权限
开 始时,某个程序需要 root 权限完成一些工作,但后续的工作不需要 root 权限。可以将该可执行程序文件设置 set_uid 位,并使得该文件的属主为 root。这样,普通用户执行这个程序时,进程就具有了 root 权限,当不再需要 root 权限时,调用 setuid(  ) 恢复进程的实际用户 ID 和有效用户 ID 为执行该程序的普通用户的 ID 。对于一些提供网络服务的程序,这样做是非常有必要的,否则就可能被攻击者利用,使攻击者控制整个系统。
 
对于设置了 set_uid 位的可执行程序也要注意,尤其是对那些属主是 root 的更要注意。因为 Linux 系统中 root 用户拥有最高权力。黑客们往往喜欢寻找设置了 set_uid 位的可执行程序的漏洞。这样的程序如果存在缓冲区溢出漏洞,并且该程序是一个网络程序,那么黑客就可以从远程的地方轻松地利用该漏洞获得运行该漏洞程序的 主机的 root 权限。即使这样的成不是网络程序,那么也可以使本机上的恶意普通用户提升为 root 权限。
结束!