やりたいこと
Linux上で、あるユーザにプログラムを実行させたい。プログラムでは別のファイルを読み込む必要があるのだが、読み込むファイルの内容は実行ユーザには見せずに秘密にしたい。そんな都合の良い事って一体できるのかしら。
今回試してみる例
- 登場するユーザ
- mario : 各ファイルの所有者
- koopa : 実行ファイルを実行するユーザ。秘密ファイルにはアクセスさせたくない
実行ファイルと秘密にしたいファイルが、以下のように格納されているとする。
.
├── load_secret # 実行ファイル。秘密にしたいファイルをReadする
└── secret
└── file.txt # 秘密にしたいファイル
secret/
ディレクトリは以下のようなパーミッションになっており、mario
しかアクセスできない。
# ls -l | grep " secret"
drwxr-x--- 1 mario mario 4096 Nov 28 12:48 secret
実行ファイルにSUID(またはSGID)を付与すれば可能
とりあえずは結論。
実行ファイルのパーミッションが以下の状態になればOK。これをSUID(Set User ID)という。
# ls -l | grep " load_"
-rwsr-xr-x 1 mario mario 14832832 Nov 28 12:48 load_secret
ポイントは、ファイル所有者の実行権限が「s」となっているところ。このシンボルがついている場合、どのユーザが実行しても必ずファイルの所有者(本例ではmario
)の権限で実行される。そのため、例えば以下のようにkoopa
になって実行しても、直接はアクセスできないsecret/file.txt
を読み取ることができる。
# su koopa
$ ./load_secret
(secret/file.txtを読み取り、プログラムは無事に終了する)
パーミッションの「s」は例えば、chmod
コマンドで以下のようにすれば付与可能
# ls -l | grep " load_"
-rwxr-xr-x 1 mario mario 14832832 Nov 28 12:48 load_secret
# chmod u+s load_secret
# ls -l | grep " load_"
-rwsr-xr-x 1 mario mario 14832832 Nov 28 12:48 load_secret
参考までに、「s」はグループに対しても付与可能。これをSGID(Set Group ID)という。
SGIDの場合は、任意のユーザがグループ権限でファイルを実行する設定となる。
# ls -l | grep " load_"
-rwxr-xr-x 1 mario mario 14832832 Nov 28 12:48 load_secret
# chmod g+s load_secret
# ls -l | grep " load_"
-rwxr-sr-x 1 mario mario 14832832 Nov 28 12:48 load_secret
動作確認
本当にできるのか実際に試してみる。
まず、secret/file.txt
の中身は以下。
Wa-hoo!
Oh yeah!
Mario time!
続いてload_secret
だが、今回は下記のようなPythonでコードを書いてバイナリを作ることにする。(バージョンは3系を利用)
# !/usr/bin/env python
# -*- coding:utf-8 -*-
if __name__ == '__main__':
with open("./secret/file.txt", "r") as f:
file_str = f.read()
print(file_str) # ファイルの中身表示(秘密だから実際はやらないだろうが…)
Pythonスクリプトのバイナリ化は「pyinstaller」というのでできるらしいのでこれを利用する。
- pyinstallerの参考サイト
pyinstallerをインストールして、バイナリファイルを作成
※便宜上、プロンプトの()内に現在のユーザ名を記載
$(mario) pip install pyinstaller
$(mario) pyinstaller load_secret.py --onefile
バイナリファイルは./dist
配下にできるので、カレントにコピー
$(mario) cp ./dist/load_secret .
SUIDの権限を付与
$(mario) chmod u+s load_secret
$(mario) ls -l | grep " load_"
-rwsr-xr-x 1 mario mario 14832832 Nov 28 12:48 load_secret
koopa
になって実行すると、直接は見れないファイルを読み込めることを確認!
# su koopa
$(koopa) ./load_secret
Wa-hoo!
Oh yeah!
Mario time!