私はsetuid
これがどのように機能するかを理解しようとしています。
そのため、現在のユーザーだけを印刷するダミープログラムを作成しました。
#include<bits/stdc++.h>
using namespace std;
int main(){
cout << system("id -a") << "\n";
cout << system("whoami") << "\n";
}
my-binary
userの下に実行可能ファイルをコンパイルして作成しましたanmol
。
-rwxrwxr-x 1 anmol anmol 9972 Feb 1 16:54 my-binary
次に、setuid
次を使用してオプションを設定しますchmod +s
。
-rwsrwsr-x 1 anmol anmol 9972 Feb 1 16:54 my-binary
正常に実行すると、次の結果が表示されます。
uid=1000(anmol) gid=1000(anmol) groups=1000(anmol),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),122(sambashare)
anmol
別のユーザーに変更を使用してsu user2
実行すると、次のような結果が得られます。
uid=1001(user2) gid=1001(user2) groups=1001(user2)
user2
使ってsudo ./my-binary
実行すると
uid=1001(root) gid=1001(root) groups=1001(root)
root
私が理解したところによると、どのように実行しても毎回最初の出力を取得する必要はありませんか?
ここで他の同様の質問をチェックし、いくつかはファイルシステムがオプションでマウントされていることを確認するようにnosuid
提案して実行し、mount | /dev/sda1
出力を得ました。
/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
これはオプションが有効になっていないことを意味します。
期待した結果が得られない理由についてのヒントはありますか?
ベストアンサー1
ライブラリ関数はLinuxでsystem(3)
コマンド引数(、または)を渡して実行し、/bin/sh -c
このオプションを使用して呼び出さない限り、すべてのsetuidまたはsetgid権限を放棄します。/bin/sh
bash
dash
mksh
-p
Bashのマニュアルページは次のように述べています。
シェルの起動時に有効なユーザー(グループ)IDが実際のユーザー(グループ)IDと同じではなく、オプションが次の
-p
場合使用不可[...] 実効ユーザ ID は実ユーザ ID に設定されます。
dash
(/bin/sh
Debian / Ubuntuでは)これは次のとおりです。少し新しい:まだDebian 9 Stretch(2017)ではそうではありません。ただ Debian 専用です。変化、まだ上流ではありません源泉2020年2月4日現在。bash
これは、バージョン2.X(RedHat 7.X、2000に最初に含まれています)から利用可能でした。
これはまだそうではありません他のシェル(ksh93
などzsh
)または/bin/sh
他のシステム(OpenBSD、FreeBSD、Solaris。しかしNetBSDではない)と一緒に使用する変更bashのように動作します。)
お持ちの場合、特権モードが機能します。違うbashと比較すると、次のようになります。存在するデフォルトでは、シェルがsetuidモードで実行されている場合はオンにする必要があります。去るset +p
シェルがsetuid権限を削除するようにします。
を使用するには、setuidバイナリから直接シェルまたは実行可能なシェルスクリプトを実行し、system()
「popen()
分割の性質」を放棄し、次の方法で実際または有効な資格情報に完全に切り替える必要がありますsetres[ug]id
。
% cat a.cc
#include <unistd.h>
#include <stdlib.h>
int main(){
uid_t euid = geteuid();
setresuid(euid, euid, euid);
system("id");
}
% c++ a.cc
% chmod u+s a.out
% ./a.out
uid=1002(fabe)
% su -c ./a.out
uid=1002(fabe)
バイナリが実際に有効な資格情報を切り替えたことを確認するには、次のように外部プログラムを呼び出すのではなく、直接実行してくださいsystem()
。
#include <iostream>
#include <unistd.h>
#include <pwd.h>
using namespace std;
int main(){
uid_t euid = geteuid(); struct passwd *pw = getpwuid(euid);
cout << "euid=" << euid;
if(pw) cout << ", " << pw->pw_name;
cout << endl;
}