ディレクトリトラバーサル(パストラバーサル)攻撃及びその対策
ディレクトリトラバーサル攻撃はサーバー内の非公開ディレクトリへ不正アクセスする攻撃です。情報漏えいや改ざんなどの被害が予想されます。
ツリー構造に対する相対パスなどを使った命令に忠実に従うサーバーの仕様を悪用しています。Wordpressは特に狙われやすいです。
basename関数などを使って入力命令を加工・制限する工夫が必要です。
ディレクトリトラバーサル(パストラバーサル)攻撃とは
WEBサイトはユーザーに表示させるページ以外にいろいろな裏方ファイルが存在しています。
皆さんよくご存じかと思いますが、Wordpressなどのシステムであれば
・wp-admin
・wp-content
・wp-include
などのような構成フォルダを目にした事があると思います。
そういったファイルのお陰でWEBページが適切に表示・制御されているのです。
なので表には出ていなくても絶対にそこになくてはなりません。
非公開ファイルへのアクセス行為
ディレクトリトラバーサル攻撃とは、このような本来アクセスさせる予定のないファイルやディレクトリの中身を引き出したり、不正なアクセスをする攻撃手法です。
この攻撃を受けると、本来表示させたくないファイルが流出してしまったり、システム自体を乗っ取られたりする危険があります。
・ユーザーのパスワード情報リスト
・サーバーやDBに接続できる情報
そのファイルが上記のような重要な情報の場合、それこそ目も当てられない状況になりますよね。
階層間をまたぐ(横断する)攻撃
ほぼ全てのサーバーは上記のようなディレクトリによる階層構造になっています。
サーバーは本来、各階層に配置されたファイル間をプログラムによる命令が伝達される事で動きます。
このようなツリー構造上の各ファイルを参照したり読み込む事で、最終的に要求に応じたデータを表示させる仕組みです。
サーバーは命令に忠実に動く
サーバーからファイル流出が起こる根本原因は、その要求がどこの階層下にあるファイルへのアクセスであっても、命令であれば正直に反応してしまう事にあります。
開発者が想定していない様な特殊な場所への命令でも、それを正確に処理しようとするのですね。
この反応はサーバーとしてはいたって正常な挙動なのです。
言葉の由来
トラバーサルは「横断する」という意味で、公開ディレクトリから非公開の別ディレクトリへ行き来する行為から命名されています。
別名「パストラバーサル攻撃」とも呼びます。
ディレクトリトラバーサル攻撃の仕組み
サーバーには基本以下の様な階層に分類されます。
・公開ディレクトリ
・非公開ディレクトリ
公開ディレクトリは一般ユーザーにアクセスを許可したゾーンの区画です。
それに対し非公開ディレクトリは一般ユーザーに許可をしていない、裏方ファイルが入ったエリアです。
例えばとある特定の画像ファイルを公開する架空WEBサイト(llpeg.info)で例に取りましょう。
画像ファイルを呼び出す操作
llpeg.info/img/という公開ディレクトリ内にある画像ファイルを表示する機能があったと想定します。
このディレクトリ中には「aaa.jpg」「bbb.jpg」のように画像ファイルが保存されています。
またこのimgディレクトリとは別に「secret」という非公開ディレクトリもあり、そこには公開しない情報が入っているものとします。
imgディレクトリとsecretディレクトリの位置関係
公開ディレクトリ内の画像を表示する
公開ディレクトリのパス「llpeg.info/img/」に入っている画像名を入力フォーム入力する事で表示する仕組みになっているとします。
入力したファイル名が「aaa.jpg」であれば、公開ディレクトリパスと結合して「llpeg.info/img/aaa.jpg」というパスになります。
そしてその画像ファイルを読み込んでユーザーに表示するのですね。
公開ディレクトリパスは変更できない
ここで公開ディレクトリのパス「llpeg.info/img/」が付くのはWEBアプリケーション側での決まり事です。
ユーザーの方では上記のディレクトリ名を指定する事はできません。
ですのでこのようにWEBアプリケーションの仕様を決めておけば、ふつうimg以外のディレクトリへのアクセスは不可能ですよね。
入力データに相対パスが入る場合
では仮に、入力するファイル名に「../secret/ccc.jpg」と相対パス入りの命令を送信したとします。
WEBアプリケーションは「llpeg.info/img/」の公開ディレクトリに対し、入力されたファイル名「../secret/ccc.jpg」をそのまま結合します。
相対パスを含んだ結合結果のパス
となると結合結果は下の様になりますよね。
llpeg.info/img/../secret/ccc.jpg
ディレクトリ間を横断する
この時入力された文字列中の「../」は一つ上の階層ディレクトリを意味します。
そうなると「open」ディレクトリを一つ登って、本来公開していない別階層の「secret」ディレクトリにアクセスできてしまいます。
この結果WEBアプリケーションは見せるつもりのない、ccc.jpgをユーザーに表示してしまう事になるのですね。
llpeg.info/img/../secret/ccc.jpg
↓
llpeg.info/secret/ccc.jpg
今回は画像ファイルを例にとりましたが、これが.txtなどのファイルで中にパスワードなど重要な情報が記載されていた場合、事態は深刻になります。
ディレクトリ名はリスト攻撃で突破される可能性もある
今回は「secret/ccc.jpg」と画像のパスが事前にわかっていた場合のお話でした。
通常非公開ディレクトリであれば、どのような名前にしているのかは普通はわかりません。
しかし仮にsecret等のファイル名がわからなくても、ありそうな単語による「リスト攻撃」を受けてしまえば突き止められてしまう可能性がありますよね。
ディレクトリリスティング攻撃にも注意
ましてや、発見されたsecretディレクトリにindexファイル等を置いて無かった場合はまずい事になります。
「../secret/」と命令される事でディレクトリ内を全て把握されてしまうのです。
これが「ディレクトリリスティング攻撃」と呼ばれるものです。
狙われてしまう脆弱なコード例
以下のコードは各ユーザーのプロフィール情報が個別のファイルとして格納されているアプリケーションの例です。
全てのファイルは同一のディレクトリに保存されているとしましょう。
脆弱コード
サンプル言語:Perl
my $dataPath = "/users/clue/profile"; my $username = param("user"); my $profilePath = $dataPath . "/" . $username; open(my $ff, "<$profilePath") || ExitError("profile error: $profilePath"); print "<ul>¥n"; while (<$ff>) { print "<li>$_</li>n"; } print "</ul>¥n;"
上記をコーディングをしているプログラマーは基本的に
・"/users/clue/profile/aaa"
・"/users/clue/profile/bbb"
等のファイルへのアクセスを想定しているため、パラメータの入力を考慮していません。
ここで攻撃者は以下のような文字列を入力します。
入力パラメータ
../../../etc/passwd
このパラメータの入力によりプログラムは以下のようなパス名を結合します。
結合結果
/users/clue/profile/../../../etc/passwd
システムはファイルが開かれる際に、パスを正規化しようと「../」部分の解決を行います。
実際には以下のファイルにアクセスする事になります。
最終結果
/etc/passwd
/users/clue/profileの部分を../../../で全てさかのぼってしまうのですね。
結果、攻撃者は/etc/にあるpasswdファイルを全て把握する事が可能となります。
Wordpressへのディレクトリトラバーサル攻撃
ディレクトリトラバーサル攻撃は、有名なCMSであるWordPressの設定ファイルを不正に読み取る攻撃でも多く見られます。
CMSシステムであるWordPressには、機能拡張を行うためのプラグインが豊富に用意されていますよね。
しかしこの拡張機能にはディレクトリトラバーサルの脆弱性が多く、よく攻撃の対象にされています。
wp-config.phpのディレクトリトラバーサル攻撃例
以下が、不正にwp-config.phpの読み取りを試みる攻撃リクエストの例です。
wp-config.php攻撃リクエスト例
/wp-content/themes/テーマ名/download.php?file=../../../wp-config.php /wp-content/plugins/プラグイン名/download.php?download_file=../../../wp-config.php
テーマやプラグイン上のディレクトリトラバーサルの脆弱性を悪用し、TOPにある設定ファイル(wp-config.php)を不正に読み取ろうとしている例です。
Wordpressはシステム構成が周知されている
Wordpressは階層の位置関係が一般的に共通なので、どこにどのファイルがあるのかが誰でもわかるのですね。
中でもwp-config.phpには、データベースのホスト名やユーザー名パスワードなどの重要な情報が記録されている事は知られています。
wp-config.phpは、絶対に不正に参照されたり外部に漏れてはいけないファイルです
Wordpressのテーマやプラグインは他人が作ったもの
Wordpressの一番怖いところは、テーマやプラグインを自分で一から作る訳ではなく、他人が作ったものを利用する点にあります。
作った人の事を一切知らずに機能だけを利用しているのです。
バージョンアップは脆弱性対策
テーマやプラグインに対し、攻撃を受ける様な脆弱性があるかどうかは開発者のレベルに比例します。
定期的にテーマやプラグインのバージョンアップがおこなわれるのは脆弱性対策がほとんどなのですね。
ですので脆弱性が発見された場合は必ず行う必要があるのです。
ディレクトリトラバーサル攻撃による被害
個人情報や企業データの漏洩・流出
ディレクトリトラバーサルによる攻撃が成功すると、非公開のはずのファイルを閲覧・ダウンロードされ、情報漏洩や流出が起きます。
公的機関や企業の公式サイト・サービスで個人情報が流出した場合、利用ユーザーが直接的、間接的に甚大な被害を受ける恐れがあります。
同時にそのサービスを提供する企業イメージや信頼性も失墜する事になるでしょう。
システムを乗っ取られてしまう可能性もある
もし閲覧されたファイルの中にIDやパスワードが含まれていた場合、不正ログインされてシステムやサービスを乗っ取られてしまう可能性があります。
流出した個人情報データ(メールアドレスとパスワード)を使って、他のサービスのアカウントやSNSへ不正ログインされてしまう事もあるのです。
WEBページやサービスの改ざんやデータ削除
非公開ファイルに不正にアクセスし、データの改ざんや削除をされてしまう恐れもあります。
例えば改ざんにより企業イメージを損ねる様な表現や情報が発信された場合、信頼性が無くなり、利用ユーザー離れにつながります。
データ自体を削除されてしまえば、コンテンツ消失によるサービス停止など直接的な被害が発生することも考えられます。
有名な被害実例
2019年11月、トレンドマイクロ株式会社製の複数の製品にディレクトリトラバーサルの脆弱性が存在する事が発表されました。
第三者によって遠隔操作にて管理コンソールの認証回避がされ、ルートユーザーアカウントでログインされる可能性があるとの事でした。
対応としては、開発者が提供する情報をもとに本脆弱性の対策専用のパッチを適用する事になっています。
サイバー攻撃から身を守るために作られたセキュリティソフトが逆にその脆弱性から攻撃の対象になってしまうという、嘆かわしい事件です。
ディレクトリトラバーサル攻撃を防ぐ対策
対策コンセプトは、入力された内容をそのまま正直にサーバー側で処理しない様に多重の工夫をする事です。
入力内容の加工方法
・basename関数を使ってディレクトリ名を消す
・非公開ディレクトリにはアクセス拒否を設定
・「/」や「\」を含むパス名を禁止する
・入力されたパスの前方一致・部分一致を使用
・入力内容に「../」や「%2e%2e%2f」などの文字が含まれないかをチェック
「%2e%2e%2f」はエンコード後に「../」と同じ文字列になるので注意です。
ポイント
最善策としては、ディレクトリパスが入力された際にはbasename関数などでディレクトリ部分を取り除き、ファイル名だけを使用する事でしょう。
いずれにしても直接入力された文字列をそのまま使用されることがないよう、処理するべきです。
これにより相対パスなどで上部階層から非公開ファイルへとたどり着く事を防げます。
設計者がパスのエンコードやセキュリティに対する知識・経験が高ければ、それだけ攻撃を受けにくくなりますのでレベルアップが必要です。
basename関数のコード例
basename関数は、ファイルあるいはディレクトリへのパスを含む文字列から、最後にある名前の部分を返します。
<?php echo basename("/users/clue/profile/aaa.php") ."\n"; echo basename("/users/clue/profile/") ."\n"; echo basename("/users/clue/") ."\n"; ?>
実行結果
aaa.php profile clue
この関数を使えば最後にあるファイル・ディレクトリ名のみに抽出されるので、パラメータを含む命令が実行される事はありませんね。
IPAの安全なWEBサイトの作り方による根本的対策
・外部からのパラメータでWEBサーバー内のファイル名を直接指定する様な機能を避ける。
・ファイルを開く際は固定のディレクトリを指定し、かつファイル名にはディレクトリ名が含まれないようにする。
の2つが紹介されています。
繰り返しになりますが、basename関数を利用すればパスからディレクトリを取り除いてファイル名だけを取り出す事ができます。
そもそも論として、外部からの入力値でファイル名を指定する機能を搭載しない事でしょう。
WAFを導入して不正アクセスを検知
「WAF」とはWEBサーバー側で導入できるファイアーフォールです。
WEBアプリケーションレベルで外部攻撃に対する監視およびセキュリティ機能を持っています。
例えば閲覧禁止としているファイルに外部から不正侵入があればそれをブロックします。
不正アクセスに対しては、403 Forbidden(アクセス権がないから閲覧禁止)を出して遮断します。
ログで攻撃遮断履歴を確認できる
WAFが検知して侵入を防いだ場合はログに残ります。
特にWordpressサイトの管理者はWAF機能を有効にしておくべきです。
wp-config.phpからさか上って侵入を試みたり、テーマのdl-skin.php経由の攻撃などをブロックした履歴が残ります。
WAFのログ確認画面(ロリポップの場合)
ファイル位置の示し方「パス」について
サーバーが稼働する仕組みを知る予備知識として、読込・実行するファイル位置の「示し方」に関する説明をしておきましょう。
ファイル位置の書き方(パスの書き方)には「絶対パス」と「相対パス」とがあります。
※絶対パスは別名「フルパス」とも呼ばれます。
絶対パス(フルパス)
絶対パスとは、例えばWEBサイトであればそのURLを先頭にした階層構造下で、ファイル位置を示す表示方法です。
例えば本サイトlpegであれば上記画像ファイルを示す絶対パスは下記になります。
・https://lpeg.info/images/directory_traversal_img1.jpg
この時、/images/directory_traversal_img1.jpgとする事でも同じ画像を指定した事になります。
先頭の「/」がサーバーにはドメイン名の部分と判断されているのですね。
このように認識する事がサーバーの正常な判断なのです。
相対パス
絶対パスは上の様に、階層構造の一番上からみた経路でした。
それに対し相対パスは「現在のファイル位置」をスタート地点とし、そこからの経路を示します。
例えば今ご覧になっている本WEBページは
https://lpeg.info/security/directory_traversal.html です。
画像ファイルを示す相対パス
本ページで上記の画像ファイルを示す場合は、画像フォルダ「images」は「security」と同位置にありますから
../images/directory_traversal_img1.jpg
この本ページから画像を読み込むパスは上記の様になります。
一つ上の階層に上がる命令「../」
一つ上の階層に上がる命令が「../」(ドットドットスラッシュ)です。
securityと同じ階層にあるimages/フォルダに入って画像ファイルを指定しています。
この様に現在のディレクトリの1つ上の階層を表す場合は「../」パスを使用することができます。
2つ上の場合は「../../」になりますね。
下に下がる場合はディレクトリ名を指定しなければ入る事ができません。
しかし上に階層に上がる場合は「../」と指定すれば、どんなディレクトリ名でも上へ行く事ができるのがポイントです。
ディレクトリトラバーサル攻撃はこの「../」が使われた相対パスを正規化する処理を悪用しています。
指定されたパスをそのまま文字通り処理すると、勝手に上部階層に登ってしまう事を許してしまうのです。
まとめ
今回はディレクトリトラバーサル攻撃について、その仕組みや被害・対策をご紹介しました。
今回の様にサーバーに本来の意図と違った挙動や処理をさせる事がサイバー攻撃のメインとなっています。
サーバーに「動いてほしい命令」を掛けるためには、「それ以外の動いてほしくない命令」を指定する必要があるのです。
これはプログラムを作成する上での基本となる考え方ですが、まだ完全に準拠されてはいません。
実際にこの様な「隙を付かれた攻撃」が現在も数多くおこなわれています。
ユーザーの自由にさせない事も利便性につながる
ディレクトリトラバーサル攻撃がおこなわれないようにするため、ユーザーの入力を制限する事も必要です。
それがひいてはサービスやWEBページを利用するユーザーの利便性につながります。
・ユーザーからの入力にある程度の制限を設ける事
・悪意のある攻撃をすぐに検知・排除する仕組みを導入する事
設計の段階からWEBセキュリティを高くするためには大切な課題でしょう。