程序可以告诉它正在sudo下运行吗?


27

我有一个程序,如果在“ sudo”下运行,其行为应有所不同。有没有办法找出它是否在sudo下运行?

更新:有人问我为什么要这样做。在这种情况下,在使用MacPorts的Mac上,输出将告诉您剪切并粘贴特定命令。如果MacPorts命令以“ sudo”运行,则在示例命令中应包含sudo:

$ sudo port selfupdate 
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.2.1 installed,
MacPorts base version 2.2.1 downloaded.
--->  Updating the ports tree
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

^^^^^^^^^ it would be really sweet if it output "sudo port upgrade outdated" instead.  It would be even better if it just did it for you :-)

我很好奇:您能解释一下它应该如何表现吗?
sciurus 2014年

1
@sciurus通常的常见用例是在需要root特权的安装脚本中;如果没有它们,它们会立即死亡。
尼克T


我隐约记得某些命令知道它是否以root用户身份运行...我认为答案是“是”
Rolf 2014年

Answers:


48

是的,当程序在sudo下运行时,设置了4个环境变量:

$ sudo env |grep SUDO
SUDO_COMMAND=/usr/bin/env
SUDO_USER=tal
SUDO_UID=501
SUDO_GID=20

请注意,只需设置它们就可以伪造它们。不要因为任何重要的事情而信任他们。

例如:在此程序中,我们需要告诉用户运行其他程序。如果当前的一个是使用sudo运行的,那么另一个也可以。

#!/bin/bash

echo 'Thank you for running me.'

if [[ $(id -u) == 0 ]]; then
  if [[ -z "$SUDO_COMMAND" ]]; then
    echo 'Please now run: next_command'
  else
    echo 'Please now run: sudo next_command'
  fi
else  echo 'Error: Sadly you need to run me as root.'
  exit 1
fi

请注意,只有先证明SUDO_ *变量以root用户身份运行,它才测试SUDO_ *变量。即使这样,它也仅使用它来更改一些有用的文本。


2
我将用于“任何重要的事情”吗?
凯文-恢复莫妮卡2014年

3
@Kevin如果有人破坏自己的环境以伪装成高特权的人,那么他们希望知道自己在做什么,并会接受后果。
尼克T

被否决的原因是,任何必须由“不信任他们的关键任务”限定的答案根本不是答案,而是丑陋的破解。
斯蒂芬C,

这是对所提问题的完全可接受的答案。对于可能试图阻止使用sudo而不是仅仅检测到 sudo的人们,警告必须存在。应该使用sudo的命令别名来进行预防,以限制用户可以运行的命令。
dwurf

11

这不能直接回答问题,但我认为这里没有提出正确的问题。在我看来,问问者是否想要一个程序,如果它具有一定的权限,则可能会有所不同,但是我认为检查sudo并不是这样做的方法。首先,许多系统可能未实现“ sudo”,但在Linux或许多Unix上却根本不需要。

例如,用户可能已经以root用户身份登录,从而使sudo变得毫无意义,或者系统可能具有非root用户,这些非root用户仍然具有执行程序可能希望执行的管理任务的能力。最后,也许该系统根本没有root或sudo,而是使用具有不同功能的强制访问控制系统,并且没有捕获所有超级用户以使用sudo。否则,用户可能会感到受宠若惊,但出于安全原因,该帐户的权限比其自己帐户的权限少(我经常与一个临时非特权用户一起运行不受信任的代码,该用户只能写入ramdisk才能删除,而不提高我的权限)。总体而言,假设像sudo这样的特定权限模型或root的存在,或者假设sudoed用户具有任何特定特权,都是一个坏主意。

如果要确定您是否有权执行某项操作,最好的方法通常是简单地尝试执行该操作,然后检查errno是否存在权限问题,或者它是否为必须全部失败或全部成功的多阶段操作?您可以检查某项操作是否可以使用POSIX 访问功能之类的功能(如果正在积极更改权限,请注意此处可能出现的竞争条件)

如果您还需要了解sudo背后的真实用户,则可以使用getlogin函数,该函数适用于与基础终端的任何交互式会话,并允许例如查找谁“真正”运行了审计命令或找到了该用户。实际用户的主目录,用于保存日志。

最后,如果您真正想要的是找出用户是否具有root用户访问权限(仍然是一个坏主意,但具体实现较少),则可以使用getuid来检查uid为0并因此为root。


7

可以使用两种机制。

  • 可以通过两种方法伪造检查环境变量的方法,但这是最简单的方法。 growisofs我不喜欢在SUDO下运行,因此我在使用脚本的脚本中未设置SUDO变量。可以用其他方式伪造。(SUDO变量也被带到环境中,以便在at和batch命令下运行的脚本。)
  • 查看您是否在sudo下运行的另一种方法是从父进程中查找进程列表,以查找sudo。很难以这种方式隐藏您在sudo下运行,但是更加复杂。仍然有可能假冒您在sudo下运行。

检查您是否以适当的用户身份运行更为常见。该id命令可用于执行此操作。TomOnTime的脚本使用该id命令来确定是否sudo可能需要运行下一个命令。


1
>很难掩盖您是在sudo下运行的,难道您不可以简单地将sudo二进制文件重命名为其他名称吗?还是命名其他可执行文件sudo来伪造相反的东西?并不是说我真的希望有人理智地做到这一点……
Bob

@Bob您需要root访问权限才能重命名sudo可执行文件。普通用户将无法执行此操作。我确实注意到,您可以伪造自己正在运行的软件sudo。重命名现有程序将起作用。专用的伪造sudo程序所需的代码很简单。
BillThor

您可以从某处下载sudo二进制文件并给予正确的权限...
Jens Timmerman 2014年

@JensTimmerman您需要root用户访问权才能授予它正确的权限。如果您可以重命名或硬链接。无需下载。如果将SUID安装到目标用户ID(如果可以那样工作),则必须已经破坏了目标用户ID。
BillThor

啊,对了,它拒绝没有setuid的情况下工作,我不好...
Jens Timmerman 2014年

2

您可以比较有效用户ID和实际用户ID。

这并不严格意味着它正在运行undo sudo(也可以设置为uid),而是表明该程序具有比用户预期更多的权限。(例如,在通常没有此类权限的情况下执行的程序,但需要在安装过程中与它们一起运行或安装更新。然后,您可以使用此程序提供有关此权限的一些警告反馈)。


2
不,sudo同时设置有效和真实ID。与suid相反,后者没有。这是一个简单的C程序,您可以使用它进行测试(对不起,该注释将删除换行符,您必须将其重新添加):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
derobert 2014年

......或者,perl -E 'say $<, "\n", $>'
derobert

2

您可以检查有效的UID(EUID)变量,如下所示:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi

这不能回答问题。以root身份运行时,该代码提供与以sudo运行时相同的输出。
斯蒂芬·C

@StephenC-我认为对于OP而言,没有区别。恕我直言,他们的目标是识别sudo执行或从真实的root shell执行而没有区别。
伊莱兰·马尔卡

1
我认为您可能是对的。我之所以来到这里,是因为我不明白为什么要sudo echo $USER打印非特权用户名(该变量在sudo之前被替换)。我实际上最终在脚本中使用了您的代码。谢谢!
斯蒂芬C,

最受欢迎的:)
Eliran Malka

-1

您可以在其中触摸文件/root,然后再触摸if -e它。并且,如果-e为true,rm(检查错误代码)它将使您的测试下一次生效。

在rm之后检查错误代码(或返回代码)可防止某人轻易地使用sudo权限来创建该文件以对您进行恶作剧。


4
此答案检查进程是否具有写入权限/root(不一定与以UID 0运行的权限相同),但不检查进程是否使用获得了这些权限sudo
Ladadadada 2014年

是的,“千种为猫皮的方法”;当我写下答案时,我想到了另外4或5件事,所以我把它包装了起来。
克里斯K

-2

我发现这很适合

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]

当我在FreeBSD,Centos7或MacOS X上尝试时,这不起作用。我认为您的意思是“ / proc”而不是“ / etc”。但是即使进行了更改,它也不适用于这三个功能。sudo重置“ $ USER”。您是说$ SUDO_USER吗?另外,您的意思是“ [[”而不是“ [”吗?
TomOnTime 2015年

1
我固定了例子。基本上检查loginuid不等于0,但是用户是root。
ruckc '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.