GNU/Linux >> Linux の 問題 >  >> Linux

シェルスクリプトでSetuidを許可しますか?

setuid パーミッションビットは、エグゼキュータではなく所有者の有効なユーザーIDでプログラムを実行するようにLinuxに指示します。

> cat setuid-test.c

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

int main(int argc, char** argv) {
    printf("%d", geteuid());
    return 0;
}

> gcc -o setuid-test setuid-test.c
> ./setuid-test

1000

> sudo chown nobody ./setuid-test; sudo chmod +s ./setuid-test
> ./setuid-test

65534

ただし、これは実行可能ファイルにのみ適用されます。シェルスクリプトはsetuidビットを無視します:

> cat setuid-test2

#!/bin/bash
id -u

> ./setuid-test2

1000

> sudo chown nobody ./setuid-test2; sudo chmod +s ./setuid-test2
> ./setuid-test2

1000

ウィキペディアによると:

セキュリティ上の欠陥の可能性が高まるため、多くのオペレーティングシステムは、実行可能なシェルスクリプトに適用されるときにsetuid属性を無視します。

私がこれらのリスクを受け入れるつもりだと仮定すると、Linuxにシェルスクリプトで実行可能ファイルと同じようにsetuidビットを処理するように指示する方法はありますか?

そうでない場合、この問題の一般的な回避策はありますか?私の現在の解決策は、sudoersを追加することです ALLを許可するエントリ NOPASSWDを使用して、特定のスクリプトを実行したいユーザーとして実行するには パスワードプロンプトを回避します。その主な欠点は、sudoersの必要性です。 これを実行するたびにエントリを入力し、呼び出し元がsudo some-scriptを実行する必要がある some-scriptの代わりに

承認された回答:

Linuxは、解釈されたすべての実行可能ファイル(つまり、#!で始まる実行可能ファイル)のsetuid¹ビットを無視します。 ライン)。 comp.unix.questions FAQは、setuidシェルスクリプトのセキュリティ問題について説明しています。これらの問題には、シバン関連とシェル関連の2種類があります。以下で詳細を説明します。

セキュリティを気にせず、setuidスクリプトを許可したい場合は、Linuxでカーネルにパッチを適用する必要があります。 3.xカーネルの時点で、install_exec_credsへの呼び出しを追加する必要があると思います load_scriptで 関数、open_execを呼び出す前 、しかし私はテストしていません。

Setuid shebang

シバンの方法に固有の競合状態があります(#! )通常は実装されます:

  1. カーネルが実行可能ファイルを開き、#!で始まることを検出します。 。
  2. カーネルは実行可能ファイルを閉じ、代わりにインタプリタを開きます。
  3. カーネルは、スクリプトへのパスを引数リストに挿入します(argv[1]として) )、インタプリタを実行します。

この実装でsetuidスクリプトが許可されている場合、攻撃者は既存のsetuidスクリプトへのシンボリックリンクを作成して実行し、カーネルがステップ1を実行した後、インタープリターが最初の引数を開きます。このため、ほとんどのユニスはsetuidビットを無視します 彼らがシバンを検出したとき。

この実装を保護する1つの方法は、インタープリターがスクリプトファイルを開くまで、カーネルがスクリプトファイルをロックすることです(これにより、ファイルのリンク解除や上書きを防ぐだけでなく、パス内のディレクトリの名前を変更することもできなくなります)。しかし、UNIXシステムは必須のロックを敬遠する傾向があり、シンボリックリンクは正しいロック機能を特に困難かつ侵襲的にします。誰もこのようにやっていないと思います。

いくつかのUNIXシステム(主にOpenBSD、NetBSD、Mac OS X、これらはすべてカーネル設定を有効にする必要があります)は、 secure setuid shebangを実装しています。 追加機能の使用:パス/dev/fd/N ファイル記述子Nですでに開かれているファイルを指します (したがって、/dev/fd/N dup(N) )。多くのUNIXシステム(Linuxを含む)には/dev/fdがあります ただし、setuidスクリプトではありません。

  1. カーネルが実行可能ファイルを開き、#!で始まることを検出します。 。実行可能ファイルのファイル記述子が3であるとしましょう。
  2. カーネルがインタプリタを開きます。
  3. カーネルは/dev/fd/3を挿入します 引数リスト(argv[1]として) )、インタプリタを実行します。
関連:(Bash)シェルの特別なパラメーター/変数はどれですか?

SvenMascheckのシバンページ setuidのサポートなど、ユニス全体のシバンに関する多くの情報があります。

Setuidインタープリター

OSがsetuidshebangをサポートしているため、またはネイティブのバイナリラッパー(sudoなど)を使用しているために、プログラムをrootとして実行できたと仮定します。 )。セキュリティホールを開けましたか? たぶん 。ここでの問題はではありません インタプリタプログラムとコンパイルプログラムについて。問題は、ランタイムシステムかどうかです。 特権を使用して実行すると、安全に動作します。

  • 動的にリンクされたネイティブバイナリ実行可能ファイルは、動的ローダーによって解釈されます。 (例:/lib/ld.so )、プログラムに必要なダイナミックライブラリをロードします。多くのユニスでは、環境を介してダイナミックライブラリの検索パスを構成できます(LD_LIBRARY_PATH は環境変数の一般名です)、実行されたすべてのバイナリに追加のライブラリをロードすることもできます(LD_PRELOAD )。プログラムの呼び出し元は、特別に細工されたlibc.soを配置することにより、そのプログラムのコンテキストで任意のコードを実行できます。 $LD_LIBRARY_PATHにあります (他の戦術の中で)。すべての正常なシステムはLD_*を無視します setuid実行可能ファイルの変数。

  • シェル sh、csh、派生物など、環境変数は自動的にシェルパラメータになります。 PATHなどのパラメータを介して 、IFS 、およびその他多くの場合、スクリプトの呼び出し元には、シェルスクリプトのコンテキストで任意のコードを実行する多くの機会があります。一部のシェルは、スクリプトが特権で呼び出されたことを検出した場合、これらの変数を適切なデフォルトに設定しますが、信頼できる特定の実装があるかどうかはわかりません。

  • ほとんどのランタイム環境 (ネイティブ、バイトコード、インタプリタのいずれであっても)同様の機能があります。 setuid実行可能ファイルで特別な予防策を講じる人はほとんどいませんが、ネイティブコードを実行する実行可能ファイルは、動的リンク(予防策を講じる)よりも優れた機能を実行しないことがよくあります。

  • Perl 注目すべき例外です。 setuidスクリプトを明示的にサポートします 安全な方法で。実際、OSがスクリプトのsetuidビットを無視した場合でも、スクリプトはsetuidを実行できます。これは、perlには、必要なチェックを実行し、必要な特権を持つ目的のスクリプトでインタープリターを再起動するsetuidルートヘルパーが付属しているためです。これはperlsecマニュアルで説明されています。以前は、setuidperlスクリプトに#!/usr/bin/suidperl -wTが必要でした。 #!/usr/bin/perl -wTの代わりに 、ただし、最近のほとんどのシステムでは、#!/usr/bin/perl -wT 十分です。

ネイティブバイナリのラッパーを使用しても、これらの問題を防ぐためにそれ自体は何もしませんことに注意してください。 。実際、状況を悪化させる可能性があります 、ランタイム環境が特権で呼び出されたことを検出できず、ランタイム構成可能性をバイパスできない可能性があるためです。

ネイティブバイナリラッパーは、ラッパーが環境をサニタイズする場合、シェルスクリプトを安全にすることができます 。スクリプトは、(現在のディレクトリなどについて)あまり多くの仮定をしないように注意する必要がありますが、これは当てはまります。環境をサニタイズするように設定されている場合は、sudoを使用できます。変数をブラックリストに登録するとエラーが発生しやすいため、常にホワイトリストに登録してください。 sudoを使用する場合は、env_resetを確認してください。 オプションがオンになっている場合、そのsetenv がオフで、そのenv_file およびenv_keep 無害な変数のみが含まれています。

関連:シェルで引用符をエスケープする方法は?

TL、DR:

  • Setuidシバンは安全ではありませんが、通常は無視されます。
  • 特権を使用して(sudoまたはsetuidを介して)プログラムを実行する場合は、ネイティブコードまたはperlを作成するか、環境をサニタイズするラッパー(env_resetを使用したsudoなど)を使用してプログラムを起動します。 オプション)。

¹この説明は、「setuid」を「setuid」に置き換えた場合にも同様に当てはまります。これらは両方とも、スクリプト上のLinuxカーネルによって無視されます


Linux
  1. シェルスクリプトの連想配列?

  2. シェルスクリプトの正しいロック?

  3. シェルスクリプトでルート権限を削除する方法は?

  1. Webサイトからシェルスクリプトを実行しますか?

  2. シェルスクリプトでパスワードを隠す?

  3. Unixシェルスクリプトのファイル拡張子?

  1. 複数のシェルスクリプト間で変数を共有しますか?

  2. シェルスクリプトのPosixコンプライアンスをテストする方法は?

  3. シェルスクリプトで長いコマンドを分割しますか?