スポンサーリンク

このドキュメントの内容は、以下の通りです。

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]

スポンサーリンク
スポンサーリンク
 
いつもシェア、ありがとうございます!


もっと情報を探しませんか?

関連記事

最近の記事

人気のページ

スポンサーリンク
 

過去ログ

2020 : 01 02 03 04 05 06 07 08 09 10 11 12
2019 : 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

サイト

Vim入門

C言語入門

C++入門

JavaScript/Node.js入門

Python入門

FreeBSD入門

Ubuntu入門

セキュリティ入門

パソコン自作入門

ブログ

トップ


プライバシーポリシー