プログラムは、それが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 14年

1
通常、@ sciurusは、root権限を必要とするインストールスクリプトによく使用されます。持っていないならすぐに死にます
ニックT 14年

3
これはmeta.stackexchange.com/questions/66377/what-is-the-xy-problem/…のように聞こえます。それはあなたがどのようなものです、本当にやりたいですか?
ジェニーDは、モニカの復職14年

ルートとして実行されているかどうかを認識しているコマンドを漠然と覚えています。答えは「はい」だと思います
ロルフ14年

回答:


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_ *変数をテストすることに注意してください。それでも、いくつかの有用なテキストを変更するためにのみ使用します。


2
「重要なもの」には何を使用しますか?
ケビン-モニカーを復活14年

3
@Kevin誰かが自分の環境にねじ込んで、高い特権で偽装する場合、彼らは自分たちが何をしているかを知り、その結果を受け入れることを願っています。
ニックT 14年

「重要なことについて信用してはいけない」という条件を満たさなければならない答えは、まったく答えではなく、いハックだからです。
スティーブンC

これは、尋ねられた質問に対する完全に受け入れられる答えです。警告は、sudoを検出するだけでなく、sudoの使用を阻止しようとする可能性のある人々のために存在する必要があります。ユーザーが実行できるコマンドを制限するには、sudoのコマンドエイリアスを使用して防止する必要があります。
dwurf

11

これは質問に直接答えませんが、ここで正しい質問がされているとは思いません。私には、特定の許可があるかどうかによっておそらく異なる動作をするプログラムが求められているように見えますが、sudoをチェックすることはその方法ではないと主張します。第一に、多くのシステムは「sudo」を実装していない可能性がありますが、Linuxや多くのUnixでは決して必要ではありません。

たとえば、ユーザーはすでにルートとしてログインしており、sudoを無意味にしたり、システムに、プログラムが実行したい管理タスクを実行する機能をまだ持っている非ルートユーザーがいる場合があります。最後に、おそらくシステムにはルートやsudoがまったくなく、代わりに、異なる機能を備えた必須のアクセス制御システムを使用し、sudoのすべてのスーパーユーザーをキャッチしません。または、ユーザーをsudoすることができますが、セキュリティ上の理由から自分のアカウントよりも権限が少ないアカウントになります(私はしばしば、権限を引き上げるのではなく、ドロップするためにramdisksにのみ書き込むことができる一時的な権限のないユーザーで信頼できないコードを実行します)。sudoやrootの存在などの特定の権限モデルを想定したり、sudoされたユーザーが特定の特権を持っていると想定したりすることは、全体的に悪い考えです。

操作を実行する権限があるかどうかを確認したい場合、通常は単に試行してから、失敗した場合、またはすべてが失敗またはすべて成功する必要があるマルチステージ操作である場合、errnoで権限の問題を確認しますPOSIX アクセス関数などの関数で操作が機能するかどうかを確認できます(アクセス許可がアクティブに変更されている場合、ここで競合状態に注意してください)

さらに、sudoの背後にある実際のユーザーを知る必要がある場合は、getlogin関数を使用できます。この関数は、基になる端末との対話セッションで機能し、たとえば、監査のためにコマンドを「本当に」実行しているユーザーを見つけたり、ログを保存する実際のユーザーのホームディレクトリ。

最後に、本当に必要なのがユーザーにルートアクセス権があるかどうかを調べること(まだ悪い考えですが、実装固有ではありません)の場合、getuidを使用して0のuid(つまりroot )を確認できます。


7

使用できるメカニズムは2つあります。

  • 環境変数の確認はどちらの方法でも偽装できますが、最も簡単です。 growisofsSUDOの下で実行するのは好きではないので、使用するスクリプトでSUDO変数の設定を解除します。他の方法で偽造することができます。(SUDO変数は、atおよびbatchコマンドで実行されるスクリプトの環境にも持ち込まれます。)
  • sudoで実行しているかどうかを確認する別の方法は、親プロセスからsudoを探してプロセスリストを調べることです。この方法でsudoで実行していることを隠すことは困難ですが、より複雑です。sudoで実行していることを偽装することは依然として可能です。

適切なユーザーとして実行しているかどうかを確認する方が一般的です。このidコマンドを使用してこれを行うことができます。TomOnTimeのスクリプトはこのidコマンドを使用してsudo、次のコマンドの実行に必要かどうかを判断します。


1
>このようにsudoで実行していることを隠すのは難しいでしょう。単にsudoバイナリを別の名前に変更することはできませんか?または、他の実行可能ファイルsudoに名前を付けて、反対のものを偽造しますか?私は本当に誰のSANEはそれを行うことを期待したいではないことを...
ボブ

@Bob 実行可能ファイルのroot名前を変更するにはアクセスが必要ですsudo。通常のユーザーはこれを行うことができません。私はあなたがあなたの下で動いていることを偽造できることに注意しましたsudo。既存のプログラムの名前を変更すると機能します。専用の偽sudoプログラムに必要なコードは簡単です。
BillThor

あなただけのどこからsudoのバイナリをダウンロードし、それを右の権限を与えることができます...
イェンスTimmerman

@JensTimmerman適切な権限を付与するには、rootアクセスが必要です。名前を変更するか、ハードリンクすることができる場合。ダウンロードする必要はありません。ターゲットユーザーIDにSUIDをインストールする場合(そのように機能する場合)、ターゲットユーザーIDを既に侵害している必要があります。
BillThor

ああ、右、それは...、setuidさせずに仕事に私の悪いを拒否
イェンスTimmerman

2

有効なユーザーIDと実際のユーザーIDを比較できます。

これは、sudoを元に戻す(setuidすることもできる)ことを厳密に意味するものではありませんが、ユーザーが予想する以上の権限がプログラムにあることを示しています。(たとえば、通常はそのような権限なしで実行されますが、インストール中または更新のインストール中に実行する必要があるプログラムで使用します。その後、これについて警告フィードバックを行うことができます)。


2
いいえ、sudo有効なIDと実際の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

...または、代わりにperl -E 'say $<, "\n", $>'
デロバート14年

2

次のように、実効UID(EUID)変数を確認できます。

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

これは質問に答えません。このコードは、sudoとして実行される場合と同じように、rootとして実行される場合と同じ出力を提供します。
スティーブンC

@StephenC-OPの目的上、違いはないと思います。私見の目的は、sudoの実行または本物のルートシェルからの実行を区別なく識別することです。
エリランマルカ

1
あなたは正しいと思う。ここに来たのは、なぜsudo echo $USER特権のないユーザー名を出力するのか理解できなかったからです(変数はsudoの前に置き換えられます)。実際、スクリプトであなたのコードを使用することになりました。ありがとうございました!
スティーブンC

最も歓迎:)
エリランマルカ

-1

あなたには、ファイルに触れることができ/root、その後、if -eそれ。-eがtrueの場合rm(エラーコードをチェック)、次回テストが機能するようにします。

rmによって誰かがsudo powersを使用してファイルを作成し、いたずらをするのを簡単に防ぐことができなくなったら、エラーコード(またはリターンコード)を確認します。


4
この回答は、プロセスに書き込み許可があるかどうかを確認します/root(UID 0として実行する場合と同じである必要はありません)が、を使用してそれらの許可を取得したかどうかは確認しませんsudo
ラダダダダ14年

はい、「猫の皮を剥ぐ千の方法」; 答えを書いたときに、さらに4つまたは5つのことを考えたので、まとめました。
クリスK 14年

-2

これでうまくいくことがわかりました

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

これは、FreeBSD、Centos7、またはMacOS Xで試してみても機能しません。「/ etc」ではなく「/ proc」を意味すると思います。しかし、その変更があっても、これら3つのいずれでも機能しません。「$ USER」はsudoによってリセットされます。$ SUDO_USERのことですか?また、「[」ではなく「[[」という意味ですか?
TomOnTime

1
私は例を修正しました。基本的に、loginuidの確認は0ではありませんが、ユーザーはrootです。
ruckc
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.