web-dev-qa-db-ja.com

Unixの実行許可は簡単に回避できます。それは不必要ですか、またはその背後にある意図は何ですか?

UNIXの読み取り権限は実際には実行権限と同じです。 1つのプロセスは書き込みアクセス権を持ち、同じファイルを実行することもできます。

これはかなり簡単に行うことができます。最初に、このプロセスは、実行されるファイルのコンテンツをバッファにロードする必要があります。その後、バッファ内のELFを解析して正しいアドレスにロードする共有ライブラリから関数を呼び出します(おそらく、execvpを呼び出すときに、通常どおり古いプロセスを上書きすることにより)。コードが新しいプログラムのエントリポイントにジャンプし、実行されます。

デニス・リッチーとケン・トンプソンがその問題を知っていたと私はかなり確信しています。それで、なぜ彼らはこの許可を発明したのですか?読み取りアクセス権を持つユーザーのプロセスの実行を妨げることができない場合、その背後にある意図とその意味は何ですか?そのような感覚さえあるのか、それとも不必要なのか?

これは深刻なセキュリティ問題である可能性もあります。rw-またはr--権限の強さに依存するシステムはありますか?

59
Martin Erhardt

「実行」権限をバイパスするさらに簡単な方法があります。自分が所有するディレクトリにプログラムをコピーし、「実行」ビットを設定します。

「実行」権限はセキュリティ対策ではありません。セキュリティはより低いレベルで提供され、オペレーティングシステムは特定のアクションを制限します。これは、多くのUnixライクなシステム(特にRitchieとThompsonの時代)では、ユーザーが独自のプログラムを作成できると想定されているためです。このような状況では、ユーザーが機密プログラムの独自のコピーを作成するだけでよいため、セキュリティ対策として「実行」権限を使用しても意味がありません。

具体的な例として、権限のないユーザーとしてfdiskを実行して、ハードドライブのパーティションテーブルをスクランブルしようとします。

$ /sbin/fdisk /dev/sda 

Welcome to fdisk (util-linux 2.24.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

...

Changed type of partition 'Linux' to 'Hidden NTFS WinRE'.

Command (m for help): w
fdisk: failed to write disklabel: Bad file descriptor

最後の行はfdiskで、ハードドライブの「書き込み」ファイル記述子を取得しようとして失敗しました。これを実行するユーザーには、それを実行する権限がないためです。

「実行」権限の目的は2つあります。1)オペレーティングシステムにどのファイルがプログラムであるかを通知すること、2)ユーザーに実行可能なプログラムをユーザーに通知することです。これらは両方とも必須ではなく推奨です。許可なしに完全に機能するオペレーティングシステムを作成できますが、ユーザーエクスペリエンスが向上します。

R ..が指摘しているように、セキュリティのために「実行」権限が使用される特定のケースが1つあります。それは、プログラムにも「setuid」ビットが設定されている場合です。この場合、「実行」権限を使用して、プログラムの実行を許可するユーザーを制限できます。 「実行」権限をバイパスする方法でも「setuid」ステータスが削除されるため、ここにセキュリティ上のリスクはありません。

80
Mark

実行可能ファイルに実行ビットを設定できますが、読み取りビットは設定できません。そうすれば、誰もファイルをコピーできなくなりますが、人々はとにかくそれを実行できます。

これは今日ではまったく意味がありません。なぜなら、a)コンパイルされたプログラムでのみ機能し、スクリプトでは機能しない(ほとんどのシステム) b)最近では、すべてのUNIXの90%がLinuxなので、人々はどこからでも実行可能ファイルをコピーできます。c)コピーされた実行可能ファイルに必要なディスク容量は重要ではありません。

それでも、昔はその用途がありました。

30年前、私が学校で使用していたUnixシステムは、RAMおよびディスク容量が非常に制限されていました。特に、/usr/tmpファイルシステムは非常に小さいため、誰かが大規模なプログラムをコンパイルしようとしました。もちろん、学生はとにかく「大規模なプログラム」を書くことを想定していませんでした。大規模なプログラムは通常、「どこか」からコピーされたソースコードでした。多くの人が/usr/bin/cc/home/<myname>/ccにコピーしました、およびddを使用してバイナリにパッチを適用し、/tmpではなく/usr/tmpを使用するようにしました。もちろん、これにより問題がさらに悪化しました。これらのコピーによって占有されるディスク領域では、当時は問題でしたが、今では定期的に/tmpがいっぱいになり、他のユーザーが自分のファイルを編集することもできなくなりました。何が起こったのかを知った後、システム管理者はchmod go-r /bin/* /usr/bin/*を実行して問題を「修正」し、すべて削除しましたCコンパイラのコピー。

もう1つの用途は、実行する予定のファイルとそうでないファイルをシェルに通知することです。名前を入力したので、ランダムなテキストファイルを実行したくありません。 xビットはこれを防ぐ方法を提供します。 (最近では、シェルはファイルの先頭だけを見て、それが#!で始まる場合にのみ実行できましたが、これはずっと後で導入されました)。 bashの補完機能も、コマンドを入力しているときにのみ実行可能ビットを持つファイルを提案します。

任意のファイルを実行する既製の方法があります。それを動的リンカー(動的にロードされた実行可能ファイルの適切なインタープリター)に引数として渡します。例えば。 Linuxでは、

cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/ld-linux.so.2 /tmp/ls

ただし、これには、ファイルを読み取ってコードにジャンプするのと同じ制限があります。setuidビットは評価されません。

昔は/bin/suのようなバイナリがよくありました:

-rwsr-xr-- root wheel  ...  /bin/su

システム管理者がwheelパスワードを知っている人にトリミングし続けたrootグループのメンバーだけがsuコマンドを実行できるため、バッファオーバーフローが存在していてもこのバイナリでは、発信者がセキュリティを回避できるようにしており、エクスプロイトはとにかくパスワードを知っている人しか使用できません。

7
Simon Richter

+ x bit:ディレクトリの別の使用法について他の誰も言及していないことに驚いています。/bin(シェルスクリプトなど)で(例)何かを実行した後かもしれませんが、ファイルよりもビットを実行する方がたくさんあります(もちろん、ディレクトリISファイルですが別の種類のファイル)。

ディレクトリに+ xアクセスがあり、同じディレクトリに-rがある場合、次の機能を使用できます。

  • そのディレクトリ内のファイル(またはディレクトリ)の名前がわかっている場合は、それを一覧表示できます(例:ls on it)。ただし、名前を知っている必要があります。
  • これに変更することはできません(cdコマンドまたはchdirシステムコールを使用)。

ただし、-xと+ rがある場合は、次の操作を実行できます。

  • ディレクトリに移動することはできません(上記と同じ方法)。
  • ファイルを一覧表示できます。ただし、ディレクトリへの+ xアクセス権がないため、ファイル自体にはアクセスできません。
  • これはまた、更新することはできず(タイムスタンプのみまたはそれ以外)、テキストエディター(またはcatまたは...)で開くこともできないことを意味します。

+ rxがあれば、すべてを行うことができます(ただし、ディレクトリ自体に書き込むには+ wが必要です(つまり、新しいファイルを作成します。ファイルの編集は機能しますが、削除は機能せず、作成は行われません)。

はい、これは、一部のユーザーにファイルの表示または編集を許可することは可能ですが、ファイルへの正確なパスを知っている場合に限られます(とにかく編集する権限がある場合)。そして、はい:lsはリストであり、ディレクトリの検索に使用されます。つまり、要約すると、ディレクトリの実行は(何らかの理由で)ディレクトリに変わります。もちろん、ビットがすべて一緒になって本当に重要なことです。

6
user54909

何らかの理由でバイナリコードを秘密にしたい場合は、プログラムを読み取り不能にせずに実行可能にすることができます。これらのユーザーがマシンに物理的にアクセスできる場合、これは役に立ちません。また、ソースコードまたはバイナリコードが広く利用できる場合も役に立ちません。したがって、これはかなり限定的なユースケースです。

プログラムにsetuidビットまたはsetgidビットがある場合、実行アクセスは、バイナリを読み取ることによって実現できることよりも多くのことを行います。 1つのアプローチは、特定のグループに対してのみ実行可能なsetuid実行可能ファイルを作成することです。それが誰でも読み取り可能である場合、そのグループの外部の人々はそれをコピーして、元の実行可能ファイルのsetgidビットを利用することができませんでした。 (ほとんどの場合、私はsetuidではなくsetgidを使用し、ディレクトリのグループを使用して、実行可能ファイルにアクセスできるユーザーを制御します。)

通常、実行可能ビットは、どのファイルが最初にプログラムであるかを示すために単に使用されます。そうすることで、補完がうまく機能し、誤って不要な実行可能ファイルを実行することがなくなります。

ユーザーが実行可能ファイルをコピーして実行できないようにする場合は、noexecを使用してホームディレクトリをマウントできます。これが意味をなすためには、ユーザーが何かを書き込むことができるすべてのファイルシステムに対してnoexecを使用する必要があります。

4
kasperd

実行ビット許可は、exec(2)(およびいとこ)システムコールの実行時にカーネルによってチェックされます。カーネルレベルでプログラムを実行する場合にのみ必要です。

exec()edができるのは、そのビットがオンになっているプログラム(所有者、グループ、または他の人があなたにヒットするものはどれでもチェックされているもの)だけです。カーネル。

他の異なることは、シェルスクリプトやPerlを解釈するときにシェルが何をするか、あるいはあなたが持っているかもしれないどんなインタプリタでもあります。スクリプトでは、カーネルはファイルの先頭の#!...をマジックナンバーとしてチェックし、そこに示されているシェルを起動し(シェルの実行権限も必要です)、do needシェルはスクリプトを開いて読み取り、解釈する必要があるため、そのスクリプトに対する読み取り権限。シェルスクリプトの場合は、読み取り権限と実行権限が必要です。ただし、シェルスクリプトの場合、シェルを実行することで常にシェルスクリプトを実行できるため、onlyには読み取り権限が必要です。シェルスクリプトをパラメーター(または入力ファイル)として渡す

もちろん、指摘したように、実行ビットはプログラムをコピーして実行可能にすることで回避できますが、そのコピーを作成するための読み取り権限がない場合はコピーできません(続行します)それを実行できるようにするため)。

(もちろんルートとして)権限をls(1)に変更して0111---x--x--x)にして、実行可能なコピーを作成してみてください。引き続き実行できる場合でも、実行可能コピーを取得することはできません。

ディレクトリでは、実行ビットは別のものを意味します。カーネルは、パスを反復するときに(_namei()カーネル関数で)「x」権限を使用するため、ディレクトリに対する実行権限がない場合は、それ、またはそれを介してアクセス可能なファイル。ディレクトリの内容を読み取り権限で読み取ることもできますが、その中のファイルにはアクセスできません。または、反対に、ディレクトリに対する実行権限を持っているが、読み取りアクセス権は持っていない可能性があります。内部のファイルを使用することはできますが、ディレクトリの内容を表示することはできません。

2
Luis Colorado