akarititle.png

SSH サービスでシステム管理者の操作を制限する

概要

このページでは、SSHサーバからログインシェルが実行される時にロールの選択を行うことにより、システム管理者の操作を制限する手順について紹介します。

ステップ1:ソースコードのコンパイル

使用するロールを決めます。このページでは「 Web サーバ管理者」「 Mail サーバ管理者」「セキュリティ管理者」の3つを使用します。

以下のソースコードをコンパイルします。このページでは、コンパイルされたプログラムの名前を /bin/sshd_login とします。また、SSHサーバのパス名を /usr/sbin/sshd とします。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SSHD_EXECUTABLE_PATH "/usr/sbin/sshd"

int main(int raw_argc, char *raw_argv[])
{
	int i;
	int argc;
	int envc;
	char *filename;
	char **argv;
	char **envp;
	{ /* Check that I'm an execute handler process.  */
		int fd = open("/proc/ccs/.execute_handler", O_RDONLY);
		close(fd);
		if (fd == EOF) {
			fprintf(stderr, "FATAL: I'm not execute_handler.\n");
			return 1;
		}
	}
	if (raw_argc < 7)
		return 1;
	filename = raw_argv[4];
	argc = atoi(raw_argv[5]);
	envc = atoi(raw_argv[6]);
	if (raw_argc != argc + envc + 7)
		return 1;
	for (i = 5; i < argc + 5; i++)
		raw_argv[i] = raw_argv[i + 2];
	raw_argv[argc + 5] = NULL;
	for (i = argc + 6; i < argc + envc + 6; i++)
		raw_argv[i] = raw_argv[i + 1];
	raw_argv[argc + envc + 6] = NULL;
	argv = raw_argv + 5;
	envp = raw_argv + argc + 6;
	/* "/usr/sbin/sshd" executes "/usr/sbin/sshd" with "-R" option. */
	if (argc == 2 && !strcmp(argv[1], "-R") &&
	    !strcmp(raw_argv[2], SSHD_EXECUTABLE_PATH) &&
	    !strcmp(filename, SSHD_EXECUTABLE_PATH)) {
		execve(filename, argv, envp);
		return 1;
	}
	/* Don't allow 'shell -c "command"' request. */
	if (argc == 3 && !strcmp(argv[1], "-c")) {
		fprintf(stderr, "You are not permitted to run %s\n", argv[2]);
		return 1;
	}
	printf("Select your role.\n\n");
	printf("1: Web administrator\n");
	printf("2: Mail administrator\n");
	printf("3: Security administrator\n\n");
	while (1) {
		int c = getchar();
		if (c == EOF)
			break;
		if (c == '1') {
			execve("/bin/webadmin-auth", argv, envp);
			break;
		}
		if (c == '2') {
			execve("/bin/mailadmin-auth", argv, envp);
			break;
		}
		if (c == '3') {
			execve("/bin/securityadmin-auth", argv, envp);
			break;
		}
	}
	return 1;
}

以下の内容を /bin/webadmin-auth として保存し、実行許可を与えます。

#! /bin/sh
echo "Enter password for web administrator."
stty -echo
read
stty echo
[ "$REPLY" == "webadmin" ] && exec /bin/bash
echo "Authentication failure"
sleep 5
exit 1

以下の内容を /bin/mailadmin-auth として保存し、実行許可を与えます。

#! /bin/sh
echo "Enter password for mail administrator."
stty -echo
read
stty echo
[ "$REPLY" == "mailadmin" ] && exec /bin/bash
echo "Authentication failure"
sleep 5
exit 1

以下の内容を /bin/securityadmin-auth として保存し、実行許可を与えます。

#! /bin/sh
echo "Enter password for security administrator."
stty -echo
read
stty echo
[ "$REPLY" == "securityadmin" ] && exec /bin/bash
echo "Authentication failure"
sleep 5
exit 1

ステップ2: AKARI のインストールと初期化

AKARI をインストールしてから、以下のコマンドを実行して初期設定を行ってください。

# /usr/lib/ccs/init_policy --module_name=akari

その後、 AKARI カーネルで再起動する前に以下の操作を行ってください。

/usr/sbin/sshd が実行された場合にはドメイン遷移が初期化されるようにするために、 /etc/ccs/exception_policy.conf に以下の内容を追加します。

initialize_domain /usr/sbin/sshd from any

/usr/sbin/sshd からのプログラムの実行要求が /bin/sshd_login に渡されるようにするために、 /etc/ccs/domain_policy.conf に以下の内容を追加します。

<kernel> /usr/sbin/sshd
task auto_execute_handler /bin/sshd_login

ステップ3:学習と運用

以上で設定は完了です。 AKARI カーネルで再起動してください。

クライアント側から ssh でサーバ側にアクセスしてください。ログイン認証後に /bin/sshd_login によるプロンプトが表示されることを確認したら、 Ctrl-C を押してログアウトしてください。これで、 /bin/sshd_login のためのドメインである <kernel> /usr/sbin/sshd /bin/sshd_login が作成されました。

/bin/sshd_login から起動される操作を制限するために、学習モードを割り当てます。

# /usr/sbin/ccs-setprofile -r 1 '<kernel> /usr/sbin/sshd /bin/sshd_login'

クライアント側から ssh でサーバ側にアクセスしてください。ログイン認証後に /bin/sshd_login が表示したプロンプトに対して 1 を入力し、 /bin/webadmin-auth が表示したプロンプトに対して webadmin を入力してください。これで、「 Web サーバ管理者」のためのドメインである <kernel> /usr/sbin/sshd /bin/sshd_login /bin/webadmin-auth /bin/bash が作成されました。

その後、「 Web サーバ管理者」に対して許可したい操作を行います。冒頭の動画では以下の操作をしています。

# service httpd restart
# cd /var/www/html/
# tar -zxf ~/htdocs.tar.gz --strip 1
# less /var/log/httpd/access_log

許可したい操作が終わったらログアウトしてください。

クライアント側から ssh でサーバ側にアクセスしてください。ログイン認証後に /bin/sshd_login が表示したプロンプトに対して 2 を入力し、 /bin/mailadmin-auth が表示したプロンプトに対して mailadmin を入力してください。これで、「 Mail サーバ管理者」のためのドメインである <kernel> /usr/sbin/sshd /bin/sshd_login /bin/mailadmin-auth /bin/bash が作成されました。

その後、「 Mail サーバ管理者」に対して許可したい操作を行います。冒頭の動画では以下の操作をしています。

# service sendmail restart
# mailq
# less /var/log/maillog

許可したい操作が終わったらログアウトしてください。

クライアント側から ssh でサーバ側にアクセスしてください。ログイン認証後に /bin/sshd_login が表示したプロンプトに対して 3 を入力し、 /bin/securityadmin-auth が表示したプロンプトに対して securityadmin を入力してください。これで、「セキュリティ管理者」のためのドメインである <kernel> /usr/sbin/sshd /bin/sshd_login /bin/securityadmin-auth /bin/bash が作成されました。

その後、「セキュリティ管理者」に対して許可したい操作を行います。冒頭の動画では以下の操作をしています。

# less /var/log/tomoyo/reject_log.conf

許可したい操作が終わったらログアウトしてください。

確認モードを割り当て、許可したい操作を行えるかどうか確認してください。

# /usr/sbin/ccs-setprofile -r 2 '<kernel> /usr/sbin/sshd /bin/sshd_login'

強制モードを割り当てれば完成です。

# /usr/sbin/ccs-setprofile -r 3 '<kernel> /usr/sbin/sshd /bin/sshd_login'

説明

/bin/webadmin-auth /bin/mailadmin-auth /bin/securityadmin-auth という3つのプログラムを /usr/sbin/sshd とログインシェルとの間に挿入してやることにより、親ドメインが異なる3つのドメイン( "<kernel> /usr/sbin/sshd /bin/sshd_login /bin/webadmin-auth /bin/bash", "<kernel> /usr/sbin/sshd /bin/sshd_login /bin/mailadmin-auth /bin/bash", "<kernel> /usr/sbin/sshd /bin/sshd_login /bin/securityadmin-auth /bin/bash" )を作成し、それぞれに必要なアクセス許可だけを与えるという形で権限を分割しています。このプログラムはサンプルなのでシェルスクリプトで済ませていますが、実際に使用する場合にはちゃんとしたユーザ認証を行うプログラムを作成してください。

AKARI の execute_handler 機能が /usr/sbin/sshd からのプログラムの実行要求を横取りして、 /bin/sshd_login に渡しています。 /bin/sshd_login がロールを選択させるためのプロンプトを表示して、ユーザからの応答を受け取ります。

システムのユーザ認証を通過後なので、シェルの実行要求を伴わないSSHの機能は許可されています。ポートフォワーディングの制限なども行いたい場合は、通常通り学習モードで動作を学習させて、強制モードで動作を制限してやる必要があります。

それぞれのドメインではプログラムを実行するたびにドメイン遷移が発生します。ドメイン遷移をさせたくない場合は、 /etc/ccs/exception_policy.conf に以下のように keep_domain を指定することができます。

keep_domain any from <kernel> /usr/sbin/sshd /bin/sshd_login /bin/webadmin-auth /bin/bash
keep_domain any from <kernel> /usr/sbin/sshd /bin/sshd_login /bin/mailadmin-auth /bin/bash
keep_domain any from <kernel> /usr/sbin/sshd /bin/sshd_login /bin/securityadmin-auth /bin/bash