sudo で実行できるプログラム
sudo -l の読み方はユーザーと sudo。このページは、許可コマンドが見つかったあと、そのコマンドが root で何を信用するかを追う。
sudo の見どころは、コマンドを実行できることより、root 実行中にどの低権限入力を信用するかである。
sudo -lls -la <allowed-command>sed -n '1,240p' <script>- 許可コマンドが root で実行される。
- そのプログラムが user-writable file、plugin directory、checkpoint、symlink、環境変数、相対パスを信頼している。
SETENVやenv_keepがあれば、環境変数も入力になる。
sudo <allowed-command>sudo <allowed-command> <extra-arg>namei -l <path-read-by-command>find <app-dir> -maxdepth 5 -writable -ls 2>/dev/null- 目的: sudoers の完全一致、引数追加の可否、実行時に読まれるファイル、書ける場所を確認する。
- 前提条件: 実行が状態変更する場合は、先にコードを読む。
restart,backup,train,logsなどは副作用がある。 - 出力の解釈: 引数追加時にパスワードを要求されたら、元の
NOPASSWDルールには一致していない可能性がある。許可コマンドが root 権限で低権限ユーザーの入力を読むなら、権限昇格の候補になる。 - 失敗した場合の切り分け:
NOPASSWDがない、TTY 不足、PATHの違い、環境変数の reset、wildcard の範囲、禁止ルール。 - 代替:
sudo -V,strings <binary>,strace -f -e file <command>。straceはノイズとログを増やすため、必要時だけ使う。 - 状態変更:
sudo -lは対象を変更しないが、認証ログに残る場合がある。許可コマンドの実行による変更は、後片付けの対象として記録する。記録欄はログと検知にある。
読まれるパスの権限はファイルとディレクトリ権限とroot が読む書き込み可能パスで確認する。
許可コマンドは、次の形で権限境界になる。主張するときは、sudoers の全文、対象スクリプトの全文、実行前後の id を残す。
- 許可コマンドだけでは root shell が出ない。別サービスが持つ状態(メンテナンス窓など)が揃って初めて処理が進む。その状態を変えるプロトコルは HTTP とは限らない。
- Python の許可コマンドに command injection がなくても、起動時に読む plugin(
.pthとsite.addsitedir())が root のコード実行になる。流れは独自コードの信頼境界。 - 禁止サブコマンドがあるルールでは、許可されているサブコマンドの実装だけを読む。
- インタプリタとスクリプトの完全一致では、引数追加は使えない。境界はスクリプトが読むファイル側にある。
- sudo が拒否されたら、許可コマンドの変形は打ち切る。次は localhost の root サービスである。
SUID と file capability の列挙はファイルとディレクトリ権限。プロセスの CapEff と、kernel や local exploit を使うときに残す version、namespace、capability、module はコンテナと名前空間で確認する。

