CyberFix Note
防御・ハードニング

Linuxで一般ユーザーがrootを奪う典型経路と、SUIDやsudoersの棚卸しから始める防御策

対象の目安: Linuxサーバーの構築や運用を担うインフラエンジニア / 実務

リク・編集長 / セキュリティ全般・戦略
・ 約20分で読めます
Linuxで一般ユーザーがrootを奪う典型経路と、SUIDやsudoersの棚卸しから始める防御策

Linuxサーバーへの侵入は、多くの場合rootではなく権限の低いアカウントから始まります。Webアプリの脆弱性を突かれればアプリの実行ユーザーとして、SSHの認証情報を盗まれればそのユーザーとして、攻撃者は最初の足場を得ます。そこからrootへ届くかどうかは、サーバー側に残っている設定の緩みと、適用されていない修正にかかっています。オランダの脆弱性開示組織DIVDは、2026年9月21日に自組織の環境がヘルプデスク製品Zammadの2件の脆弱性を連鎖させて侵害されたと公表しています。Zammadユーザーとしてのコード実行を許すCVE-2026-102489と、ローカルのzammadユーザーからrootへ昇格できるCVE-2026-102490の組み合わせです(影響範囲などについてはZammad社が異なる見解を示しています)。入口を塞ぐ対策だけでなく、入られた後に昇格させない作りが問われる例です。

この記事では、一般ユーザーやサービスアカウントからrootへ至る典型的な経路を整理し、MITRE ATT&CKのテクニックと対応づけたうえで、防御側が定期的に回す棚卸しと検知の設計を説明します。対象読者はLinuxサーバーの構築や運用を担うインフラエンジニアです。記述はMITRE ATT&CK、NVD、sudoの公式マニュアルとアドバイザリ、Linuxのmanページ、Docker公式ドキュメント、脆弱性の発見者による公開情報にもとづき、事実は執筆時点(2026年10月8日)で確認できた範囲に限ります。攻撃のためのエクスプロイト手順は扱わず、掲載するコマンドは自組織のサーバーを点検するためのものです。点検や検証は、自組織が管理する、または管理者から明確な許可を得た環境でのみ行ってください。許可のないサーバーで権限の確認や昇格を試みる行為は、不正アクセス禁止法など関連法令に抵触するおそれがあります。

あわせて読みたい

ZammadのCVE-2026-102489と102490がKEV入り。DIVDを侵害したゼロデイ連鎖と、ベンダーとの見解の食い違い

権限昇格の経路は3系統に分かれる

個別の手口は数多くありますが、成立する理由で分類すると次の3系統に収まります。

1つ目は、OSが用意している昇格の仕組みそのものを悪用する系統です。SUIDビットやsudo、Linux capabilitiesは、特定の操作だけを一般ユーザーに許すための仕組みですが、許可の範囲が広すぎると、本来の目的を超えてrootの権限を引き出せます。

2つ目は、rootが実行するものに一般ユーザーが手を加えられる系統です。rootのcronが呼ぶスクリプトや、systemdユニットが起動するプログラムに書き込めるなら、次の実行時に任意の処理がrootとして動きます。PATHの順序の細工や、パーミッションの緩い設定ファイルに残った秘密情報もここに入ります。

3つ目は、カーネルやSUIDプログラムの脆弱性を突く系統です。設定に落ち度がなくても、修正が適用されていなければ一般ユーザーからrootへ届きます。

経路成立する条件対応するATT&CK
SUID/SGIDバイナリシェルを起動できるプログラムや脆弱なプログラムにSUIDが付いているT1548.001 Setuid and Setgid
sudoersの過剰な許可NOPASSWDや、シェルを抜けられるコマンドを許可しているT1548.003 Sudo and Sudo Caching
Linux capabilitiescap_setuidなど強いcapabilityが汎用プログラムに付与されているT1548の類型として扱う(後述)
cronスクリプトrootのcronが呼ぶファイルに一般ユーザーが書き込めるT1053.003 Cron
systemdユニットユニットファイルや起動対象のプログラムを書き換えられるT1543.002 Systemd Service
PATHの細工特権で動くスクリプトがコマンドを絶対パスで呼ばず、書き込み可能なディレクトリがPATHの前方にあるT1574.007 Path Interception by PATH Environment Variable
設定ファイルの秘密情報rootやDB管理者のパスワード、鍵が誰でも読める場所にあるT1552.001 Credentials In Files
dockerグループ一般ユーザーがDockerデーモンを操作でき、ホストのファイルシステムをマウントできるT1611 Escape to Host
未修正の脆弱性カーネルやsudo、polkitの既知の脆弱性が残っているT1068 Exploitation for Privilege Escalation

capabilitiesについては、ATT&CKで名指しした項目を執筆時点で確認できなかったため、昇格の制御機構の悪用(T1548)に近い類型として整理しています。

ATT&CKの全体像や、テクニックIDを検知設計に使う考え方は別記事で扱っています。

あわせて読みたい

MITRE ATT&CKで攻撃を体系的に理解する。戦術と技術のマトリクスを検知・防御にどう活かすか

昇格の仕組みを悪用する経路

SUIDとSGID

SUIDビットが付いた実行ファイルは、実行したユーザーではなくファイル所有者の権限で動きます。所有者がrootなら、誰が実行してもrootとして動きます。passwdのようにパスワードファイルを更新するための正当な用途がある一方で、エディタやインタプリタ、ファイル操作のツールにSUIDが付いていると、その機能を通じてrootのシェルやrootとしての書き込みが得られます。MITRE ATT&CKのT1548.001は、攻撃者がSUIDやSGIDの付いた脆弱なプログラムを探して悪用することがあり、探索にfindコマンドが使われると記載しています。

防御側も同じfindで先に棚卸しできます。問題になりやすいのは、ディストリビューションの標準パッケージ以外に付いたSUIDです。検証のために付けたまま忘れたもの、独自にビルドしたツール、古い管理ソフトが残したものが典型です。

sudoersの過剰な許可

sudoはコマンド単位で権限を委ねられるため、最小権限の運用に向いています。ただし許可の書き方を誤ると、そのまま昇格の経路になります。

1つは、シェルを抜けられるコマンドの許可です。vi、less、find、各種インタプリタのように、内部から別のコマンドを起動できるプログラムをsudoで許すと、そこからrootのシェルを開けます。こうした正規コマンドの悪用パターンはGTFOBinsという公開データベースにまとめられており、攻撃側も防御側も参照しています。自組織のsudoersで許可しているコマンドがGTFOBinsに載っていないかを確認するのは、手軽で効果の大きい点検です。

もう1つは、引数を固定しない許可やワイルドカードの多用です。許可するコマンドに任意の引数を渡せると、想定外のオプションでファイルを書き換えたり別のプログラムを呼んだりできる場合があります。sudoersのマニュアルは、ALLから!演算子でコマンドを除外する書き方は実効性が低いと明記しています。除外したいコマンドを別名でコピーすれば回避できるためです。

sudoersマニュアルのSECURITY NOTESは、ALLから!演算子でコマンドを「引き算」する方法は一般に効果がなく、利用者はコマンドを別名にコピーして実行するだけで回避できると説明しています。シェルの起動を防ぐ手段としてNOEXECやINTERCEPTのタグも用意されていますが、動作するかどうかはシステムやプログラムに依存するとしています。

NOPASSWDの付与は、それ自体が昇格の手口ではありませんが、そのユーザーのセッションを乗っ取った攻撃者が、パスワードを知らないままsudoを使えることを意味します。サービスアカウントや自動化用アカウントにNOPASSWDとALLを組み合わせた設定は、乗っ取られた時点でrootを渡すのと同じです。

Linux capabilities

capabilitiesは、rootの権限を機能ごとに分割して個別に与える仕組みです。たとえばcap_net_bind_serviceを付ければ、root以外のユーザーでも1024番未満のポートで待ち受けられます。一方で、capabilities(7)のマニュアルによれば、CAP_SETUIDはプロセスのUIDを任意に操作できる権限です。これがインタプリタのような汎用プログラムに付いていると、UIDを0に切り替えてrootとして動けます。CAP_DAC_OVERRIDEやCAP_DAC_READ_SEARCHのようにファイルの権限チェックを迂回できるものも、/etc/shadowなどを読める経路になります。SUIDほど知られていないぶん、棚卸しから漏れやすい点に注意が要ります。

rootが実行するものへの書き込み

cronとsystemdユニット

rootのcronが定期的に実行するスクリプトに一般ユーザーやサービスアカウントが書き込めると、次の実行時にその内容がrootとして動きます。見落としやすいのは、crontab自体の権限は正しくても、呼び出し先のスクリプトや、スクリプトが読み込む別ファイル、置き場所のディレクトリに書き込み権限が残っている場合です。ディレクトリに書き込めれば、ファイルを削除して作り直せます。

systemdも同じ構造です。ユニットファイル、ExecStartで指定したプログラム、EnvironmentFileで読み込むファイルのいずれかを書き換えられれば、サービスの再起動時にその内容が動きます。MITRE ATT&CKはこれらを永続化の手口としても挙げており、昇格と居座りの両方に使われます。

PATHの細工と設定ファイルの秘密情報

rootで動くスクリプトがコマンドを絶対パスで書かず、PATHの前方に一般ユーザーが書き込めるディレクトリがあると、同名の偽プログラムが先に見つかって実行されます。sudoではsecure_pathでPATHを固定できますが、cronやsystemdから呼ばれる独自スクリプトは、スクリプト側で絶対パスを使うか、冒頭でPATHを明示しておくと安全です。

設定ファイルに残った秘密情報も、昇格の近道になります。誰でも読めるバックアップファイル、デプロイ用スクリプトに書かれたrootやDB管理者のパスワード、シェルの履歴、権限の緩い秘密鍵などが該当します。パスワードの使い回しがあれば、技術的な脆弱性がなくてもrootに届きます。

dockerグループへの所属

Docker公式ドキュメントは、dockerグループがユーザーにroot相当の権限を与えると警告しています。Dockerデーモンはrootで動き、ホストのディレクトリを制限なくコンテナに共有できるため、Dockerを操作できるユーザーはホストのファイルシステム全体を書き換えられます。sudoを使わずにdockerコマンドを打てるようにする目的で開発者を所属させる運用はよく見かけますが、それはrootを配っているのと同じです。

Docker公式のLinux向けインストール後の手順は「The docker group grants root-level privileges to the user.」と警告し、詳細はDocker Daemon Attack Surfaceを参照するよう案内しています。Docker Engine securityのページは、Dockerデーモンを操作できるのは信頼できるユーザーに限るべきだと述べています。

コンテナにdocker.sockをマウントする構成や、privilegedで起動したコンテナも、コンテナからホストへ抜ける経路になります。MITRE ATT&CKのT1611は、ホストのファイルシステムをマウントしたコンテナの作成や、マウントされたdocker.sockの悪用を例に挙げています。

あわせて読みたい

コンテナ(Docker)セキュリティの基礎と実務で効く守り方

未修正の脆弱性による昇格

設定が正しくても、カーネルやSUIDプログラムの既知の脆弱性が残っていれば昇格されます。代表例を4件挙げます。いずれもCISAのKnown Exploited Vulnerabilities(KEV)カタログに、実際の悪用が確認された脆弱性として登録されています。

CVE対象概要KEV追加日
CVE-2022-0847(Dirty Pipe)Linuxカーネルパイプバッファのフラグが初期化されず、一般ユーザーが読み取り専用ファイルのページキャッシュに書き込める2022-04-25
CVE-2021-4034(PwnKit)polkitのpkexec引数の数の扱いの誤りにより、環境変数を細工して任意のコードをrootで実行できる2022-06-27
CVE-2021-3156(Baron Samedit)sudo 1.9.5p2より前sudoedit -sでのヒープバッファオーバーフローによりrootへ昇格できる2022-04-06
CVE-2025-32463sudo 1.9.14から1.9.17chrootオプションで利用者が用意したnsswitch.confが読み込まれ、sudoersに記載がなくてもrootでコマンドを実行できる2025-09-29

Dirty Pipeを報告したMax Kellermann氏によれば、この脆弱性はLinux 5.8以降に存在し、5.16.11、5.15.25、5.10.102で修正されました。ディストリビューションのカーネルは修正を独自に取り込むため、判定はバージョン番号ではなく各ディストリビューションのセキュリティ情報で行います。

Qualysは2022年1月25日の公表で、PwnKitが2009年5月の最初の版以降のすべてのpkexecに影響し、Ubuntu、Debian、Fedora、CentOSの標準インストールでrootを取得できたと報告しています。修正を適用できない場合の一時的な緩和策として、pkexecからSUIDビットを外す方法を示しています。

sudoのアドバイザリは、CVE-2025-32463の影響をsudo 1.9.14から1.9.17までとし、1.9.17p1でsudo 1.9.14の変更を取り消したうえでchroot機能を非推奨にしたと説明しています。

PwnKitの例が示すように、SUIDの付いたプログラムは脆弱性が見つかった瞬間に昇格の経路になります。使っていないSUIDプログラムを減らしておくことは、将来の脆弱性への備えにもなります。

防御側が回す棚卸し

ここからは、自組織のサーバーを点検するためのコマンドです。出力を前回分と比較し、増えたものや見覚えのないものを確認する運用にすると、変化に気づきやすくなります。

# SUID/SGIDが付いたファイル(ローカルのファイルシステムのみ)
find / -xdev -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} + 2>/dev/null

# ファイルcapabilitiesが付いたファイル
getcap -r / 2>/dev/null

# sudoersの許可内容(visudoで構文を確認しつつ、NOPASSWDとALLの使用箇所を洗い出す)
visudo -c
grep -rnE 'NOPASSWD|ALL' /etc/sudoers /etc/sudoers.d/

# 特定ユーザーに許可されているsudoコマンド
sudo -l -U <ユーザー名>

# 特権に相当するグループの所属
getent group sudo wheel docker adm

# cronとsystemdの関連ファイルのうち、root以外が所有するもの、グループやその他に書き込み権限があるもの
find /etc/cron* /etc/systemd/system /usr/local/bin -xdev \( ! -user root -o -perm -0020 -o -perm -0002 \) -ls 2>/dev/null

# サービスユニットのサンドボックス設定の評価
systemd-analyze security

cronやsystemdの確認は、上の場所だけでは足りません。crontabやユニットファイルの中身を読み、呼び出しているスクリプトと、それが読み込むファイルや置き場所のディレクトリまでたどって権限を見ます。systemd-analyze securityは、ユニットごとにサンドボックス関連の設定を評価して一覧表示するコマンドで、NoNewPrivilegesやProtectSystemなどの未設定項目を見つける手がかりになります。

  • サービスはrootではなく専用のアカウントで動かし、そのアカウントにログインシェルとsudo権限を与えない
  • SUIDとcapabilitiesの一覧を取り、標準パッケージ以外のものは用途を確認して不要なら外す
  • sudoersで許可しているコマンドをGTFOBinsと照合し、シェルを起動できるものは許可しない
  • sudoの許可は引数まで固定し、ファイル編集はsudoeditで許可する
  • NOPASSWDとALLの組み合わせを洗い出し、自動化用アカウントは必要なコマンドだけに絞る
  • dockerグループの所属者をroot権限保持者として管理し、不要な所属を外すか、rootlessモードを検討する
  • rootが実行するcronスクリプトとsystemdユニット、その置き場所のディレクトリにroot以外の書き込み権限がないことを確認する
  • 設定ファイルやバックアップ、デプロイスクリプトに平文の認証情報が残っていないかを確認する
  • カーネル、sudo、polkitの更新を定期的に適用し、カーネル更新後の再起動まで計画に含める

あわせて読みたい

最小権限の原則(Least Privilege)。なぜ権限を絞ることが最強の防御の一つなのか

検知とログの設計

棚卸しで穴を減らしても、未知の脆弱性による昇格は防ぎきれません。昇格が起きたことに後から気づけるよう、root権限での実行を記録しておきます。

sudoの実行はsyslogに記録され、Debian系では/var/log/auth.log、Red Hat系では/var/log/secure、journald環境ではjournalctlで確認できます。sudoersのuse_ptyはsudo 1.9.14以降で既定で有効になっています。log_inputやlog_outputを有効にすると、sudoで実行したコマンドの入出力まで記録できます。

auditdでは、一般ユーザーとしてログインしたセッションから実効UIDが0のプログラムが実行された場合を記録すると、SUIDやcapabilities、脆弱性を経由した昇格の痕跡を拾いやすくなります。audit.rules(7)のマニュアルは、ログインUID(auid)で絞り込む際に未設定値を除外するため、auid!=unsetを併記する書き方を示しています。

# /etc/audit/rules.d/privesc.rules の例(32ビットのシステムコールも監視する場合はarch=b32の行を追加する)
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=unset -k root_exec
-w /etc/sudoers -p wa -k sudoers_change
-w /etc/sudoers.d/ -p wa -k sudoers_change
-w /etc/cron.d/ -p wa -k cron_change
-w /etc/systemd/system/ -p wa -k systemd_change

execveの監査はイベント量が多くなるため、まず検証環境で件数を測り、SIEMに送る範囲を決めてから本番へ広げます。記録した後は、ausearch -k root_execのようにキーで検索できます。見るべきなのは、サービスアカウントを起点とするroot権限の実行、業務時間外のsudoersの変更、平常時に存在しなかったSUIDファイルの出現です。

SELinuxやAppArmorも昇格後の被害を狭めます。サービスのプロセスを専用のドメインやプロファイルに閉じ込めておけば、アプリの脆弱性でコードを実行されても、触れられるファイルや実行できるプログラムが制限されます。無効化したまま運用しているサーバーは、まずpermissiveやcomplainのモードで違反を記録し、影響を見てから強制に切り替える進め方が現実的です。

コンテナで動かす場合の注意

コンテナでもroot権限の扱いは同じ考え方で整理できます。コンテナ内のプロセスをrootで動かさず、privilegedでの起動とdocker.sockのマウントを避け、不要なcapabilitiesを落とします。Dockerのdocker runにはno-new-privilegesのセキュリティオプションがあり、コンテナ内のプロセスがSUIDなどで新たな権限を得ることを止められます。systemdのNoNewPrivileges=yesも同じ目的の設定です。

コンテナはカーネルをホストと共有するため、Dirty Pipeのようなカーネルの脆弱性はコンテナの境界を越える可能性があります。コンテナ化はカーネル更新の代わりにはなりません。

サーバー全体の要塞化の進め方や、SSHの鍵運用と組み合わせると、入口と昇格の両方を絞れます。

あわせて読みたい

サーバーのハードニング基礎。最小化・最小権限・更新・設定堅牢化をCISベンチマークから学ぶ

まとめ

Linuxの権限昇格は、昇格の仕組みの悪用、rootが実行するものへの書き込み、未修正の脆弱性という3系統で整理できます。どの系統も、防御側が先にコマンドで棚卸しできるものが大半です。SUIDとcapabilities、sudoers、cronとsystemdの書き込み権限、特権グループの所属を定期的に洗い出し、カーネルとsudo、polkitの更新を止めないこと。そのうえでauditdとsudoログでroot権限の実行を記録しておけば、侵入された後に昇格させず、昇格されても気づける状態に近づけます。点検は自組織が管理する環境で、許可の範囲内で行ってください。

出典・参考

この記事をシェア

関連する記事

防御・ハードニング

最小権限の原則(Least Privilege)。なぜ権限を絞ることが最強の防御の一つなのか

必要最小限の権限だけを与える「最小権限の原則」を、なぜ効くのか(侵害時の被害局所化・横展開の抑止)という原理から噛み砕き、過剰権限の典型例とRBAC・ジャストインタイム権限・定期棚卸しといった実践、ゼロトラストとの関係までを実務目線で整理します。

防御・ハードニング

SSHサーバのハードニングと鍵の運用

パスワード認証から公開鍵認証へ移す理由を署名の仕組みから説明し、OpenSSH公式のman説明とリリースノートで確認できた既定値をもとに、sshd_configの要点、鍵の作り方と保管、踏み台とアクセス経路、ログと検知までを整理します。