今回はセキュリティ攻撃の1つであるディレクトリ・トラバーサルについて解説をしていきます。
ディレクトリ・トラバーサル攻撃を受けてしまうと、被害内容によっては社会的信頼を失い、会社に大きな損害を与える結果となってしまう恐れもあります。
この記事を読むことでPHPでの対策方法も分かるため、ぜひ最後までご覧ください。
- ディレクトリ・トラバーサルの概要
- ディレクトリ・トラバーサルの攻撃手法
- ディレクトリ・トラバーサルによる被害・影響
- ディレクトリ・トラバーサルを受けてしまう原因
- ディレクトリ・トラバーサルの対策方法(PHPコードあり)
Webアプリのセキュリティ対策についてしっかり学ばれたい方にはこちらの書籍がおすすめです。
(通称:徳丸本と呼ばれる「Webアプリ開発者必読」とまで言われている書籍です)
体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践
徳丸 浩/著 SBクリエイティブ/出版│Amazon
ディレクトリ・トラバーサルとは?
ディレクトリ・トラバーサルとは、
本来はアクセスを許可していないファイルへ不正アクセスすることで、データを盗んだり、改ざん、削除するセキュリティ攻撃
です。
ディレクトリ・トラバーサル攻撃の主な被害・影響
ディレクトリ・トラバーサル攻撃よって起こりうる被害としては主に以下のようなものが挙げられます。
- 重要情報の流出
- データの改ざん
- データの削除
そしてディレクトリ・トラバーサル攻撃による1次被害がさらに発展し、以下のような大きな被害に繋がってしまう恐れがあるのです。
- アカウントの乗っ取り
- 社会的信頼の失墜による経済的損失
- マルウェアの拡散(データに埋め込まれるなど)
ディレクトリ・トラバーサル攻撃の流れ
このように重要データにまつわる被害へと発展する可能性のあるディレクトリ・トラバーサル攻撃ですが、実際に攻撃者がどのような方法で本来ならアクセス不可のファイルへアクセスできてしまうのかをお見せしようと思います。
前提として、一般的にディレクトリ・トラバーサル攻撃を受けるWebアプリには「外部からサーバー内のファイルを呼び出せる」という機能が実装されています。
それを踏まえた上で、1つのWebアプリを例に挙げ、ディレクトリ・トラバーサル攻撃がどのようにして行われるのかをお伝えしていきます。
Webアプリにおける通常時の処理
今回、例として挙げるWebアプリには、
ユーザが任意のテンプレートファイルを呼び出し、サイトの見た目を変更できる機能
が実装されている設定でご説明をしていきます。
このWebアプリの処理の流れはこうです。
- ユーザが「ファイル名入力フォーム」に任意のファイル名を入力する
- 送信ボタンが押下されると、入力されたファイル名に基づくリクエストがサーバーへ要求される
- サーバーが指定のテンプレートファイルをブラウザへ返し、サイトの見た目が変更される
ここで、入力されたファイル名に基づくリクエストとは、例えば以下のようなものを言います。
(例)ファイル名として「sample」が入力された場合
https://example/temp.php?file_name=sample.html
最後の「.html」はプログラム内で自動的に付与されるようになっています。
上記のリクエスト(URL)がサーバーへ送られることで、temp.php上でテンプレートファイルまでのフルパスが生成され、それによりテンプレートファイル(sample.html)が表示されるという流れとなります。
攻撃の例
次に、攻撃者がこの機能を利用して非公開ファイルを表示する例をお見せします。
攻撃者は、ファイル名に次のようなパスを指定します。
../../../etc/hosts%00
ここで注目して頂きたいのが、「../」と「%00」の部分です。
「../」は、相対パスにおいて1つ上のディレクトリを意味する記号です。
上記のパスの目的は、公開ルート(ドキュメントルート)のさらに上の階層にあるルートディレクトリ内の「/etc/hostsファイル」を指定することにあります。
「%00」はヌルバイトを表します。また、ヌルバイトというのはヌル文字(=文字列の終端を表す文字などとして利用される文字)のことです。これにより、プログラム側で最終的に付与される「.html」が無いものにされてしまう、という流れになります。
※ヌル文字の扱いはプログラミング言語によって異なります。
上記のパスによって送出されるリクエスト(URL)は以下のようになります。
https://example/temp?file_name=../../../etc/hosts%00
このリクエストにより、プログラム側でテンプレートファイルを呼び出すためのフルパスが生成されるわけですが、ヌルバイト(%00)によって「ここが文字列の終端」という意味になるため、プログラム側で「.html」が省略され、結果的に生成されるフルパス(つまり呼び出されるファイル)は以下のようになるのです。
/etc/hosts
「/」とはサーバーのルートディレクトリのことで、本来なら公開サイトからのアクセスは禁止されています。
しかし、ここまでの説明のように、「Webアプリのファイル呼び出し機能」、「../」そして「ヌルバイト」を利用することで不正アクセスが可能となってしまうのです。
ディレクトリ・トラバーサル攻撃を受ける主な原因
ここまで、具体的な攻撃例を挙げてディレクトリ・トラバーサル攻撃の流れをご説明していきました。
それでは、ディレクトリ・トラバーサル攻撃を受ける原因にはどのようなものがあるのでしょうか?
主な原因としては、以下のものが挙げられます。
- 外部からサーバー内のファイル名を指定して呼び出せる仕様になっている
- 外部からサーバー内のファイルを呼び出す際、パスにディレクトリ名が含まれている
- 外部から要求されたファイル名に対するチェックを行っていない
1つ目は攻撃の例で挙げたWebアプリの機能のことです。
実を言うと、ディレクトリ・トラバーサル攻撃においては、この外部からファイル名を指定して呼び出せる機能を実装しないことが最大の対策です。
こちらも踏まえ、このあとはディレクトリ・トラバーサル攻撃の対策方法をご紹介していきます!
対策(PHPによるコード解説あり)
対策① 外部からファイル名を指定して呼び出せる仕様を避ける
ディレクトリ・トラバーサルが実行できてしまうのは、そもそもとして、外部から任意のファイル名を指定して呼び出せる仕様になっているためです。
従って、ディレクトリ・トラバーサル対策として最も有効なのが
です。
とは言え、機能として実装が必要な場合もあるかと思います。
そうした際には以下のような代替手段を用いることで、ディレクトリ・トラバーサル対策になります。
- 呼び出すファイル名を固定のものにする=外部からファイル名の指定をさせない
- ファイル名を直接指定せず、別の表現(数字など)で指定する
繰り返しになりますが、任意のファイル名を指定できる仕様を避けることがディレクトリ・トラバーサルへの根本的な対策となります。
しかし、上記の代替手段を用いることも難しいという場合には、以下よりご説明する対策を取り入れることでディレクトリ・トラバーサルが成功してしまう可能性を低めることが可能です。
対策② 呼び出すファイルの置き場所を固定のディレクトリにする
「呼び出すファイルの置き場所を固定のディレクトリにする」とは、例えばユーザが呼び出せるファイルの置き場所を「sampleディレクトリ」に限定するという意味です。
その上で、ユーザから入力されたファイル名(攻撃者からの入力の場合はパス)からは、最後のファイル名部分のみを取得するようにします。
- sampleディレクトリへのパス
- 入力内容から取得したファイル名
上記の2つを組み合わせることで、仮に「../../../etc/ファイル名%00」という入力が行われたとしても、生成されるフルパスは必ず、
/~省略~/sample/ファイル名
という形となり、意図しないディレクトリ内のファイルへの不正アクセスを防ぐことが可能です。
実装例
上記の機能をPHPで実装する例をお見せします。
<?php
// 固定のディレクトリ
define('SAMPLE_DIR', '/var/www/html/sample/');
// 入力内容の取得
// ※GET送信データの検証処理は省略
$file_name = $_GET['file_name'];
// 入力内容からファイル名のみを取得
$sample = basename($file_name);
// パスを組み立てる
$path = SAMPLE_DIR . $sample . '.html';
?>
basename()関数は、引数で渡したパスの最後にある名前の部分(ここで言うファイル名)を返す関数です。
上記の処理により、「../../../../etc/hosts%00」という攻撃用の入力内容も、最終的には
/var/www/html/sample/hosts
となるため、不正アクセスは失敗に終わります。
※プログラム内の「.html」はヌル文字(%00)によって省略されます。
ただし、ここで1つ注意点があります!
仮に上記の「hosts」が「hosts.php」など拡張子付きで指定された場合はどうでしょう?
この場合、生成されるフルパスは拡張子「.php」までを含めた/var/www/html/sample/hosts.phpとなり、場合によっては意図しないアクセスを許してしまう恐れがあります。
こうした事態を避けるためには、入力内容から取得したファイル名(上記プログラム例の$file_name = $_GET[‘file_name’];の部分)の妥当性を検証する必要があります。
対策③ ファイル名を英数字のみに限定する
ディレクトリ・トラバーサル攻撃では「../」記号が用いられます。
そのため、ファイル名の入力を英数字に限定することがディレクトリ・トラバーサル対策となります。
実装例
<?php
// 入力内容の取得
$file_name = $_GET['file_name'];
//半角英数字のみの入力かどうかを検証
if(!preg_match( "/^[a-zA-Z0-9]+$/" , $file_name)){
// 半角英数以外の文字が含まれていた場合は処理を受け付けない
}
// 入力内容からファイル名のみを取得
$sample = basename($file_name);
// パスを組み立てる
$path = SAMPLE_DIR . $sample . '.html';
?>
上記のコードの内、以下の部分が実際に半角英数字の検証を行っている箇所になります。
//半角英数字のみの入力かどうかを検証
if(!preg_match( "/^[a-zA-Z0-9]+$/" , $file_name)){
// 半角英数以外の文字が含まれていた場合は処理を受け付けない
}
ここでは、PHPのpreg_match()関数と正規表現を用いることで検証処理を実装しています。
参考:https://www.php.net/manual/ja/function.preg-match.php
以上がPHPにおけるディレクトリ・トラバーサル攻撃対策でした。
基本的には対策①の外部からファイル名を指定して呼び出せる仕様を避けるが最も確実な対策ですが、機能的に外すことが難しい場合には、
②や③を取り入れることでディレクトリ・トラバーサルのリスクを減らすことが可能です。
まとめ
ディレクトリ・トラバーサルは本来アクセスが許可されていないファイルへ不正アクセスされてしまうことで、情報漏洩やデータ改ざん、削除といった問題に加え、漏洩した情報を元にしたアカウントの乗っ取りなどに派生してしまう危険性があるセキュリティ攻撃です。
ディレクトリ・トラバーサル攻撃が実行可能となってしまう原因は、
Webアプリに外部から任意のファイルを指定して呼び出せるという機能的な仕様
にあります。
したがって、根本的な回避策は、この仕様を実装しないことです。
しかし、場合によってそれが難しい場合には、項目「対策(PHPによるコード解説あり)」でお伝えした②、③仕様や検証処理を取り入れることがディレクトリ・トラバーサル対策になります。
セキュリティ対策は運営・開発者だけでなくそのユーザのために実施するものでもあります。
この記事でお伝えした内容だけでなく、開発するWebアプリの仕様に適した対策を施すようにしましょう。
以上、ここまでディレクトリ・トラバーサルについて詳しくお伝えをしてきました。
最後に、僕がセキュリティ対策を学ぶ際に利用した書籍をご紹介させていただきます。
体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践
徳丸 浩/著 SBクリエイティブ/出版│Amazon
こちらの書籍は通称徳丸本と呼ばれており、Webセキュリティの第一人者である徳丸浩さんが手がけられている書籍です。Webアプリを開発する方やWebアプリケーションのセキュリティ対策を徹底的に学びたい方にとてもオススメできる一冊です。
Webアプリケーション開発において、ある意味セキュリティ対策は技術力以上に重要です。
こちらの書籍を読むことでWebアプリケーションにおいて必要なセキュリティ要件も明確となるため、Webアプリ開発に携わる方は必ず目を通しておきたい一冊です。
それでは最後までお付き合いいただきありがとうございました!
また別の記事でお会いできれば光栄です!