第8章 入力検査
環境変数の検査とリセット
環境変数は書き変えられているかもしれない
攻撃者の手によって環境変数が改変されると、偽のライブラリや子プログラムを起動してしまう等、プログラムの振舞いが干渉されてセキュリティ侵害がおこるおそれがある。
環境変数とプログラムのすり替え
ロードするプログラムやライブラリの所在を示す環境変数の改ざんによって、攻撃者が自分の用意したプログラムを不正に動作させるおそれがある。
(1) PATH
プログラムの探索パスを保持する環境変数。
呼び出されるプログラムのすり替えと権限昇格(root 権限の不正な使用)のおそれがある。
例えば、rootアカウントで動作する setuid または setgid ビットが設定されているプログラムの中に PATH 変数を用いて別のプログラムを呼び出す API の使用箇所があるような場合、PATH 変数の書き変えによって起動するプログラムをすり替える手口によって、プログラムを起動できるユーザなら誰でも自分のプログラムを root 権限で実行させることができるようになる。

(2) LD_LIBRARY_PATH
共有ライブラリの探索パスを保持する環境変数。
この変数の書き変えによってロードされるライブラリのすり替えがおこるおそれがある。
(3) LD_PRELOAD
プリロード(他のライブラリに優先してロード)すべき共有ライブラリのリスト。
この変数の書き変えによってロードされるライブラリのすり替えがおこるおそれがある。
既存のライブラリ関数をフックしてデバッグや付加価値を与える等にも利用される。
setuid/setgidプログラムに対しては通常効果がない。ここに指定されているライブラリやオブジェクトのプリロードは、当然ながら、この環境変数が継承される限り子プロセスにおいても行われる。
(4) CLASSPATH
Java のクラス(バイトコードファイル)探索パス。
この変数の書き変えによってロードされるクラスのすり替えがおこるおそれがある。
そのほか注意すべき環境変数
次の環境変数も重要な役割を担っている場合があり、注意を要する。
- HOME
- 環境変数 HOME は、ユーザのホームディレクトリを示している。HOME 変数が改ざんされた状態でプログラムが動作すると、攻撃者が用意したディレクトリへデータが漏洩したり、プログラムのロジックが妨害されるおそれがある。
- LOGNAME
- ユーザのログイン名(System V系Unix)
- SHELL
- ログインシェルのパス名
- TEMP
- 一時ファイルのディレクトリ(Windows)
- TMPDIR
- 一時ファイルのディレクトリ(GNU/Linux)
- TZ
TZDIR - タイムゾーンの情報
- USER
- ユーザのログイン名(BSD系Unix)
環境変数の対策
プログラムの動作にあたってはすでに環境変数が改ざんされていることを想定し、次のような対策を講じる。
(1) 環境変数の検査
ロードするライブラリの所在等処理系に用意されているパラメータも含め、プログラムの動作に大きな影響を与える環境変数の値がすべて所定の仕様を満たしていることを厳密に検査する。
(2) 環境変数のクリア
外部プログラムをコールする(exec(3))前に、環境変数をすべてクリアするとより安全になる。環境変数をクリアするには、clearenv(3) をコールすればよい。
clearenv(3) が無い環境では、以下のように extern char **environ 変数を直接クリアする。
environ = NULL;
※上記の方法で環境変数をクリアしても、system (3) による子プロセスの環境変数は、クリアされず再設定されたものになる。
(3) 絶対パス名による呼び出し
偽の別プログラムを起動しないようにするには、外部プログラムを絶対パス名で指定する。呼び出された別のプログラムが,さらに別のプログラムを呼び出すような場合も、同様に絶対パス名で指定するようにする。
(4) PATH の再設定
環境変数 PATH は妥当なコマンド探索パスを示すように設定し直せば、安全になる。
環境変数 PATH を必要最小限の妥当なコマンドサーチパスに設定し直すことで,別なプログラム(子)から派生するさらなる別なプログラム(孫)の呼び出しについてもすり替えの対策を施すことになる。
ただし,呼び出す先の別のプログラム(子)も,呼び出す側のプログラム同様に十分な安全対策が施されているものでないと安心できない。
(5) 古いシェルの不使用
シェルとして古い sh, bsh は使用せず、bash の最新版を使用する。
最近の GNU bash では問題は解消されているが、古い UNIX システムの Bourne シェルでは「環境変数 IFS に「/」が設定されているとコマンド「/bin/sh」が実行される文脈において「bin sh」と解釈されプログラム bin が呼び出される」という問題があった。
環境変数 IFS は sh や bash でコマンドラインの引数を分割するために使用するキャラクタの指定で利用されている環境変数である。デフォルト値は「 \t\n」(スペース、タブ、改行)である。
上記の脆弱性のある sh, bsh を使わざるを得ないのであれば、プログラムの先頭で環境変数 IFS をデフォルトの値「 \t\n」に再設定するようにする。
参考:sudo、suコマンドの環境変数対策
(1) sudo コマンドが行う環境変数対策
sudo は、別のユーザアカウント(デフォルトは root)で任意のコマンドを実行させるコマンドである。
sudo コマンドは対象のコマンドを起動する前に、環境変数に関する次のような設定を行う。
- LD_*, _RLD_*, SHLIB_PATH(HP-UX), LIBPATH(AIX) 変数を削除する
- TERMCAP 変数にパスが設定されている場合、無視する
- LC_*, LANGUAGE 変数に「/」、「%」文字が含まれている場合、無視する
- sudo が SecurID をサポートする場合、VAR_ACE, USR_ACE, DLC_ACE 変数を削除する
- PATH 変数の「.」と「""」を無視して実行する
呼ばれるコマンドには「.」と「""」を無視した PATH は渡されない。
(2) su コマンドが行う環境変数対策
su は別のユーザ・アカウント(デフォルトは root)でシェルのセッションを開始するコマンドである。
環境変数の観点からいうと su はおおむね次の3種類の動作をする。
- 環境変数やカレントディレクトリを全く変更せずアカウントのみ切り替える
- HOME、SHELL、USER、LOGNAME の値が対象アカウントのものに切り替わる。ただし、対象アカウントが root のときは HOME と SHELL のみ値が切り替わる(これが標準の動作)
- 対象アカウントへ直接ログインしたときと同様の環境設定を行う。HOME、SHELL、PATH、TERM、USERに値が設定され、それ以外の環境変数の値は消去される