スクリプトを読み取る権限がない場合、スクリプトを実行することはできますか?ルートモードで、スクリプトを作成しました。他のユーザーにこのスクリプトを実行させますが、読み込ませません。読み取りと書き込みを禁止して実行を許可するためにchmod
を実行しましたが、ユーザーモードでは、次のメッセージが表示されました。権限が拒否されました。
問題は、スクリプトが実行されているものではなく、インタープリター(bash
、Perl
、python
など)であることです。そして、通訳はスクリプトを読む必要があります。これは、プログラムがインタープリターのようにカーネルに直接ロードされるという点で、ls
のような「通常の」プログラムとは異なります。カーネル自体がプログラムファイルを読み取っているので、読み取りアクセスについて心配する必要はありません。通常のファイルを読み取る必要があるため、インタプリタはスクリプトファイルを読み取る必要があります。
これはバイナリでのみ可能です。
$ chown foo:foo bar
$ chmod 701 bar
非特権ユーザーとして:
$ ls -lha bar
-rwx-----x 1 foo foo 7.0K 2012-03-15 03:06 bar
$ cat bar
cat: bar: Permission denied
$ ./bar
baz
さて、ここがキッカーです。従来の方法ではファイルを読み取ることができませんが、ファイルの読み取りを実際に防ぐことはできません。これは実際には http://smashthestack.org/ (レベル13)の課題です。 hktrace
と呼ばれるよく知られたユーティリティがあり、ptrace
を使用してファイルを読み取ることができます。
これは、少なくともLinuxでは不可能です(他のUnicesでも可能です)。考えてみてください。スクリプトを実行するとき、シェルは何をすべきかを知るためにそれを読む必要があります。
前のステートメントには半分真実があります。ユーザーが読み取れないようにスクリプトを設定できますが、実行可能です。プロセスは少し引き出されていますが、/ etc/sudoerで例外を作成することで実行でき、ユーザーはパスワードの入力を求められることなく、自分でスクリプトを一時的に実行できます。この方法:-他のディストリビューションのsetuidパッチを回避します。 -ユーザーにすべてに対するSudo権限を与えることなく、特定のスクリプトに対して一時的に昇格したアクセス許可を与えることができます。
この投稿の指示に従ってください: ファイル権限の実行のみ
私は、これをsetuid
で行うことができると思います。
ほとんどのディストリビューションは(どうやら)setuid
を無効にしているので、それはできません。これは、巨大なセキュリティホールであるためです。私はそれが無効になっているので、この答えが機能するかどうかは実際にはわかりません。私はそれがすべきであると思うので、とにかく投稿します。
とにかく、私があなたがやりたいことをやりたいと思っていて、そしてスクリプトでsetuid
を有効にしたディストリビューションがあったら、私は次のようにします。
$ chmod 700 myscript
$ cat > myscript-nonroot
#!/bin/sh
bash myscript
^D
$ Sudo chown root:root myscript-nonroot
$ Sudo chmod 4755 myscript-nonroot # make SURE this isn't world-writable!
つまり、私が唯一の目的がroot読み取り専用スクリプトを呼び出し、rootが所有するように変更し、それにsetuid権限を与えることを目的とする別のスクリプトを作成するということです。 (他のすべての人による付随する書き込み不可ステータスとともに)。
Myscript-nonroot関数は誰でも読み取り可能であるため、読み取りと実行が可能であり、2つの時点で実際にスクリプトを実行する行(bash myscript
)rootとして実行されています(または、ラッパーファイルが同じユーザーによって所有されている限り、正確なユーザーは関係ありません)。
この状況では、NOPASSWDオプションを指定してSudoを使用したため、ユーザーはスクリプトを読み取ることなく実行できます。
@eradmanの コメント ですでに述べたように、これはOpenBSDで可能です。
ルートとして:
_hzy# cat <<'EOT' >/tmp/foo; chmod 001 /tmp/foo
#! /bin/sh
: this is secret
echo done
EOT
_
一般ユーザーとして:
_hzy$ cat /tmp/foo
cat: /tmp/foo: Permission denied
hzy$ /tmp/foo
done
_
これは、インタープリターに_/dev/fd/3
_(またはスクリプトへのオープンfdが何であれ)を渡すことで機能します。そのトリックはnotでLinuxで機能しますが、_/dev/fd/N
_はfdのdup(2)
を返す特殊文字デバイスではありません開くと、元のファイル/歯科への「マジック」シンボリックリンク。ファイルを最初から開きます[1]。それはFree/NetBSDまたはSolarisに実装できます...
基本的にx
(実行)アクセス許可を与えるとは、シバン[2]を持つファイルに対してr
(読み取り)アクセス許可も与えることを意味します:
_hzy$ cat /tmp/foo
cat: /tmp/foo: Permission denied
hzy$ ktrace -ti /tmp/foo
done
hzy$ kdump | tail -n8
70154 sh GIO fd 10 read 38 bytes
"#! /bin/sh
: this is secret
echo done
"
70154 sh GIO fd 1 wrote 5 bytes
"done
_
ktrace
が唯一の方法ではありません。インタープリターがPerl
やpython
のように動的にリンクされた実行可能ファイルである場合、read(2)
関数をオーバーライドする_LD_PRELOAD
_ edハックを代わりに使用できます。
いいえ、それをsetuidにしても、通常のユーザーはそのコンテンツを見ることができます。彼女は単にptrace(2)
の下で実行することができます。これにより、setuidビットが無視されます。
ルートとして:
_hzyS# cat <<'EOT' >/tmp/bar; chmod 4001 /tmp/bar
#! /bin/sh
: this is secret
id
EOT
_
一般ユーザーとして:
_hzyS$ ktrace -ti /tmp/bar
uid=1001(duns) euid=0(root) gid=1001(duns) groups=1001(duns)
hzyS$ kdump
... nothing, the kernel disabled the ktrace ...
hzyS$ cc -Wall -xc - -o pt <<'EOT'
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <signal.h>
int main(int ac, char **av){
int s; pid_t pid;
if((pid = fork()) == 0){
ptrace(PT_TRACE_ME, 0, 0, 0);
execvp(av[1], av + 1);
}
while(wait(&s) > 0 && WIFSTOPPED(s)){
s = WSTOPSIG(s);
ptrace(PT_CONTINUE, pid, (caddr_t)1, s == SIGTRAP ? 0 : s);
}
}
EOT
hzyS$ ./pt ktrace -ti /tmp/bar
uid=1001(duns) gid=1001(duns) groups=1001(duns)
hzyS$ kdump | tail -5
29543 sh GIO fd 10 read 31 bytes
"#! /bin/sh
: this is secret
id
"
_
(これが最も簡単な方法ではない場合は申し訳ありません)
[1]これはLinuxで_binfmt_misc
_を使用してエミュレートできますが、インタープリターを変更するか、ラッパーを使用する必要があります。 この答え の最後の部分を参照してください意図的にばかげて安全ではない例。
[2]または一般的に、execve()
がENOEXEC
を返さないファイル。