LoginSignup
1
1

More than 3 years have passed since last update.

SUIDを使って、読み取り権限のないファイルを読み込みたい

Last updated at Posted at 2020-11-28

やりたいこと

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の中身は以下。

secret/file.txt
Wa-hoo!
Oh yeah!
Mario time!

続いてload_secretだが、今回は下記のようなPythonでコードを書いてバイナリを作ることにする。(バージョンは3系を利用)

load_secret.py
#!/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をインストールして、バイナリファイルを作成
※便宜上、プロンプトの()内に現在のユーザ名を記載

$(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!
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1