suid 実行可能ファイルは特権を昇格させませんが、「sudo」は特権を昇格させます。

suid 実行可能ファイルは特権を昇格させませんが、「sudo」は特権を昇格させます。

私はパスワードや確認を必要とせずにラップトップをすばやく終了できるプログラムを書こうとしています。ノートブックはLinux、特にManjaroを実行します。

これを行うには、固定引数で実行され、シェルも生成する実行可能setuidファイルを作成しようとしています。私はプログラムを短く保つためにこれを使用しています。セキュリティの観点からは悪い考えです。downnowshutdownsystem

// downnow.c
#include <stdlib.h>

int main() {
  system("shutdown --no-wall --halt now");
  return 0;
}

その後、 をコンパイルしてdownnowに移動し、/bin所有者を変更し、 setuid および setgid 権限を付与しました。

$ sudo chown root /bin/downnow 

$ sudo chgrp root /bin/downnow 

$ sudo chmod u+s /bin/downnow 

$ sudo chmod g+s /bin/downnow 

ただし、権限のないユーザーとして実行しようとすると、downnowsystemdと通信できません。

$ downnow 
Failed to halt system via logind: Interactive authentication required.
Failed to talk to init daemon.

ingの前後に同じメッセージが表示されますch{own,grp,mod}

stat/bin/downnowレポートには同じ権限があります/usr/bin/sudo

$ stat /bin/downnow 
  File: /bin/downnow
  Size: XXXX        Blocks: XX         IO Block: XXXX   regular file
Device: XXXXX/XXXXX Inode: XXXXXX     Links: 1
Access: (6755/-rwsr-sr-x)  Uid: (    0/    root)   Gid: (    0/    root)

$ stat /usr/bin/sudo
  File: /usr/bin/sudo
  Size: XXXXXX      Blocks: XXX        IO Block: XXXX   regular file
Device: XXXXX/XXXXX Inode: XXXXXXX     Links: 1
Access: (4755/-rwsr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)

完璧に動作するのに、なぜdownnow権限を高めることができないのですか?sudo

答え1

許可ビットを設定すると、アプリケーションはその呼び出しを使用setuidできますが、それ自体は権限を変更しません。これを行うには、を使用してuidを設定する必要がありますsetuid(uid_t uid)。詳しくはマニュアルページをご覧ください。https://linux.die.net/man/2/setuid

geteuid()現在有効なuid(つまり、setuid権限を持つファイルの所有者)を取得するために使用できます。マニュアルページを参照してください。https://linux.die.net/man/2/geteuid

例:

// downnow.c
#include <stdlib.h>
#include <unistd.h>

int main() {
  setuid(geteuid());
  system("shutdown --no-wall --halt now");
  return 0;
}

答え2

setuid(2)おそらく電話を受けられなかったからだろう。これらの通貨の前後比較は次のとおりです。

#include <err.h>
#include <stdio.h>
#include <unistd.h>

#define GETUIDS(p) (p[0]=getuid(),p[1]=geteuid())

int main(void)
{
    uid_t ids[2];
    GETUIDS(ids);
    fprintf(stderr, "real %lu effective %lu\n", (unsigned long) ids[0],
            (unsigned long) ids[1]);
    if (setuid(0) == -1)
        err(1, "setuid failed");
    GETUIDS(ids);
    fprintf(stderr, "real %lu effective %lu\n", (unsigned long) ids[0],
            (unsigned long) ids[1]);
    return 0;
}

そしてラッパーもそれほど安全ではありません。マルチユーザーシステムにエスケープしないことを願っています。不要なシェル呼び出しを避け(shellshock型のエクスプロイトや...などの冗長環境変数の奇妙な処理が好きでない限りbash)、代わりにプロセスを直接exec(3)呼び出しに置き換える方が安全です。shutdown

#include <err.h>
#include <unistd.h>

int main()
{
    if (setuid(0) == -1)
        err(1, "setuid failed");
    //execl("/usr/bin/echo", "echo", "--no-wall", "--halt", "now",
    execl("/usr/sbin/shutdown", "shutdown", "--no-wall", "--halt", "now",
          (char *) 0);
    err(1, "exec failed");
    return 1;
}

後で予期しないシャットダウンが複数回発生しました。

centos7# make badcode
cc     badcode.c   -o badcode
centos7# mv badcode /badcode
centos7# chmod u+s /badcode
centos7# su - jhqdoe
Last login: Thu Jan 10 01:39:03 UTC 2019 on pts/0
[jhqdoe@centos7 ~]$ /badcode
Connection to 192.168.99.2 closed by remote host.
Connection to 192.168.99.2 closed.

関連情報