在Linux系统中,为了系统安全,通常程序不会直接以root用户运行,而是以它所需要的最小权限的用户运行。但是程序中有部分代码,却必须要root权限运行,此时,就必须在程序中进行提权操作,暂时将权限提升至root权限。执行完对应代码后,降回原来权限。这样,既能保证程序功能正常,也能保证系统安全。
此文介绍通过sudo的方式来提升程序权限。

sudo

sudo是Linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具。简单来说,就是普通用户可以通过sudo执行root用户才能执行的操作(前提是root用户在sudo配置文件中,配置了对应Alias)。

sudo配置

Linux系统中,将需要切换到root身份下的用户及其能执行的操作等相关信息,存储在/etc/sudoers中。需要注意,配置sudo需要在root用户下进行。一般将/etc/sudoers的语句称为AliasAlias主要分为4种:

1)Host_Alias:即允许的主机名列表,如:Host_Alias HOST_FLAG=hostname1,hostname2,hostname3,表示只能在运行的主机上进行sudo操作。
2)Cmnd_Alias:即允许执行的命令列表,命令前加!表示不允许执行此命令。如:Cmnd_Alias COMMAND_FLAG=command1,command2,!command3,表示可以通过sudo执行command1,command2,不可以执行command3。
3) User_Alias:即拥有sudo权限的用户列表。如:User_Alias USER_FLAG=user1,user2,user3。
4)Runas_Alias:即用户已什么身份执行的列表。如:Runas_Alias RUNAS_FLAG=operator1,operator2,operator3。

配置格式为:
USER_FLAG HOST_FLAG=(RUNAS_FLAG) COMMAND_FLAG

如下图,则表示 operator用户可以通过sudo指令,以root身份,执行reboot和cat指令。

root ALL=(ALL) ALL
Cmnd_Alias COMMAND_FLAG=/sbin/reboot,/bin/cat
operator ALL=(root)NOPASSWD:COMMAND_FLAG

场景应用

如下,我们在root用户中,创建文件helloWorld.txt,并将其文件权限设置为400,即只有root用户才能查看文件内容。

root@tz:/tmp# echo "hello world !" > helloWorld.txt
root@tz:/tmp# chmod 0400 helloWorld.txt
root@tz:/tmp# cat helloWorld.txt
hello world !
root@tz:/tmp#

其他用户(以operator为例)尝试查看文件内容,提示权限不允许。

@tz:/tmp$ ls -l helloWorld.txt
-r--------    1 0        0               14 Dec 26 15:54 helloWorld.txt
@tz:/tmp$ echo ${USER}
operator
@tz:/tmp$ cat helloWorld.txt
cat: can't open 'helloWorld.txt': Permission denied
@tz:/tmp$

此时,我们在/etc/sudoers下配置如下Alias,使operator能通过sudo执行cat指令。

root ALL=(ALL) ALL
Cmnd_Alias COMMAND_FLAG=/bin/cat
operator ALL=(root) NOPASSWD:COMMAND_FLAG

再切换到operator用户,执行sudo cat helloWorld.txt,执行结果为

@tz:/tmp$ ls -l helloWorld.txt
-r--------    1 0        0               14 Dec 26 16:04 helloWorld.txt
@tz:/tmp$ sudo cat helloWorld.txt
hello world !
@tz:/tmp$

说明配置生效了。将Cmnd_Alias添加 !/bin/chmod,让operator不能执行/bin/chmod指令。再分别执行如下shell脚本。

#!/bin/sh

name=$(echo ${USER})

echo "I am $name"

ls -l /tmp/helloWorld.txt

sudo cat /tmp/helloWorld.txt

sudo chmod 777 /tmp/helloWorld.txt

ls -l /tmp/helloWorld.txt

root用户下的执行结果如下图,可以看到,cat执行成功,chmod也执行成功,文件的权限被改成了777。

root@tz:/tmp# /tmp/test.sh
I am root
-r--------    1 root     root            14 Dec 26 16:04 /tmp/helloWorld.txt
hello world !
-rwxrwxrwx    1 root     root            14 Dec 26 16:04 /tmp/helloWorld.txt
root@tz:/tmp#

operator用户的执行结果如下,cat执行成功,chmod执行时报错,提示不被允许执行chmod,文件权限仍为400。

@tz:/tmp$ /tmp/test.sh
I am operator
-r--------    1 0        0               14 Dec 26 16:04 /tmp/helloWorld.txt
hello world !
Sorry, user operator is not allowed to execute '/bin/chmod 777 /tmp/helloWorld.txt' as root on tz.
-r--------    1 0        0               14 Dec 26 16:04 /tmp/helloWorld.txt
@tz:/tmp$

除了shell脚本中,C语言程序中,也可通过sudo暂时提升权限。如下程序,通过execve执行cat /tmp/helloWorld.txt。

int main(void)
{
    char *argv[] = {"/bin/cat", "/tmp/helloWorld.txt", NULL};
    char *envp[] = {0, NULL};

    execve("/bin/cat", argv, envp);

    return 0;
}

root用户的执行结果如下,能正常获取helloWorld.txt文件内容。

root@tz:/tmp# ls -l helloWorld.txt
-r--------    1 root     root            14 Dec 26 16:04 helloWorld.txt
root@tz:/tmp# /tmp/cwmpd
hello world !
root@tz:/tmp#

operator用户下,执行结果表明用户权限不允许。

@tz:/tmp$ ls -l helloWorld.txt
-r--------    1 0        0               14 Dec 26 16:04 helloWorld.txt
@tz:/tmp$ /tmp/cwmpd
cat: can't open '/tmp/helloWorld.txt': Permission denied
@tz:/tmp$

更改程序,使用sudo执行cat /tmp/helloWorld.txt,代码如下:

int main(void)
{
    char *argv[] = {"sudo", "/bin/cat", "/tmp/helloWorld.txt", NULL};
    char *envp[] = {0, NULL};

    execve("/usr/bin/sudo", argv, envp);

    return 0;
}

operator用户执行结果如下,能正常获取文件内容。

@tz:/tmp$ ls -l helloWorld.txt
-r--------    1 0        0               14 Dec 26 16:04 helloWorld.txt
@tz:/tmp$ /tmp/cwmpd
hello world !
@tz:/tmp$

作为对比,使用sudo执行chmod的执行结果如下。

int main(void)
{
    char *argv[] = {"sudo", "/bin/chmod", "777", "/tmp/helloWorld.txt", NULL};
    char *envp[] = {0, NULL};

    execve("/usr/bin/sudo", argv, envp);

    return 0;
}
@tz:/tmp$ ls -l helloWorld.txt
-r--------    1 0        0               14 Dec 26 16:04 helloWorld.txt
@tz:/tmp$ /tmp/cwmpd
Sorry, user operator is not allowed to execute '/bin/chmod 777 /tmp/helloWorld.txt' as root on tz.
@tz:/tmp$

执行结果与shell脚本一致,表明sudo配置生效。并且能在shell脚本中和C程序中,通过sudo提升执行权限。