#!/path/to/interpreter
現在のユーザーがファイルに対する実行(--x)権限しか持っていない場合、どのユーザーの下でインタプリタ(ファイルの先頭に指定)が実行されますか?
現在、ユーザーはファイルを読み取る権限がないため、そのユーザーにすることはできません。インタプリタに含まれるすべてのコードはrootアクセス権を持っているため、rootにすることはできません。
では、インタプリタプロセスはどのユーザとして実行されますか?
編集:私の質問は、ファイルが指定した通訳者を知るのに十分に読んだと仮定していますが、実際にはそれまで届かないと思います。現在、シェル(通常b / a / sh)がターゲットファイルを実行するために解釈するコマンドは、そのファイルを読み取ろうとしますが失敗します。
答え1
ユーザーに実行可能なスクリプトに対する読み取り権限がない場合は、実行してみてください。失敗するCAP_DAC_OVERRIDE
、彼女に能力がない場合(たとえば、ルートの場合):
$ cat > yup; chmod 100 yup
#! /bin/sh
echo yup
^D
$ ./yup
/bin/sh: 0: Can't open ./yup
インタプリタは(失敗や成功に関係なく)スクリプトのsetuidビットまたはsetcap拡張属性を無視し、常に現在のユーザとして実行されます.
実行可能なスクリプトは、実行するためにインタプリタが開いて読み取ることができる必要があるという点でバイナリとは異なります。ただし、これは単にインタプリタに引数として渡され、インタプリタはこれをまったく読み取ろうとするのではなく、まったく異なる操作を実行できます。
$ cat > interp; chmod 755 interp
#! /bin/sh
printf 'you said %s\n' "$1"
^D
$ cat > script; chmod 100 script
#! ./interp
nothing to see here
^D
$ ./script
you said ./script
もちろん翻訳者はそれ自体setuidまたはcap_dac_override=ep
-setcapバイナリ(またはそのバイナリの引数としてスクリプトパスを渡す)にすることができます。この場合、高い権限で実行され、すべてのファイル権限は無視できます。
Linuxでbinfmt_miscを介して読み取れないSetuidスクリプト
Linuxでは、次のモジュールを使用して実行可能なスクリプトのすべての制限をバイパスすることができます(そしてシステムを損傷する可能性があります;-))binfmt_misc
。
ルートとして:
# echo ':interp-test:M::#! ./interp::./interp:C' \
> /proc/sys/fs/binfmt_misc/register
# cat > /tmp/script <<'EOT'; chmod 4001 /tmp/script # just exec + setuid
#! ./interp
id -u
EOT
一般ユーザーとして:
$ echo 'int main(void){ dup2(getauxval(AT_EXECFD), 0); execl("/bin/sh", "sh", "-p", (void*)0); }' |
cc -include sys/auxv.h -include unistd.h -x c - -o ./interp
$ /tmp/script
0
女皮族に生まれた若いエリート層!
詳細については、次を参照してください。Documentation/admin-guide/binfmt-misc.rst
カーネルのソースコードから。
この-p
オプションは一部のシェルでエラーを引き起こす可能性があります(オプションは単に削除できます)、最新バージョンではエラーを防ぐためにdash
このオプションが必要です。bash
特権を放棄する要求なしで。
答え2
スクリプトの実行には2つのステップがあります。まず、カーネルはファイルの先頭を読んでから始まるものを見つけて、#!
次のように読みます。シェルボーンどの通訳者に電話するかを決定します。その後、カーネルは生のコマンドラインをインタプリタパス、shebang行のオプション(存在する場合)、ファイルパス、およびrawオプションに変換します。その後、このコマンドラインは常にコマンドラインであったかのように実行されますが、追加のShebang処理は実行されません。
これまでカーネルは、呼び出し元がスクリプトファイルに対する実行権限を持っていることを確認していました。読み取り権限はまだ適用されていません。カーネルはファイルの実行中にファイルの先頭を読み取るので、これは読み取り権限ではなく実行権限によって制御されます。
第2段階では、インタプリタが実行される。コマンドラインでスクリプトファイル名を確認するので、そのファイルを開こうとします。この時点で読み取り権限が必要です。インタプリタがファイルを読み取る権限がない場合、呼び出しはopen
失敗し、インタプリタはエラーメッセージを印刷して放棄する可能性があります。私が「おそらく」と言ったのは、それがすべての合理的な通訳者がすることだからです。しかし、そのように仕事が発生しなければならない技術的な義務はありません。 Shebangラインで使用されるプログラムが通訳者ではない場合、最初のステップでは違いはありませんが、プログラムは2番目のステップでそのタスクを実行します。たとえば、「script」で始まると、#!/bin/echo
スクリプトファイル名と他のコマンドライン引数が印刷されてから終了し、スクリプトはそれに対してのみ実行可能でなければなりません。
1Linuxを含む多くのカーネルは1つだけ選択できます。
答え3
通常、ファイルを所有していても「r」権限がないとスクリプトを実行できません。
$ ls -l tst
---x--x--x 1 sweh sweh 24 May 4 21:22 tst*
$ ./tst
/bin/bash: ./tst: Permission denied
$ sudo cat tst
#!/bin/bash
echo hello
修正された質問に基づいています。
プログラムのこの部分は#!
カーネルによってexec()
システムコールの一部として解釈されます。したがって、これを達成するためにスクリプトを読み取る必要はありません。
私の例で実際に起こるのは、カーネルがmyを呼び出し./tst
に変換することです。/bin/bash ./tst
この変換はスクリプトをr
処理するためにアクセスが必要な理由を説明しますが、カーネルは使用するx
インタプリタを決定するだけです。