コマンドの情報ページには、id
実際のユーザーIDと異なる場合に有効なユーザーIDを出力することが示されています。私はUbuntuの一般(無許可)ユーザーとしてBashシェルを使用してコマンドを実行し、何とかこれを達成しようとしました。たとえば、@Asain Kujovicの答えから例を試しました。ここしかし、うまくいかず、出力は得られませんeuid
。例は次のとおりです。
osbo@osboxes:~/t$ sudo gcc -o test.bin -xc - <<EOF
#include <stdlib.h>
#include <unistd.h>
int main() { seteuid(0); system("id"); }
EOF
osbo@osboxes:~/t$ sudo chmod +s test.bin && ./test.bin && sudo rm test.bin
uid=1000(osbo) gid=1000(osboxes) groups=1000(osboxes),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),113(bluetooth),119(scanner)
編集する:
私はLinux初心者なので、私が尋ねる質問についてこれが可能であれば、初心者にやさしい答えを歓迎します。私はシェルプログラムが何であるか(例:Bashまたはsh)、環境変数が何であるか、Cプログラムが何であるか、システムコールが何であるか(例:およびgetuid
)を知っていますgeteuid
。また、ユーザー作成プロセスに関連する実際の有効で保存されたユーザー/グループIDが何であるかを知っています。ただし、親子プロセスのシナリオやコマンドstrace
についてはほとんど知りません。
答え1
system("code")
実際には、、、、sh
パラメータを使用して実行されます。sh
-c
--
code
1 子プロセスで。セキュリティ対策として、一部のシェルは次の機能を実行します。
if (geteuid() != (uid = getuid())
setuid(uid);
つまり、有効な uid が実際の uid と異なる場合、有効な uid を実際の uid に復元します。
setuid実行可能ファイルを作成する場合(可能であれば最初から実行しないでください)、昇格の脆弱性が発生しないように、昇格された権限で実行されるコード部分をできるだけ短く厳密に制御する必要があります。
セキュアシェルスクリプトを書くことはほとんど不可能なので、setuid実行可能ファイルからシェルを実行するのは最も望ましくない操作です。したがって、これらのシェルは起動時に最初にこれらの権限を削除することでこれを達成するのに役立ちます。
以下は、ダッシュベースのUbuntuシステムのzshからのものです。
$ sudo install -m 4750 -o root -g "$GID" =env .
$ ls -ld env
-rwsr-x--- 1 root stephane 43352 Dec 7 16:12 env*
$ sudo strace -u "$USERNAME" -ze '/uid|execve' ./env sh -c ''
execve("./env", ["./env", "sh", "-c", ""], 0x7ffde6ddf108 /* 17 vars */) = 0
execve("/usr/bin/sh", ["sh", "-c", ""], 0x7fff075efcd0 /* 17 vars */) = 0
getuid() = 10031
geteuid() = 0
geteuid() = 0
setuid(10031) = 0
geteuid() = 10031
+++ exited with 0 +++
これを行う一部のシェルには通常、-p
これを無効にするオプションがありますが、これは使用中ですsystem()
。その後、彼らは自分の権限を放棄しませんが、それでも自分の環境をあまり信頼しないように注意してください。
$ sudo strace -u "$USERNAME" -ze '/uid|execve' ./env sh -pc ''
execve("./env", ["./env", "sh", "-pc", ""], 0x7ffd4616dfb8 /* 17 vars */) = 0
execve("/usr/bin/sh", ["sh", "-pc", ""], 0x7ffef3883230 /* 17 vars */) = 0
getuid() = 10031
geteuid() = 0
+++ exited with 0 +++
ここでできることは、実際のuidと有効なuidの両方がゼロになるようにsetuid(0)
呼び出す前に行うことです。ただし、これはシェルが権限を放棄せず、その環境を信頼しないことを意味します。system()
だからこれは非常に悪い考えです。少なくともsudo
setuid実行可能ファイルからasを呼び出すsh
前に、setuidなどのコマンドで実行されたすべてのクリーンアップ操作を実行したいと思いますroot
。
たとえば、zsh
ここでは削除操作を実行せずに、次の操作を実行するために組み込みのuid変更をサポートしますsetuid()
。
$ sudo strace -u "$USERNAME" -ze '/uid|execve' ./env zsh -c 'UID=0; exec "$@"' zsh sh -c 'id -u'
execve("./env", ["./env", "zsh", "-c", "UID=0; exec \"$@\"", "zsh", "sh", "-c", "id -u"], 0x7ffc6de6e5e8 /* 17 vars */) = 0
execve("/usr/bin/zsh", ["zsh", "-c", "UID=0; exec \"$@\"", "zsh", "sh", "-c", "id -u"], 0x7ffda351af70 /* 17 vars */) = 0
getuid() = 10031
geteuid() = 0
getuid() = 10031
setuid(0) = 0
execve("/usr/bin/sh", ["sh", "-c", "id -u"], 0x562a89149d20 /* 21 vars */) = 0
getuid() = 0
geteuid() = 0
geteuid() = 0
0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=47576, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
子プロセスのsetuid実行可能ファイルから別々の実行可能ファイルを実行する必要がある場合は、適切なsystem()
操作(子プロセスでフォーク、実行、一部のシグナルブロック、および親プロセスで待機)を実行できますが、少なくともOverはスキップされますsh
。照会に依存するのではなく、実行可能ファイルへのフルパスを提供しようとしており、$PATH
いくつかの環境クリーンアップを実行する必要があるかもしれません。
1実際には通常、、、として使用されますsh
。-c
code
これは現代的な実装を意味しますsh
。code
-
またはで始めます+
。これでより多くの実装変更がある可能性があります。POSIX施行標準8版以降。