英語613639 views
数学講師2886227 views
世界の国564520 views
高校物理160203 views
中学英語811710 views
中学社会668760 views
高校国語788336 views
高校化学2924392 views
LaTeX962153 views
Computer368106 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

setuid/setgid ビットと Python スクリプト

setuid/setgid ビットは実行ファイルに特別な権限を与える仕組みだ。しかし Python スクリプトでは期待どおりに動作しないことが多い。

setuid/setgid とは

通常、プログラムは実行したユーザーの権限で動作する。setuid ビットが設定されていると、ファイルの所有者の権限で動作する。

通常の実行

プログラムは実行ユーザーの UID/GID で動作する

setuid 付きの実行

プログラムはファイル所有者の UID で動作する。root 所有なら root 権限で動作する

# setuid ビットの例: passwd コマンド
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 Jan 1 00:00 /usr/bin/passwd
#    ^-- s は setuid ビット

# 一般ユーザーが実行しても、root 権限で /etc/shadow を編集できる

Python スクリプトに setuid は効かない

Python スクリプトに setuid ビットを設定しても、期待どおりに動作しない。

# setuid を設定(意味がない)
sudo chown root:root script.py
sudo chmod u+s script.py

ls -l script.py
# -rwsr-xr-x 1 root root 100 Jan 1 00:00 script.py

# 実行しても root 権限にならない
./script.py

これはセキュリティ上の理由で、多くの Unix 系 OS がスクリプトの setuid を無視するためだ。

なぜスクリプトの setuid は危険か

シェバン行の脆弱性

#!/usr/bin/python を含むスクリプトは、カーネルが /usr/bin/python script.py として実行する。この間にスクリプトを差し替える攻撃(race condition)が可能だった。

インタプリタの複雑さ

Python インタプリタは環境変数(PYTHONPATH など)に影響される。攻撃者が環境変数を操作して悪意のあるコードを実行させる可能性がある。

Linux は「nosuid」マウントオプションやカーネルの設定でスクリプトの setuid を無効化している。

Python で特権を得る方法

Python スクリプトで root 権限が必要な場合、いくつかの代替手段がある。

sudo で実行

最も単純で安全。ユーザーが明示的に権限昇格を許可する。

setuid バイナリラッパー

C で書いた setuid バイナリから Python スクリプトを呼び出す。

capabilities

Linux の capabilities を使って、root 権限の一部のみを付与する。

setuid ヘルパープログラム

pkexec、dbus 経由のサービスなど、権限昇格を安全に行う仕組みを利用する。

sudo の例

# script.py - root 権限が必要な処理
import os
import sys

if os.geteuid() != 0:
    print("Root権限が必要です。sudo で実行してください。")
    sys.exit(1)

# root 権限での処理
with open("/etc/shadow", "r") as f:
    print("shadow ファイルを読めました")
sudo python script.py

C ラッパーの例

どうしても setuid が必要な場合、C ラッパーを使う。

// wrapper.c
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    // 環境変数をクリア(セキュリティ対策)
    clearenv();
    
    // 安全な環境変数だけ設定
    setenv("PATH", "/usr/bin:/bin", 1);
    
    // Python スクリプトを実行
    execl("/usr/bin/python3", "python3", "/opt/myapp/script.py", NULL);
    
    return 1;
}
# コンパイルして setuid を設定
gcc -o wrapper wrapper.c
sudo chown root:root wrapper
sudo chmod u+s wrapper

# wrapper 経由で実行
./wrapper

capabilities の利用

Linux capabilities は root 権限を細分化した仕組みだ。

# Python に特定のポートをバインドする権限を付与
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/python3

# これで一般ユーザーでも 80 番ポートを使える
python3 -c "import socket; s=socket.socket(); s.bind(('', 80))"
# capabilities を確認する
import subprocess
result = subprocess.run(
    ["getcap", "/usr/bin/python3"],
    capture_output=True, text=True
)
print(result.stdout)

ただし、Python インタプリタに capabilities を付与すると、そのシステム上のすべての Python スクリプトが影響を受けるため注意が必要だ。

setgid の利用例

setuid ほど危険ではないが、setgid も使える場面がある。

# 特定グループに属するファイルにアクセスさせたい場合
sudo chown root:secretgroup script.py
sudo chmod g+s script.py

# スクリプト内で補助グループを確認
python3 -c "import os; print(os.getgroups())"

まとめ

方法安全性用途
sudoユーザーが明示的に権限昇格を許可する場合
C ラッパー自動化された権限昇格が必要な場合
capabilities特定の権限のみ必要な場合
setuid スクリプト不可OS が無視するため使えない
Python で特権が必要なら

sudo を使うのが最も安全で推奨される方法。自動化が必要なら、sudoers で NOPASSWD を設定するか、専用のサービスとして実装する。

setuid の「魔法」に頼ろうとせず、適切な権限管理の仕組みを使うことが重要だ。