web-dev-qa-db-ja.com

スクリプトは実行可能ですが読み取り可能ではありませんか?

スクリプトを読み取る権限がない場合、スクリプトを実行することはできますか?ルートモードで、スクリプトを作成しました。他のユーザーにこのスクリプトを実行させますが、読み込ませません。読み取りと書き込みを禁止して実行を許可するためにchmodを実行しましたが、ユーザーモードでは、次のメッセージが表示されました。権限が拒否されました。

69
ashim

問題は、スクリプトが実行されているものではなく、インタープリター(bashPerlpythonなど)であることです。そして、通訳はスクリプトを読む必要があります。これは、プログラムがインタープリターのようにカーネルに直接ロードされるという点で、lsのような「通常の」プログラムとは異なります。カーネル自体がプログラムファイルを読み取っているので、読み取りアクセスについて心配する必要はありません。通常のファイルを読み取る必要があるため、インタプリタはスクリプトファイルを読み取る必要があります。

70
Arcege

これはバイナリでのみ可能です。

$ 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を使用してファイルを読み取ることができます。

35
kwarrick

これは、少なくともLinuxでは不可能です(他のUnicesでも可能です)。考えてみてください。スクリプトを実行するとき、シェルは何をすべきかを知るためにそれを読む必要があります。

6
Renan

前のステートメントには半分真実があります。ユーザーが読み取れないようにスクリプトを設定できますが、実行可能です。プロセスは少し引き出されていますが、/ etc/sudoerで例外を作成することで実行でき、ユーザーはパスワードの入力を求められることなく、自分でスクリプトを一時的に実行できます。この方法:-他のディストリビューションのsetuidパッチを回避します。 -ユーザーにすべてに対するSudo権限を与えることなく、特定のスクリプトに対して一時的に昇格したアクセス許可を与えることができます。

この投稿の指示に従ってください: ファイル権限の実行のみ

3
santana

私は、これを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として実行されています(または、ラッパーファイルが同じユーザーによって所有されている限り、正確なユーザーは関係ありません)。

3
quodlibetor

この状況では、NOPASSWDオプションを指定してSudoを使用したため、ユーザーはスクリプトを読み取ることなく実行できます。

2
user33577

OpenBSDで動作します

@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が唯一の方法ではありません。インタープリターがPerlpythonのように動的にリンクされた実行可能ファイルである場合、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を返さないファイル。

0
mosvy