質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • Linux

    3650questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

  • CentOS

    2645questions

    CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

linuxのsuidを設定した実行ファイルで、実行者が所有者にならない

受付中

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 3,249

ryuuinn

score 67

はじめまして。
linuxを使っていてわからないことがあったので教えて下さい。

ファイルのパーミションについて学んでいた時に、SUIDというものに出会ったので、
早速実験してみましたが、参考にした情報どおりの挙動にならなかったので原因が分かりましたらご教示頂きたいです。

OS: CentOS 6.5

 実験手順


 1. 実験に使う実行ファイルをつくる(744)


[riki permTest]$ cat hello 
#/bin/bash
 
# 実行者のUIDとユーザ名を表示する
echo $UID $USER

[riki permTest]$ ls -la .
合計 16
drwxrwsr-x  2 riki riki 4096  8月 25 00:25 2015 .
drwxr-sr-x 31 riki riki 4096  8月 25 00:25 2015 ..
-rwxr--r--  1 riki riki       29  8月 25 00:25 2015 hello


 2. 所有者が実行してみる


[riki permTest]$ ./hello 
503 riki

これは意図どおりです。

 3. 他のユーザが実行してみる


hogeユーザで実行してみる

[hoge permTest]$ ./hello
-bash: ./hello: 許可がありません

実行権限を与えてないので、これも意図どおり。

 4. 他のユーザに実行権限を与えて、他のユーザが実行してみる


他のユーザにもhelloに実行権限を与える

[riki permTest]$ chmod o+x hello 
[riki permTest]$ ls -la .
合計 16
drwxrwsr-x  2 riki riki 4096  8月 25 00:25 2015 .
drwxr-sr-x 31 riki riki 4096  8月 25 00:25 2015 ..
-rwxr--r-x  1 riki riki       29  8月 25 00:25 2015 hello

もう一回hogeで実行

[hoge permTest]$ ./hello 
500 hoge

実行出来ました。そしてhogeが実行したことになってます。
これも意図どおり。

 5. uidを設定して、hogeで実行してみる


いよいよ本題です。helloにsuidを設定してみます。

[riki permTest]$ chmod u+s hello
[riki permTest]$ ls -la .
合計 16
drwxrwsr-x  2 riki riki 4096  8月 25 00:25 2015 .
drwxr-sr-x 31 riki riki 4096  8月 25 00:25 2015 ..
-rwsr--r-x  1 riki riki       29  8月 25 00:25 2015 hello

suidが設定された状態でhogeが実行(503 rikiと表示されるハズ)

[hoge permTest]$ ./hello 
500 hoge

これが意図と違いました。

 質問


参考にしたサイト

上記のサイトを見て、suidが設定された実行ファイルは、他のユーザが実行しても実行ユーザがファイルの所有者になると思い、今回のような実験をしてみました。

期待していた結果としては、suidを設定したhelloスクリプトはhogeユーザが実行した時も503 rikiと表示してくると思っていましたが、普通に500 hogeとなってしまいました。。

何か私の認識で勘違いしている部分があるのでしょうか・・><
期待通りの結果になっていない原因をご教示いただけますと幸いです!
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

(シェバング行が書かれた)ただのスクリプトだと、実行可能でも setuid は効きません。
実行可能なバイナリである必要があります。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

int main()
{
    uid_t uid = geteuid();
    struct passwd *pw = getpwuid(uid);
    printf("%d %s\n", uid, pw->pw_name);
    return 0;
}

gcc a.c -o hello
./hello # 500 ore
sudo chown daemon hello
sudo chmod u+s hello
./hello # 2 daemon

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

セキュリティ上の理由でスクリプトにsetuidは効きません。下記参照。
1990年代からあるUnix FAQ

追記:
本題から逸れますが、実効ユーザーの確認は、UID、USERでは出来ません。
bashの場合、実効ユーザーIDは、EUID です。また、USERは /etc/profileで設定されてたりするものなので、単にbashを起動しただけではユーザーが異なっても再設定されないでしょう。
シェルスクリプトからの実効ユーザーの確認にはidコマンドを使ってください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

otnさんのご説明の通り、セキュリティー上の理由で、スクリプトにはsetuidは効きません。
しかしシステム(カーネル)の設定によっては、例外的にperlスクリプトのみsetuid/gidの仕組みを利用できます。
(参考)
(もっとも、カーネルの設定で禁止されている場合にはどうしようもありません。)

どうしても特定のスクリプトでsetuid/gidの仕組みを利用したい場合には、そのスクリプトを呼び出すラッパーをcか何かで作成し、ラッパー側にsetuidを設定、スクリプト側にはシェバン行に-pオプションを付加し「特権モード」を有効化することで、目的を達成することができます。

自分は、以前、業務上の必要に迫られて以下のようなラッパーを使用して実際に使用していたことがあります。引数も普通にシェルスクリプトへ渡せます。
(古い記憶を頼りに記載したので、誤記があったらごめんなさい…)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>

extern char **environ;

int main(int argc, char *argv[]) {
    int     pid;
    int     status;
    int     i;
    int     rc = 1;
    char  command[256];

    /* 実行スクリプト設定 */
    strcpy(command, "/path/to/script");        // 対象スクリプトの絶対パスを設定

    pid = fork();

    switch(pid) {
    case 0:
        /* 子プロセス */
        /* スクリプト実行 */
        setgid( ggg );        // setuidを設定したいユーザーのgid
        setuid( uuu );        // setuidを設定したいユーザーのuid
        if (execve(command, argv, environ) < 0) {
            exit(EXIT_FAILURE);
        }
        break;
    case -1:
        /* 失敗 */
        exit(EXIT_FAILURE);
        break;
    default:
        /* 親プロセス */
        /* 子プロセスの完了を待つ */
        waitpid(pid, &status, 0);
        if (WIFEXITED(status)) {
            rc = WEXITSTATUS(status);
        }
        break;
    }

    return(rc);
}
このプログラムを普通にgccでコンパイルし、望みのユーザーにsetuidします。
一方、呼び出されるスクリプト側はシェバン行に-pオプションを指定し特権モードを有効にしておきます。
#!/bin/bash -p

# 任意の処理
スクリプト本体のオーナー・パーミッションは、ラッパーから実行可能であれば大丈夫だったと思います。

セキュリティー上のリスクを伴うので、慎重に使用してください。


ちょっと補足します。
実行ユーザがファイルの所有者になると思い…

と記載されていましたが、setuidを利用しても「実ユーザー」自体は変わりません。「実効ユーザー」の権限で実効可能になるということです。実効ユーザーという概念が(自分にとっては最初)ちょっと紛らわしかったので、補足しておきます。
(参考)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Linux

    3650questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

  • CentOS

    2645questions

    CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。