[英]How can I find out the original username a process was started with?
There is a perl script that needs to run as root but we must make sure the user who runs the script did not log-in originally as user 'foo' as it will be removed during the script. 有一个perl脚本需要以root身份运行,但我们必须确保运行该脚本的用户最初不以用户'foo'登录,因为它将在脚本中被删除。
So how can I find out if the user, who might have su-ed several times since she logged in has not impersonated 'foo' at any time in that chain? 那么我如何才能知道自登录以来可能多次上过几次的用户是否在该链中的任何时候都没有冒充'foo'?
I found an interesting perl script that was calling the following two shell scripts, but I think that would only work on Solaris. 我发现了一个有趣的perl脚本,它调用了以下两个shell脚本,但我认为这只适用于Solaris。
my $shell_parent =
`ps -ef | grep -v grep | awk \'{print \$2\" \"\$3}\' | egrep \"^@_\" | awk \'{print \$2}'`;
my $parent_owner =
`ps -ef | grep -v grep | awk \'{print \$1\" \"\$2}\' | grep @_ | awk \'{print \$1}\'`;
This needs to work on both Linux and Solaris and I'd rather eliminate the repeated calls to he the shell and keep the whole thing in Perl. 这需要在Linux和Solaris上工作,我宁愿消除对shell的重复调用,并将整个事情保留在Perl中。
Quick and dirty and (UNIX only): 快速和脏和(仅限UNIX):
my $user = (split /\s/,`who am i`)[0];
The who am i
command returns the owner of the TTY - ie who you were when you logged in. who am i
命令返回TTY的所有者 - 即您登录时的身份。
If you want to do this in pure perl: 如果你想在纯perl中这样做:
use POSIX;
my $tty = POSIX::ttyname(1); # The tty we are running in
my $uid = (stat $tty)[4]; # The owner uid of that tty
my $user = getpwuid($uid); # The user with that uid
This will return the correct user, even after multiple su's. 这将返回正确的用户,即使在多个su之后。 This usually freaks out your (less experienced) sysadmins. 这通常吓坏了你(经验较少)的系统管理员。
I recognized a corner case when calling scripts from mc (at least in our RHEL's), which results that the who am i
does not output anything. 我从mc调用脚本时认识到了一个极端情况(至少在我们的RHEL中),这导致who am i
是who am i
没有输出任何东西。 To circumvent that, I produced the following one-liner in bash: 为了避免这种情况,我在bash中制作了以下单行:
REALUSERNAME=$(ps uhp `ps -AjH | grep \`ps -u $USER fh | awk '{ print $0; if(index($0, "ps -u $USER fh")) exit 0;}' | tac | awk '{if(!index($0, "\\\\\_")){print $1; exit 0;}}'\` | awk '{print $3}'` | awk '{print $1}')
Essentially, this walks backwards on the tree output of ps -u $USER fh
and then crops on the topmost username column. 从本质上讲,这会在ps -u $USER fh
的树输出上向后移动,然后在最顶端的ps -u $USER fh
上裁剪。
Thoughts, better solutions are welcome :-) 想法,更好的解决方案是受欢迎的:-)
Here's a Perl program that checks for direct setuid change: 这是一个检查直接setuid更改的Perl程序:
#! /usr/bin/perl sub callingUser() { my ($login, $pass, $uid, $gid) = getpwuid($<); return $login; } sub effectiveUser() { my ($login, $pass, $uid, $gid) = getpwuid($>); return $login; } printf("Real user name: %s\n", effectiveUser()); printf("Calling user name: %s\n", callingUser());
But since you mentioned that the setuid change may have occured anytime before, you probably have to parse the output of ps
: I would do it using the following command. 但是既然你提到setuid更改可能在之前的任何时候发生过,你可能需要解析ps
的输出:我会使用以下命令来完成它。 This command only uses features defined in POSIX , so I hope it is portable to all kinds of systems: 此命令仅使用POSIX中定义的功能,因此我希望它可以移植到各种系统:
ps -e -o pid,ppid,user,ruser
Maybe the following is what you want. 也许以下是你想要的。 The function hasBeenUser
reads the process table and then follows the process chain from the current process down the parent process. 函数hasBeenUser
读取进程表,然后从当前进程沿着父进程跟随进程链。 If any of the processes on the way has a user
or real user
field equal to the username in question, the function returns a nonzero value. 如果路上的任何进程的user
或real user
字段等于相关用户名,则该函数返回非零值。
#! /usr/bin/perl sub hasBeenUser($) { my ($username) = @_; my $procs = {}; open(PS, "ps -e -o pid,ppid,user,ruser |") or die; while (defined(my $line = <PS>)) { next unless $line =~ m"^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+$"; my ($pid, $ppid, $user, $ruser) = (int($1), int($2), $3, $4); $procs->{$pid} = [$pid, $ppid, $user, $ruser]; } close(PS) or die; my $pid = $$; while (exists($procs->{$pid})) { my $proc = $procs->{$pid}; delete $procs->{$pid}; # don't risk ending in an endless loop. warn "D: checking process $pid\n"; if ($proc->[2] eq $username || $proc[3] eq $username) { warn "E: process $pid was called by $username.\n"; return 1; } last if $pid < 2; $pid = $proc->[1]; } return 0; } hasBeenUser("del"); # should return 0 hasBeenUser("root"); # should return nonzero
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.