运行读取/ etc / shadow的脚本,而无需以root用户身份登录

时间:2018-07-06 17:38:37

标签: shell command-line syntax

我目前处于一种需要通常可以以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折:

  1. 有没有一种方法可以在嵌入式Linux中以非root用户格式运行上述命令?
  2. 如果是这样-有更好的方法吗?如果不是,那么是否需要输入su命令才能运行该命令?

使用的嵌入式Linux版本:4.4.36-rt43-yocto-preempt-rt

3 个答案:

答案 0 :(得分:1)

最简单的方法是用C语言编写包装器:编译完成后,您可以将setuid位置1,以使其以root身份运行。


将Shell脚本嵌入C字符串中

要将您的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中调用该脚本来编写

因此,让我们用它来构建一个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 ...更改为