我目前处于一种需要通常可以以root用户身份运行的命令由非root用户身份运行的情况。
命令如下。
UserAccs=`awk -F: '$1 !~ /^[[:space:]]*#/ && $3>=500 && $3!=65534 {print $1}' /etc/passwd 2>/dev/null`
for Acc in $UserAccs; do
awk -F: '$1 ~ /^[[:space:]]*'$Acc'$/ && $2!~/[!*]+/ {print Acc":PASS_MIN_DAYS="$4, "PASS_MAX_DAYS="$5, "PASS_WARN_AGE="$6, "INACTIVE="$7}' Acc=$Acc /etc/shadow 2>/dev/null
done
预期结果应为:
Novatech:PASS_MIN_DAYS=0 PASS_MAX_DAYS=99999 PASS_WARN_AGE=7 INACTIVE=
但是作为非root用户,我什么也没得到:
$ UserAccs=`awk -F: '$1 !~ /^[[:space:]]*#/ && $3>=500 && $3!=65534 {print $1}' /etc/passwd 2>/dev/null`
$ for Acc in $UserAccs; do
> awk -F: '$1 ~ /^[[:space:]]*'$Acc'$/ && $2!~/[!*]+/ {print Acc":PASS_MIN_DAYS="$4, "PASS_MAX_DAYS="$5, "PASS_WARN_AGE="$6, "INACTIVE="$7}' Acc=$Acc /etc/shadow 2>/dev/null
> done
$
但是,如果我进入su模式,则可以再次运行命令。
问题是2折:
使用的嵌入式Linux版本:4.4.36-rt43-yocto-preempt-rt
答案 0 :(得分:1)
最简单的方法是用C语言编写包装器:编译完成后,您可以将setuid位置1,以使其以root身份运行。
要将您的shell脚本转换为C文字,可以执行以下操作:
#!/usr/bin/env bash
script=$(cat <<'EOF'
while read -r Acc; do
awk -v Acc="$Acc" -F: '$1 = Acc && $2!~/[!*]+/ {print Acc":PASS_MIN_DAYS="$4, "PASS_MAX_DAYS="$5, "PASS_WARN_AGE="$6, "INACTIVE="$7}' Acc=$Acc /etc/shadow
done < <(awk -F: '$1 !~ /^[[:space:]]*#/ && $3>=500 && $3!=65534 {print $1}' /etc/passwd)
EOF
)
script_c=$script
script_c=${script_c//$'\\'/'\\'}
script_c=${script_c//$'\n'/'\n'}
script_c=${script_c//$'\"'/'\"'}
printf '"%s"\n' "$script_c"
...将生成以下内容作为输出:
"while read -r Acc; do\n awk -v Acc=\"$Acc\" -F: '$1 = Acc && $2!~/[!*]+/ {print Acc\":PASS_MIN_DAYS=\"$4, \"PASS_MAX_DAYS=\"$5, \"PASS_WARN_AGE=\"$6, \"INACTIVE=\"$7}' Acc=$Acc /etc/shadow\ndone < <(awk -F: '$1 !~ /^[[:space:]]*#/ && $3>=500 && $3!=65534 {print $1}' /etc/passwd)"
因此,让我们用它来构建一个C程序:
/* the below assumes this is saved as check_password_expirations.c */
#include <unistd.h>
const char *interpreter = "/bin/bash";
const char *script_argv[] = { "/bash", "-c", "while read -r Acc; do\n awk -v Acc=\"$Acc\" -F: '$1 = Acc && $2!~/[!*]+/ {print Acc\":PASS_MIN_DAYS=\"$4, \"PASS_MAX_DAYS=\"$5, \"PASS_WARN_AGE=\"$6, \"INACTIVE=\"$7}' Acc=$Acc /etc/shadow\ndone < <(awk -F: '$1 !~ /^[[:space:]]*#/ && $3>=500 && $3!=65534 {print $1}' /etc/passwd)", NULL };
const char *minimal_env[] = { "PATH=/bin:/usr/bin", NULL };
int main(void) {
execve(interpreter, script_argv, minimal_env);
return 1; /* if this is reached, we failed. */
}
要确保C程序在每次调用时均以root特权运行,您可以将其冠以root身份并启用setuid位。
在下面的抄本中,dev
应该是您安装Yocto Application Development Toolkit的工作站,而emb
应该是您的嵌入式系统。
user@dev$ arm-poky-linux-gnueabi-gcc -o check-password-expirations check_password_expirations.c
user@dev$ scp check-password-expirations your-embedded-host:
user@dev$ ssh user@your-embedded-host
user@emb$ su -
root@emb# mv ~user/check-password-expirations /usr/local/bin
root@emb# chown root:root /usr/local/bin/check-password-expirations
root@emb# chmod u+s /usr/local/bin/check-password-expirations
此后,check-password-expirations
在/usr/local/bin
上从emb
调用时本身将始终以root用户身份运行。
答案 1 :(得分:0)
您不想授予非root用户访问/etc/shadow
的权限。
当您确实定期需要此类信息并征得您的管理员的同意时,您可以考虑使用root cron作业,它将所需的数据(不是加密的密码)公开给另一个文件,该文件只能由某些特殊组的用户读取。
答案 2 :(得分:0)
如果这是您需要定期执行的操作,则用完root的crontab。如果您或管理员需要执行一两次以上操作,则将其放入脚本中,然后运行sudo script
。如果是一次性的,那么问题是/etc/shadow
必须不是世界可读的。在循环中,将awk ...
更改为sudo awk...
,或者最好将sudo cat /etc/shadow | awk ...
更改为