sudoersのNOPASSWDを絞り込んだら、PCが2回勝手に落ちた話

sudo systemctl restart bluetoothと打ったら、パスワードを聞かれずに通った。何かがおかしい。ここから、GTFOBinsの調査、SSH鍵の作り直し、rrsyncとの格闘、そしてOpenSSHのソースコードを読むところまで進んだ調査の記録。最後には、原因が分からないままPCが2回勝手に落ちるという、後味の悪いオチが付く。 きっかけ: パスワードを聞かれない Bluetoothの調子が悪くてsudo systemctl restart bluetoothを打った。いつもならパスワードを聞かれるはずが、そのまま通った。直近でsudoを使った覚えもない。おかしいと思ってsudo -n -l(パスワード無しで、自分に許可されているsudoコマンドを一覧表示する)を叩いてみた。 ユーザー takashi は takashi-pc 上で コマンドを実行できます (ALL : ALL) ALL (root) NOPASSWD: /usr/bin/rsync, /usr/bin/systemctl, /usr/bin/poweroff Copy /etc/sudoers.d/配下に、rsync・systemctl・poweroffの3つが、パスワード無しで、引数を問わず実行できる設定が入っていた。 GTFOBinsで確認した危険性 GTFOBinsは、Unix系のバイナリを悪用した権限昇格の手口をまとめたデータベースだ。systemctlとrsyncのページを見ると、この設定がどれだけまずいかがすぐ分かる。 systemctl: 自分でsystemdのサービスファイルを作り、systemctl link→systemctl enable --nowで登録・起動すれば、そのサービスはroot権限で動く。あるいはSYSTEMD_EDITOR環境変数に自分のスクリプトを指定した状態でsystemctl editを叩くと、そのスクリプトがrootで呼ばれる。 rsync: --rsh(または-e)オプションで、任意のコマンドを「リモートシェル」として起動できる。sudo rsync -e /bin/sh ...のような形で、rootのシェルを直接取れる。 つまりこの設定は、一般ユーザーのまま実質rootになれる、という状態だった。poweroffだけは被害が限定的(シャットダウンのみ)だが、残り2つは深刻。 誰がこれを使っていたのか このPCで動いている自動化を一通り確認したが、systemd timerにもcronにも、この3つのNOPASSWDに依存しているものは見当たらなかった。 答えは、別のマシン(自宅のミニPC、以下NAS)側にあった。backup-archという、このPCの/home /boot /etcを毎晩NASへrsyncでバックアップするスクリプトが、SSH経由でこのPCに対してsudo rsyncを実行していた。バックアップ完了後、sudo systemctl stop/startでコンテナを一時停止する処理と、sudo poweroffで自動シャットダウンする処理も持っていた。 backup-archの最初のコミットは2025年10月。当時はコーディングエージェントに書かせたもので、SSH経由のsudo実行を前提にした設計だった。systemctlを使っていた「バックアップ前後にコンテナを止める」処理は、後になって「そもそも止める対象がバックアップ範囲に含まれておらず、意味が無かった」という理由で既に削除されていたが、sudoers側の許可だけが広いまま残っていた。 絞り込みの設計: rrsyncとSSH強制コマンド rsyncとsystemctlのNOPASSWDを外し、その代わりに、必要な操作だけをできる形に絞り込むことにした。 rsyncにはrrsync(restricted rsync)という、rsync本体に同梱されている補助スクリプトがある。SSHのauthorized_keysで、特定の鍵に対してcommand="rrsync -ro /path/to/dir"のように強制コマンドを指定すると、その鍵で接続してきたクライアントが何を要求しても無視され、指定した1つのディレクトリへの読み取り専用アクセスだけが許可される。 ただしrrsyncは、1回の起動につき1つのディレクトリしか制限できない。今回は/home /boot /etcの3か所が必要だったので、ディレクトリごとに専用の鍵を1本ずつ、計3本作った。加えて、シャットダウン専用の鍵をもう1本。合計4本の鍵、それぞれに対応する強制コマンドをauthorized_keysに設定した。 command="sudo /usr/bin/rrsync -ro /home",restrict ssh-ed25519 AAAA... nas-backup-home command="sudo /usr/bin/rrsync -ro /boot",restrict ssh-ed25519 AAAA... nas-backup-boot command="sudo /usr/bin/rrsync -ro /etc",restrict ssh-ed25519 AAAA... nas-backup-etc command="sudo /usr/bin/poweroff",restrict ssh-ed25519 AAAA... nas-backup-poweroff Copy sudoers側も、引数まで完全一致させた形にする。 ...