セキュリティの落とし穴が、まさか「環境変数」にあるとは思わなかった——そんな声が現場から聞こえることがあります。
Linuxサーバーを運用していると、ユーザーごとにシェルの環境変数が異なるのは当たり前の光景です。ところがその環境変数が、悪意ある操作の踏み台になるケースがあります。特に LD_PRELOAD や PATH の値を意図的に書き換えられると、一般ユーザーがシステム管理者権限を奪い取る「特権昇格」に直結することがあります。
この記事では、環境変数を使った特権昇格の主要な手口を「防御するために知る」という文脈で解説し、sudoersの設定・setuidプログラムの管理・定期的な監査手順まで、情シス1人でも今日から実践できる対策をまとめます。

環境変数とセキュリティの関係
環境変数とは、シェルが動作する際に参照する名前付きの値のことです。たとえば PATH はコマンドを探すディレクトリのリスト、HOME はホームディレクトリのパスを指します。
通常、環境変数は「使い勝手を良くするための仕組み」にすぎません。しかし、特定の条件下ではこの仕組みが攻撃者に利用されます。とくに問題になるのは次の2点です。
・setuidプログラムの存在: 実行時に所有者(多くの場合root)の権限で動くプログラムです。環境変数を引き継いで動作する場合、攻撃者が細工した環境変数が特権処理の中に持ち込まれます。
・sudoでのコマンド実行: sudo経由で呼び出すコマンドが、呼び出し元ユーザーの環境変数を受け継ぐように設定されていると、悪意のある値が特権コマンドに渡されます。
「環境変数は単なる設定値」という先入観が、セキュリティの盲点になりやすい部分です。
攻撃の仕組み(敵を知る)
1. LD_PRELOAD を悪用した特権昇格
LD_PRELOAD は、プログラムの起動時に通常のライブラリより先に読み込む共有ライブラリのパスを指定する環境変数です。本来はデバッグや一時的な関数置き換えに使われます。
攻撃者はこれを悪用し、悪意のある共有ライブラリを指定することで、標的プログラムの内部関数を乗っ取ります。
想定例(架空のシナリオ): 一般ユーザーが LD_PRELOAD=/tmp/evil.so sudo somecommand のように環境変数をセットした状態でsudoを実行できる場合、evil.so内の悪意のある関数が特権プロセスの中で呼び出される可能性があります。
ただし、Linuxカーネルは setuid バイナリについて LD_PRELOAD を無視する保護機能を持っています。問題は sudo の設定が適切でない場合に生じます。
# LD_PRELOAD の現在値を確認する(通常は空が正常) echo $LD_PRELOAD # sudo が環境変数をどう扱うか確認する sudo -V | grep "environment"
2. PATH 汚染(Path Hijacking)
PATH 環境変数は、コマンドを検索するディレクトリのリストです。攻撃者が PATH の先頭に書き込み可能なディレクトリを追加し、そこに正規コマンドと同名の悪意あるスクリプトを配置すると、特権プログラムが意図しないコマンドを実行してしまいます。
よくあるつまずき: setuidビット付きシェルスクリプトはとくに危険です。シェルスクリプトの内部で相対パスのコマンドを呼び出している場合、PATHを差し替えられると別のコマンドが動作します。
想定例(架空のシナリオ): /usr/local/bin/backup.sh(setuid root)の中で単に tar と書かれていた場合、攻撃者が PATH=/tmp:$PATH をセットして /tmp/tar(任意のコード)を置くと、rootとして実行されます。
# 相対パス呼び出しをしているsetuidスクリプトを探す(危険の特定) find / -perm -4000 -name "*.sh" 2>/dev/null # PATHに書き込み可能なディレクトリが先頭に入っていないか確認する echo $PATH | tr ':' ' ' | while read d; do [ -w "$d" ] && echo "[WARN] writable: $d" done
3. LD_LIBRARY_PATH の悪用
LD_LIBRARY_PATH は共有ライブラリを探すディレクトリを追加指定するための環境変数です。LD_PRELOAD と同様、setuidバイナリでは通常無視されますが、sudo経由での環境変数継承が設定されている場合は注意が必要です。
また、開発環境でライブラリのテストのために設定した LD_LIBRARY_PATH が、サービスアカウントや本番環境の環境変数に残ったままになっているケースも現場では見られます。
具体的な防御手順
1. setuid・setgid プログラムの棚卸しをする
まずサーバー上のsetuid/setgidファイルを洗い出し、不必要なもののビットを落とします。
# setuidビット付きファイルを列挙する find / -perm -4000 -type f 2>/dev/null | sort # setgidビット付きファイルを列挙する find / -perm -2000 -type f 2>/dev/null | sort # 不要なsetuidビットを削除する(例: /usr/bin/at が不要な場合) # chmod u-s /usr/bin/at
標準的なLinuxディストリビューションでは、passwd・sudo・ping・mount など最小限のプログラムだけがsetuidを持ちます。それ以外のプログラムにsetuidが付いている場合は理由を確認してください。
Linuxのカーネルエクスプロイト緩和策(ASLR・NXビットなど)についても合わせて確認すると、攻撃のハードルをさらに上げることができます。詳しくはLinuxのカーネルエクスプロイト緩和策入門をご覧ください。
2. sudoers で env_reset を有効にする
sudo は env_reset オプションが有効な場合、sudo実行時に呼び出し元の環境変数をリセットし、最小限の安全な環境変数だけを渡します。多くのディストリビューションではデフォルトで有効ですが、明示的に確認します。
# sudoers の設定を確認する(visudo経由で確認・編集する) sudo visudo -c # 文法チェック # /etc/sudoers の該当部分を確認する(直接編集しない・必ずvisudoを使う) sudo grep -i "env_reset\|env_keep\|secure_path" /etc/sudoers /etc/sudoers.d/*
設定ファイルに以下が含まれていることを確認してください。
# 推奨設定(/etc/sudoersの Defaults セクション) Defaults env_reset Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
env_reset があると LD_PRELOAD・LD_LIBRARY_PATH・PATH などがsudo実行時にリセットされます。
3. env_keep の設定を最小化する
env_keep は「env_resetをかけても引き継ぐ環境変数」のリストです。ここに LD_PRELOAD や PATH が含まれていると、env_resetの保護が無効になります。
# env_keep に危険な変数が入っていないか確認する sudo grep "env_keep" /etc/sudoers /etc/sudoers.d/* 2>/dev/null # 以下のような記述があれば削除または修正する(危険な例) # Defaults env_keep += "LD_PRELOAD" ← 絶対に設定しない # Defaults env_keep += "LD_LIBRARY_PATH" ← 絶対に設定しない
4. 不審なプロセスと環境変数を定期確認する
稼働中のプロセスが持っている環境変数は /proc/[PID]/environ で確認できます。定期監査で異常なLD_PRELOADやPATHがないかを確認します。
# 特定のプロセスの環境変数を確認する(PIDを指定) cat /proc/1234/environ | tr '\0' '\n' | grep -E "LD_|PATH" # LD_PRELOAD が設定されているプロセスを全探索する(rootで実行) for pid in /proc/[0-9]*/environ; do env=$(cat "$pid" 2>/dev/null | tr '\0' '\n') if echo "$env" | grep -q "^LD_PRELOAD="; then echo "[WARN] LD_PRELOAD found in PID: ${pid%%/environ*##*/}" echo "$env" | grep "^LD_PRELOAD=" fi done
不審なプロセスや通信が見つかった場合の調査手順については、Linuxの不審プロセス・ネットワーク接続を調査する方法も参考にしてください。
中小企業・情シスでも今日からできること
高度なツールがなくても、次のことをすぐに実施できます。
・sudoers の env_reset を確認する: sudo visudo で開き、Defaults env_reset の行があることを確認する。なければ追加する。
・setuidファイルの棚卸し: find / -perm -4000 2>/dev/null で一覧を作り、不明なファイルがあれば用途を確認する。
・env_keep の棚卸し: sudoers に LD_PRELOAD や LD_LIBRARY_PATH を env_keep で引き継ぐ設定がないかを確認する。
・開発環境の変数が本番に残っていないか確認する: サービスの起動スクリプト(systemdのUnit FileやinitスクリプトのEnvironment行)を見直す。
Linuxのsudoers設定の全体像や関連する権限管理については、姉妹サイトLinuxMaster.JPでも詳しく解説しています。
よくある誤解と注意点
・「setuidバイナリはLD_PRELOADを無視するから安全」: カーネルがLD_PRELOADをドロップするのはsetuidバイナリ自体の話です。sudoや特権スクリプトが内部でdynamic linkライブラリを呼ぶ場面では、設定次第で引き継がれることがあります。env_resetが有効かどうかが実際の境界線です。
・「SUID付きシェルスクリプトはLinuxでは動かない」: 多くのディストリビューションでは、シェルスクリプトのsetuidを無視する設定が入っています。しかし古いシステムや特定の構成では有効になる場合があります。依存せず、setuid付きのシェルスクリプトは作らないことが基本です。
・「LD_PRELOADを空にすれば十分」: PATH汚染はLD_PRELOADとは別の攻撃経路です。env_resetで両方をまとめて対処するのが正解です。
環境変数を悪用した攻撃はLOLBins(合法ツールを悪用する攻撃)とも重なる部分があります。LOLBins攻撃の仕組みと防御策も合わせて読むと、攻撃者の視点がより立体的に理解できます。
また、特権昇格のリスク全般については権限昇格(Privilege Escalation)とは?で体系的に解説しています。

本記事のまとめ
| 攻撃手口 | 悪用される変数 | 主な対策 |
|---|---|---|
| LD_PRELOAD インジェクション | LD_PRELOAD | sudo の env_reset 有効化・env_keepから除外 |
| PATH 汚染(Path Hijacking) | PATH | secure_path の設定・setuidスクリプトの廃止 |
| LD_LIBRARY_PATH インジェクション | LD_LIBRARY_PATH | sudo の env_reset 有効化・本番環境での変数整理 |
| setuid プログラムの悪用 | 各種 | 不要な setuid ビットの削除・定期棚卸し |
環境変数のセキュリティは、setuidの棚卸しとsudoersのenv_reset確認という2つのチェックポイントを押さえるだけで、大部分のリスクを下げることができます。ツール導入なしでもすぐ実施できるので、まずは sudo visudo を開いて確認するところから始めてみてください。
PR
SELinux・ファイアウォール・権限管理・ログ監視まで、Linuxサーバー堅牢化の実践的な手法を体系的に学べる一冊です。本記事で触れたsetuidやsudoersの設定をより深く理解したい方に適しています。
