setuidが機能しない

setuidが機能しない

私はsetuidこれがどのように機能するかを理解しようとしています。

そのため、現在のユーザーだけを印刷するダミープログラムを作成しました。

#include<bits/stdc++.h>
using namespace std;


int main(){
    cout << system("id -a") << "\n";
    cout << system("whoami")  << "\n";
}

my-binaryuserの下に実行可能ファイルをコンパイルして作成しました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/shbashdashmksh-p

Bashのマニュアルページは次のように述べています。

シェルの起動時に有効なユーザー(グループ)IDが実際のユーザー(グループ)IDと同じではなく、オプションが次の-p場合使用不可[...] 実効ユーザ ID は実ユーザ ID に設定されます。

dash/bin/shDebian / 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;
}

おすすめ記事