Linuxシステムを強化していて、コマンドの実行をサポートするsetuid
、awk
などの一般的なバイナリを使用して(vim
ベースの)シェルエスケープをテストしたいと思いました。
ただし、sh
とbash
を除いて、私がテストしたすべてのバイナリは、それらのsetuid
ビットを尊重しません。
特に、awk
は通常のユーザーとして実行を継続します。
$ ls -lL /usr/bin/awk
-rwsr-xr-x 1 root root 121976 Mar 23 2012 /usr/bin/awk
$ id
uid=1000(bob) gid=1000(bob) groups=1000(bob)
$ awk 'BEGIN{system("id")}'
uid=1000(bob) gid=1000(bob) groups=1000(bob)
対照的に、-p
オプションを指定すると、bash
はroot
として実行されます。
$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1168776 Apr 18 2019 /bin/bash
$ /bin/bash -p
# id
uid=1000(bob) gid=1000(bob) euid=0(root) groups=1000(bob)
awk
、vim
、less
などにsetuid
ビットを尊重させ、コマンドをroot
として実行する方法はありますか?
[〜#〜] os [〜#〜]:
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
更新:
parallels@debian-gnu-linux-vm:~$ ls -la /proc/self/fd/0 /dev/fd/0 /dev/stdin
lrwx------ 1 parallels parallels 64 Mar 26 08:15 /dev/fd/0 -> /dev/pts/1
lrwxrwxrwx 1 root root 15 Mar 20 19:56 /dev/stdin -> /proc/self/fd/0
lrwx------ 1 parallels parallels 64 Mar 26 08:15 /proc/self/fd/0 -> /dev/pts/1
$ ls -lL /usr/bin/awk
-rwsr-xr-x 1 root root 121976 Mar 23 2012 /usr/bin/awk
$ awk 'BEGIN{system("id")}'
uid=1000(bob) gid=1000(bob) groups=1000(bob)
あなたの例では、特権を落としたり「setuidビットを尊重」したりするのはawk
ではなく、awkがsystem()
関数を実装するために使用する/bin/sh
コマンドです。
Cの対応物と同様に、awkのsystem()
はコマンドを直接解析して実行するのではなく、引数として/bin/sh -c
に渡します。 /bin/sh
がbash(または、Debianバージョンのdash、またはこの誤った機能をbashからコピーした他のいくつかのシェル)の場合、有効なuidを実際のuidにリセットします。
同じことがawkのprint | "cmd"
または"cmd" | getline
にも当てはまります。これらは/bin/sh -c
を呼び出すpopen(3)
で実装されています。これは常に/bin/sh
(またはシステムのシェル(Androidでは/system/bin/sh
など))であり、ユーザーのログインシェルや$Shell
環境変数からのものではないことに注意してください。 [1]
これはPerlでは異なります。Perlのsystem
、exec
、open "|-"
、open2
、open3
などは、複数の引数で呼び出された場合、またはコマンドにシェルメタ文字が含まれていない場合、コマンドを直接実行します。 :
$ id -nu
ahq
$ ls -l /tmp/Perl
-rwsr-xr-x 1 dummy_user dummy_user 3197768 Mar 24 18:13 /tmp/Perl
$ env - /tmp/Perl -e 'system("id -nu")'
dummy_user
$ env - /tmp/Perl -e 'system("{ id -nu; }")'
ahq
この例はDebian10上にあります。FreeBSDや古いDebianのような他のシステムでは、/bin/sh
が特権をドロップしないため、両方のコマンドは同じものを出力します。 [2]
注:
[1]vim
やless
のような他のプログラムは、$Shell
環境変数を使用するので、簡単に「ラッパーを指すことで修正可能」。 vim
では、:set shcf=-pc
を使用して、-p
および同様のコマンドに使用されるシェルに:!
オプションを渡すこともできます。
[2]Perlの例は、env - /tmp/Perl 'script'
をより鈍いecho 'script' | /tmp/Perl /dev/fd/0
に置き換えると、FreeBSDと同じようにOpenBSDでも機能します。
OpenBSDのPerlは、setuidモードで実行しているときに、-e
引数を拒否し、stdinからのスクリプトの読み取りを拒否します( this 終了を参照 here -OpenBSDにはおそらく安全なsetuidスクリプトがあります)。
しかし、それは/dev/fd/N
には当てはまりません。Perlは それ自体を処理します スクリプト名として指定された場合(/dev/fd/N
または/dev/stdin
ではなく/proc/self/fd/N
フォームのみ)。
obsd66$ ls -l /tmp/Perl
-rwsr-xr-x 1 dummy_user dummy_user 10728 Mar 25 18:34 /tmp/Perl
obsd66$ env - /tmp/Perl -e 'system("{ id -nu; }")'
No -e allowed while running setuid.
obsd66$ echo 'system("{ id -nu; }")' | env - /tmp/Perl
No program input from stdin allowed while running setuid.
obsd66$ echo 'system("{ id -nu; }")' | env - /tmp/Perl /dev/stdin
Can't open Perl script "/dev/stdin": Operation not permitted
obsd66$ echo 'system("{ id -nu; }")' | env - /tmp/Perl /dev/fd/0
dummy_user
debian10$ su - other_user -c 'Perl /dev/fd/7' 7<<<'print "OK\n"'
OK
debian10$ su - other_user -c 'Perl /proc/self/fd/7' 7<<<'print "OK\n"'
Can't open Perl script "/proc/self/fd/7": Permission denied