スクリプトはどうですか?

スクリプトはどうですか?

一般ユーザーが実行するときにroot権限を必要とするプロセスがあります。明らかに「setuidビット」を使用してこれを行うことができます。 POSIXシステムでこれを行う正しい方法は何ですか?

また、インタプリタ(bash、perl、python、phpなど)を使用するスクリプトを使用してこれをどのように実行できますか?

ベストアンサー1

これユーザーIDビットの設定実行時にプログラムが実際のユーザー(他の場合)ではなくファイル所有者の権限を持つように実行可能ファイルに設定できます。それは違いです。効果的なuid(ユーザーID)と本物uid。

一部の共通ユーティリティ(例passwd:)は、ルートが所有し、必要に応じて設定されます(ルートのみを読み取る権限へ passwdのアクセスが必要です)。/etc/shadow

これを行う際の最善の戦略は、スーパーユーザーとして必要なタスクをすぐに実行し、権限を下げてrootとして実行するときにエラーや誤用が発生する可能性を減らすことです。これを行うには、プロセスの設定が必要です。効果的なuidは実際のuidです。 POSIX Cでは:

#define _POSIX_C_SOURCE 200112L // Needed with glibc (e.g., linux).
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

void report (uid_t real) {
    printf (
        "Real UID: %d Effective UID: %d\n",
        real,
        geteuid()
    );
}

int main (void) {
    uid_t real = getuid();
    report(real);
    seteuid(real);
    report(real);
    return 0;
}

POSIXシステムで一般的に使用される関連機能は、ほとんどの高度な言語でも同じ機能を持つ必要があります。

  • getuid():得る本物uid。
  • geteuid():得る効果的なuid。
  • seteuid():設定効果的なuid。

実際のuidと一致しない最後のエントリでは何もできません実行ファイルに setuid ビットが設定されていない場合。したがって、これを試すにはコンパイルしてくださいgcc test.c -o testuid。その後、権限が必要です。

chown root testuid
chmod u+s testuid

最後はsetuidビットを設定します。通常のユーザーとして実行すると./testuid、プロセスがデフォルトで有効なuid 0、rootとして実行されていることがわかります。

スクリプトはどうですか?

これはプラットフォームによって異なります。しかし、Linuxでは、インタプリタ(バイトコードを含む)が必要なものは、インタプリタに設定されていないとsetuidビットを使用できません(非常に愚かなことです)。以下は、上記のCコードを模倣した単純なPerlスクリプトです。

#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);

print "Real UID: $< Effective UID: $>\n";
$> = $<; # Not an ASCII art greedy face, but genuine perl...
print "Real UID: $< Effective UID: $>\n"; 

$>* nixyルートに忠実に、Perlには有効なuid()と実際のuid($<)の特殊変数が組み込まれています。ただし、同じ操作を試しchownchmodコンパイルされた実行可能ファイル(C、前の例)と組み合わせて使用​​すると、違いはありません。スクリプトが権限を取得できません。

答えは、setuidバイナリを使用してスクリプトを実行することです。

#include <stdio.h>
#include <unistd.h> 

int main (int argc, char *argv[]) {
    if (argc < 2) {
        puts("Path to perl script required.");
        return 1;
    }
    const char *perl = "perl";
    argv[0] = (char*)perl;
    return execv("/usr/bin/perl", argv);
}

gcc --std=c99 whatever.c -o perlsuid次にこれをコンパイルしますchown root perlsuid && chmod u+s perlsuid。これで実行できますどの有効なuidが0のPerlスクリプト、誰がそれを所有しても構いません。

同様の戦略がPHP、Pythonなどに適用されます。 しかし...

# Think hard, very important:
>_< # Genuine ASCII art "Oh tish!" face

してくださいこれを放置しないでください。 おそらく実際にはスクリプト名でコンパイルしたいと思います。絶対パスつまり、その中のすべてのコードをmain()次に置き換えます。

    const char *args[] = { "perl", "/opt/suid_scripts/whatever.pl" }
    return execv("/usr/bin/perl", (char * const*)args);

/opt/suid_scriptsroot以外のユーザーの場合は、その中のすべての内容が読み取り専用であることを確認してください。そうでなければ、誰かがそれのために何でも変えることができますwhatever.pl

また注意事項多くのスクリプト言語では、環境変数がスクリプトの実行方法を変更できるようにします。。たとえば、環境変数により、呼び出し元によって提供されたライブラリがロードされ、呼び出し元が任意のコードをrootとして実行できます。したがって、インタプリタとスクリプト自体がすべての可能な環境変数に強力であることを知らない限り、これをしないでください。

だから私は何をすべきですか?

root以外のユーザーがrootとしてスクリプトを実行できるようにするより安全な方法は、次のものを追加することです。Sudoルールを作成し、ユーザーにそれを実行させますsudo /path/to/script。 Sudoは、ほとんどの環境変数を削除し、管理者がコマンドを実行できる人とパラメータを詳細に選択できるようにします。よりパスワードを要求せずにルートで特定のプログラムをどのように実行できますか?例えば。

おすすめ記事