ドロッププロセス権限


12

ルートとして実行されているデーモンによって開始されるプロセスがありますが、このプロセスの特権を平均的なユーザーの特権に「ダウングレード」したいと考えています。これは可能ですか?はいの場合はどうですか?

PS:MacでUNIXを実行する

回答:


5

プロセス自体がsetuid(2)を呼び出す必要があります。まだ実行していない場合は、chroot(8)内で実行することも検討する必要があります。私の知る限り、rootが別のプロセスのuidを変更する方法はありません。

ルートとして実行している理由がポートのバインドである場合は、通常のユーザーとして上位ポートで実行し、OS Xでipfw(8)を使用してポート80/443 / etcを上位ポートに転送することをお勧めします。

http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx


rootとして実行するプログラムにsetuid(uid)を入れましたが、通常のユーザーとして実行する必要がありますが、何も起こりません。つまり、rootとして実行し続けます
Samantha Catania '23

おそらくそれからエラーをキャッチする必要があります(おそらくuidのEINVALを取得しています)。その可能性の低いsetuidがマシンで壊れている場合は、Apacheが_wwwとして実行されているかどうかを確認することで確認できます。プログラマーのドキュメント:developer.apple.com/library/mac/#documentation/Darwin/Reference/...
多項式

それは正しいですが、それはuidから構文エラーを与えます。これは正しい形式のsetuid(500)ですか?
サマンサカターニア

問題を見つけました:system()を介してコマンドを実行しようとしましたが、コマンドを実行して問題を解決しました。thx for the help
Samantha Catania

いいえ、これは良いアドバイスsetuid()ではありません。一人で電話するだけでは十分ではありません。
ニコラスウィルソン

13

sudo tcpdump -Z initgroups(3)、setgid(2)、setuid(2)を使用して、自身のプロセスのルート特権を削除します。

# code taken from: 
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c

/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
            if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
               setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
                    fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
                        username, 
                        (unsigned long)pw->pw_uid,
                        (unsigned long)pw->pw_gid,
                        pcap_strerror(errno));
                    exit(1);
            }
...
}

2
正しい。initgroupssetgidsetuid(最後!)は、UNIX上で正確に右のパラダイムである、と常に従うべきです。さらに、責任のある「droproot」関数は、3つの主要な関数すべてが成功を返したとしても、そのuidとgidが実際に設定されていることを確認します。
ニコラスウィルソン

3

以下を使用して、他のユーザーとしてコマンドを実行できますsu

 su USERNAME -c COMMAND

COMMANDドロップされた権限で実行されUSERます。


デフォルトでsuは、ターゲットユーザーのシェルインタープリターを使用してコマンドを実行することに注意してください。対照的に、のデフォルトの動作でsudoCOMMAND、をスタンドアロンプ​​ログラムとして扱い、現在の環境で実行されます。もちろん、これらのデフォルトの動作は、さまざまなスイッチと環境変数で変更できます。


以下のように見えるがsuUSERNAMEが定義されたシェルを持っていない(または場合は動作しません/bin/false)sudoが作業を行うのに対し。
2013年

1
@Aifユーザーが対話型コマンドの実行を許可されていない場合、デフォルトの動作suはそれを反映します。ただし、いつでも-sスイッチを使用してオーバーライドできます。の目的はsu、特定のユーザーの動作を模倣することであることに注意してください。これは通常、シェルの影響を受けます。対照的に、sudo(デフォルトでは)ターゲットユーザーのシェル設定を無視します。
rozcietrzewiacz 2013年

いいえ、特権を落とすためだけにシェルを使用して実行しないでください。それは攻撃者の制御にあまりに多くを残し、あなたが触れたくないさまざまな設定ファイルを読み込みます。
ニコラスウィルソン

2

特権をドロップするには、ドロップする非rootユーザーが必要です。次に、そのユーザーに切り替えるだけです。

#define UNPRIV_UID  48
#define UNPRIV_GID  48

if (getuid() == 0) { // we are root
    // setting UID/GID requires root privileges, so if you don't set
    // the GID first, you won't be able to do it at all.
    if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
    if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}

ASSERT(getuid() != 0); 

これは、ラッパースクリプトではなく、プログラム自体ので行われることに注意してください。多くのプログラムは、特定の目的(たとえば、小さい番号のポートにバインドする)のためにroot権限を必要としますが、その後はrootを必要としません。したがって、これらのプログラムはrootとして起動しますが、不要になると特権を削除します。

root権限がまったく必要ない場合は、rootとして実行しないでください。例えば:

# Change this:
myprog -C /my/config/file

# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"

1
これにより、必要に応じてプロセスが特権を回復できることに注意してください。このsetuid関数は、実際のUIDではなく、実効 UID のみを設定します。setreuidプロセスが特権を取り戻すことができないようにしたい場合に使用してください。(そして上記のコードは補足的なグループ特権も扱いません。ほとんど信頼されているコードを起動する場合にのみ適しています。)
David Schwartz

@David Schwartzコードは、使用されるメカニズムを示すために意図的に簡略化されています。
tylerl 2011

セキュリティが重要なコードを簡略化する場合は、これがあなたがやっていることを非常に明確にする必要があります。そうでない場合は、「それは単なる問題」のようなことを言うべきです。
David Schwartz

2
@David実際にsetuid()は、実際の保存されたユーザーIDを設定します。あなたは考えているかもしれませんseteuid()。すべてのシステムにがあるわけsetreuid()ではないため、どこでも使用できるわけではありません。の正確なセマンティクスsetuid()は複雑ですが、euid 0を持っている場合は、を使用して従来のすべてのユーザーID特権を削除できますsetuid()。この回答で最大の省略はということですinitgroupsか、setgroupsなどと呼ばれなければならないsetgidsetuidし、より徹底したアサーションが最後に行われるべきであるということ。
ニコラスウィルソン

0

あなたが別の実行可能ファイルを実行している場合、つまり、あなたが呼んでいるexecveかの他のexec機能のfamiliy、おそらく間接的などの機能を通じてsystemまたはpopen、子プロセスは最初から権限なしで実行する必要があり、その後、最も簡単な方法は、取得することですシェルが関与し、を呼び出しますsu。これは、Perlでのコードの外観の概要であり、に必要な引用を示しています。

$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;

子プロセスがrootとして開始する必要があるが、後で特権を削除する必要がある場合は、この回答のコードを参照してください。プロセスの特権をダウングレードする方法が示されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.