Unix suidなコマンドからsystem関数を呼ぶと子プロセスではrootのeuidが失われる
スポンサーリンク
このドキュメントの内容は、以下の通りです。
root ユーザがオーナのファイルで、suid ビットがオンの場合、そのコマンドから system 関数を呼び出して、
さらに別のコマンドを実行した場合、子プロセスでは、
euid の root 権限が失われる。
getresuid.c
#include <stdio.h> #include <stdlib.h> #include <err.h> #include <sys/types.h> #include <unistd.h> int main (int argc, char *argv[]) { int r = 0; uid_t ruid, euid, suid; r = getresuid (&ruid, &euid, &suid); if ( r == -1 ) { err (EXIT_FAILURE, "getresuid"); } (void) printf ( "ruid: %d\n" "euid: %d\n" "suid: %d\n", ruid, euid, suid); exit (EXIT_SUCCESS); }
system.c
#include <stdio.h> #include <stdlib.h> #include <err.h> #include <unistd.h> #include <sys/types.h> void show () { int r = 0; uid_t ruid, euid, suid; r = getresuid (&ruid, &euid, &suid); if ( r == -1 ) { err (EXIT_FAILURE, "getresuid"); } (void) printf ( "ruid: %d\n" "euid: %d\n" "suid: %d\n", ruid, euid, suid); } int main (int argc, char *argv[]) { char *cmd = "getresuid"; (void) printf ("dump ids\n"); show (); (void) printf ("system(%s)\n", cmd); system (cmd); exit (EXIT_SUCCESS); }
Makefile
all: getresuid suid_system system suid_execve execve clean:: @rm -f getresuid suid_system system suid_execve execve getresuid: getresuid.c $(CC) $(CFLAGS) $< -o $@ suid_getresuid: getresuid cp $< $@ sudo chown root:wheel $@ sudo chmod u+s $@ system: system.c $(CC) $(CFLAGS) $< -o $@ execve: execve.c $(CC) $(CFLAGS) $< -o $@ suid_execve: execve cp $< $@ sudo chown root:wheel $@ sudo chmod u+s $@ suid_system: system cp $< $@ sudo chown root:wheel $@ sudo chmod u+s $@ setuid_system: setuid_system.c $(CC) $(CFLAGS) $< -o $@ suid_setuid_system: setuid_system cp $< $@ sudo chown root:wheel $@ sudo chmod u+s $@
実験
通常のユーザで suid がオフのコマンドで試してみます。
なんの変哲もない結果になります。
薫% system dump ids ruid: 500 euid: 500 suid: 500 system(getresuid) ruid: 500 euid: 500 suid: 500
suid がオンのコマンドで試してみます。
薫% suid_system dump ids ruid: 500 euid: 0 suid: 0 system(getresuid) ruid: 500 euid: 500 suid: 500
system関数から実行された getresuid では、
euid と suid の root 権限が剥奪され、ruid の user で上書き
されています。
これは、 system() 関数が sh -c でコマンドを実行していることに
起因します。
解決策
いいかどうか、というのは別にして、方法として、2つのやり方があります。
- system()関数を利用する前提で、setuid(0) する
- execve を使う
setuid_system.c
system() 関数を呼び出す前に setuid(0) します。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> void show () { int r = 0; uid_t ruid, euid, suid; r = getresuid (&ruid, &euid, &suid); if ( r == -1 ) { err (EXIT_FAILURE, "getresuid"); } (void) printf ( "ruid: %d\n" "euid: %d\n" "suid: %d\n", ruid, euid, suid); } int main (int argc, char *argv[]) { char *cmd = "getresuid"; (void) printf ("dump ids\n"); show (); (void) printf ("setuid(0)"); setuid (0); (void) printf ("dump ids\n"); show (); (void) printf ("system(%s)\n", cmd); system (cmd); exit (EXIT_SUCCESS); }
ruid を setuid で 0 にしてしまいます。
結果として、 ruid, euid, suid が 0 になるため、
sh が起動してコマンドが実行されても、ruid が上書きされることはありません。
薫% suid_setuid_system dump ids ruid: 500 euid: 0 suid: 0 setuid(0)dump ids ruid: 0 euid: 0 suid: 0 system(getresuid) ruid: 0 euid: 0 suid: 0
execve.c
setuid(0)ではなく、execveでコマンドを起動する場合は、
以下のとおりです。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> void show () { int r = 0; uid_t ruid, euid, suid; r = getresuid (&ruid, &euid, &suid); if ( r == -1 ) { err (EXIT_FAILURE, "getresuid"); } (void) printf ( "ruid: %d\n" "euid: %d\n" "suid: %d\n", ruid, euid, suid); } int main (int argc, char *argv[]) { char *cmd = "getresuid"; (void) printf ("dump ids\n"); show (); (void) printf ("execve(%s)\n", cmd); char *_argv[] = { cmd, NULL }; char *env[] = { NULL }; int r = execve (cmd, _argv, env); err (EXIT_FAILURE, "execve(%s)", cmd); exit (EXIT_SUCCESS); }
execve() で実行されたコマンドは、euid が 0 のままになっており
権限は、失っていません(当たり前)。
薫% ./suid_execve dump ids ruid: 500 euid: 0 suid: 0 execve(getresuid) ruid: 500 euid: 0 suid: 0
参照しているページ (サイト内): [2012-02-23-1]
スポンサーリンク
スポンサーリンク
いつもシェア、ありがとうございます!
もっと情報を探しませんか?
関連記事
最近の記事
- パナソニック ジェットウォッシャードルツ EW-DJ61-Wのホースの修理
- LinuxセキュリティモジュールIntegrity Policy Enforcement
- アマゾンのEcho Show 5を買ったのでレビューします
- アマゾンのサイバーマンデーはAlexa Echo Show 5が安い
- Android スマートフォン OnePlus 7T と OnePlus 7の違い
- Android スマートフォン OnePlus 7 をAndroid10にアップデートしてみた
- クレジットカードのバーチャルカードの比較のまとめ
- 活動量計 Xiaomi Mi Band 4を買ってみたのでレビュー
- Android スマートフォン OnePlus 7 のレビュー
- AliExpressでスマートフォンを買い物してみた
- パソコンのホコリ対策 レンジフードフィルターと養生テープ
- 80PLUS GOLDのPC電源ユニットAntec NeoEco 750 Goldのレビュー
- イギリスの付加価値税 VAT は払い戻しを受けられる
- イギリスのロンドンでスーツケースなど荷物を預けられる場所は
- イギリスのロンドンで地下鉄やバスに乗るならオイスターカードを使おう
- イギリスのヒースロー空港からロンドン市内への行き方
- 航空便でほかの航空会社に乗り継ぎがある場合のオンラインチェックイン
- SFC会員がANA便ではなくベトナム航空のコードシェアを試して解ったこと
- ベトナムの入国審査でeチケットの掲示が必要だった話
- シアトルの交通ICカードはオルカカード(Orca)です
人気のページ
- Windows7 IME 辞書ツールで単語の登録に失敗しました
- C言語 popen()でコマンドを実行して出力を読み込む
- Windows7で休止状態にする方法
- CentOS MySQLの起動、停止、再起動
- loggerコマンドでsyslogにエラーを出力する方法
- パソコンパーツの買取をしてくれる店のまとめ
- Java Mapの使い方 get(),put(),remove(),size(),clear()
- 楽天のRポイントカードを作ってみた
- iPhone 5 から iPhone 6 に乗り換えたのでレビュー
- netstatコマンドのステータスの意味
スポンサーリンク
過去ログ
2020 : 01 02 03 04 05 06 07 08 09 10 11 122019 : 01 02 03 04 05 06 07 08 09 10 11 12
2018 : 01 02 03 04 05 06 07 08 09 10 11 12
2017 : 01 02 03 04 05 06 07 08 09 10 11 12
2016 : 01 02 03 04 05 06 07 08 09 10 11 12
2015 : 01 02 03 04 05 06 07 08 09 10 11 12
2014 : 01 02 03 04 05 06 07 08 09 10 11 12
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12