それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

setsuid で実行ユーザが固定できるってのはどこまで?シェルスクリプトはsuidできる?

setsuid で実行ユーザが固定できるってのはどこまで?

シェルスクリプトってsuidできなかったよね。ということを確認してみる。

suidを試してみる。

まずは、suid を素直に試してみることにする。 実行可能なバイナリを準備する。

#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>


int main ( char** args, int argc ){

  printf("user is %s\n", getlogin());

  struct passwd* pw = getpwuid(geteuid());
  printf("euid is %s\n", pw->pw_name );

}

これをコンパイルして実行してみる。

takuya@:~$ gcc test.c -o out
takuya@:~$ ./out 
user is takuya
euid is takuya

ちゃんと、実行ユーザ(euid)と現在のログインユーザ(user)が表示される。

setsuid してみる。

takuya@:~$ sudo chown  www-data:www-data out
takuya@:~$ sudo chmod u+s  out
takuya@:~$ ./out
user is takuya
euid is www-data
takuya@:~$

今度は、実行ユーザ(euid)がwww-data になり、ちゃんと別ユーザーで実行されていることがわかる。

シェルスクリプトならどうだ? できないね。そうだね。

#!/usr/bin/env bash
whoami
who | awk '{ print $1 }'

sudo ならユーザIDが変化するけど。

takuya@:~$ sudo  -u www-data  ./sample.sh
www-data
takuya
takuya@:~$ sudo ./sample.sh
root
takuya

chmod でsuidをやってみると。

takuya@:~$ sudo chown www-data sample.sh
takuya@:~$ sudo chmod u+s  sample.sh
takuya@:~$ ll sample.sh
-rwsrwxr-x 1 www-data www-data 56 11月  9 13:34 sample.sh*
takuya@:~$ ./sample.sh
takuya
takuya

なぜなら、シェルスクリプトを実行したら、 shebang指定されたbashが起動し、ボディ文字列が標準入力(的なナニカ)としてbashへ渡されるだけである。

そのためsetsuidで実行できるわけがない。

代替手段

  • sudo を execする
  • set suid したbashを用意する。
  • shebang を工夫する

sudo を使う場合

これで、rootとして実行される。

#!/usr/bin/env bash
[ "root" != "$USER" ] && exec sudo  $0 "$@"
whoami
who | awk '{ print $1 }'

これで、www-dataとして実行される。

#!/usr/bin/env bash
[ "www-data" != "$USER" ] && exec sudo sudo -u www-data $0 "$@"
whoami
who | awk '{ print $1 }'

suid は難しい問題。

set suid の設定これは、すごく不思議な問題で、トラブルが多いので、とても慎重に考える必要がある。いちばん簡単で安全なのは、set suid したコマンドを ~/.bin に設定しておいておくことである。たとえば、bashをコピーしset suid して別の場所に設置するが考えられるが、セキュリティ・ホールを生み出してしまう。だからSUIDDでShebangを使うのは難しい。どうしても必要ならコマンドを実行(execv)するコマンドをCやRUST/Goで記述して、バイナリ実行する必要がある。

とりあえず、suid はシェルスクリプトは対象外。と覚えておくことにする。

この話は掘り下げると「沼」だとわかったのでここまで。

参考資料。

http://www.faqs.org/faqs/unix-faq/faq/part4/section-7.html