【初心者目線】Webアプリケーションの開発 第6回

【初心者目線】Webアプリケーションの開発 第6回を書きます

1. ポートのセキュリティについて

システムのハッキング・クラッキングによる企業の顧客情報流出に関する事件のニュースや記事を、誰もが一度は見聞きしたことがあると思います。

このような事件は企業内部にいる人間の犯行である事例もありますが、外部からシステムに不正なアクセスがされたことにより発生することも多くあります。

1-1. ポートスキャン

悪意のあるユーザにより外部から不正にシステムにアクセスする場合、まず最初に行われるのが「ポートスキャン」という行為です。

これは、サーバーでどのようなサービスが実行されているかを確認する方法です。


例えば、下図のように開いているポート(反応がある)を探し、そのポートを通じて接続を試みます。


システムに接続するためのユーザIDやパスワードを、容易に想像できるようなものに設定していたり、そのサービス自体に不具合やバグなどのセキュリティホールが存在する場合、悪意のあるユーザにより不正アクセスされる危険性が非常に高まります。

それでは、Linuxの「nmap」というコマンドを使用して、ポートスキャンの実行例を確認します。


PORT(ポート番号)、STATE(状態)、SERVICE(サービス)の項目があり、どのポートが開いているか、またそのポートでどのようなサービスが実行されているかを確認できます。

STATE(状態)がopenとなっているポートは解放されており、closedとなっているポートは閉鎖されている状態を表しています。


上記の実行例の場合、下線部②の23番ポートのtelnetサービスがopen状態なのが危険です。

telnetはセキュアな接続を行わない(暗号化されていない)リモートコンピュータとの通信方法なので、悪意のあるユーザによりユーザID、パスワードが盗まれるとサーバが乗っ取られる可能性があります。


また、下線部①の21番ポートのftpサービスがopenなのも要注意です。

ファイル転送に使用されるFTP通信には通常ユーザIDとパスワードを入力する必要がありますが、「anonymous FTP」と呼ばれる機能があり、匿名接続ができるサーバであれば誰でもファイル転送ができるため、コンピュータウィルス等の不正なファイルを送信される可能性があります。


悪意を持ったユーザの攻撃からシステムを守る方法はいくつかありますが、基本的な方法として使用していないポートは解放しないといったことが挙げられます。

上記ポートスキャンの例でいうと、sshという暗号化された通信サービスがopenになっているので、暗号化されていないtelnetをopenにしておく必要はありません。


自身のシステムに対しポートスキャンを行う行為は問題ありません。

しかし、外部からポートスキャンを受けていると気づいた場合は、既に悪意を持つユーザが攻撃の準備をしていると考えられるため、システムのリアルタイム監視や不正侵入防止に関する対策をとる必要があります。

2. GETメソッドによる情報の送受信

私たちがWebアプリケーションに情報を渡すための方法はGETメソッド、POSTメソッドの2種類あります。

ここではGETメソッドによる引き渡し方法について解説していきます。

2-1. パラメータの引き渡し

例えば以下のような足し算ができるHTMLフォームがあるとします。

計算するボタンを押下すると「123+456」の計算結果が表示されます。


このWebページのHTMLは以下のように構成されています。※一部抜粋


上記の下線部①、②にはそれぞれ「arg1」「arg2」というname属性が付けられています。

これはWebページのテキストフィールドに入力された文字列が「arg1」「arg2」という名前でWebサーバへ送られることを表しています。


今回のHTMLフォームでは「計算する」ボタンを押下した際、下線部③のaction属性で指定されたURLへアクセスしています。

また、下線部④のmethod属性で指定された方法でデータの受け渡しを行っており、今回はGETメソッドを使用して入力内容を送信することを表しています。


上記の内容を踏まえた上で、HTMLフォームからWebサーバに情報を送信する方法について確認します。


上図はGETリクエストで送られたHTMLフォームの情報を表しています。

1行目のリクエストラインのURLの最後に「?」が付与されており、今まで見てきたURLには無かった文字列が追加されています。

この下線部の部分は「クエリ文字列(Query String)」と呼ばれ、HTMLフォームに入力された文字列をWebサーバに渡すために使用されています。


Webサーバ側はリクエストラインの中に「?」マークが存在する場合、以降をクエリ文字列として認識し、文字列に含まれるパラメータをアプリケーションに渡しています。

今回のように、パラメータ間を「&」で区切ることにより複数のパラメータをWebサーバに渡すことも可能です。

2-2. パラメータの受け取り

GETメソッドにより引き渡されたパラメータが、アプリケーション側でどう処理されるのか解説します。

以下はGETリクエストで指定された「get_calculator.php」のソースコードを一部抜粋したものです。


枠線部①の部分はクエリ文字列に格納された値を取得して、取り出した値を変数「&arg1」「&arg2」に格納しています。

言語によりパラメータ値の取り出し方は変わりますが、考え方は同一になります。


下線部②の部分は変数「&arg1」「&arg2」の値を足した結果を、変数「&result」に格納しています。

下線部③の部分はecho文でHTMLを出力しています。

これはフォームの「計算する」ボタン押下後の画面に出力されていた「123 + 456 = 579」の文字列を生成し出力するための処理になります。

3. POSTメソッドによる情報の送受信

ここまでGETメソッドについて解説しましたが、GETメソッドにはとある大きな問題点がありました。

それを解決できる引き渡し方法として、POSTメソッドという方法があります。

ここからはそのPOSTメソッドについて解説していきます。

3-1. GETメソッドの問題点

GETメソッドはURLの末尾にパラメータを付与しWebサーバへ情報を送信していると説明しましたが、Webサーバはその受け取ったGETリクエストをログとしてサーバ内に残しています。

そのためユーザIDやパスワード等の機密情報がパラメータに含まれていると、第三者がログを見た際に機密情報が知られてしまう危険性があります。

3-2. パラメータの引き渡し

POSTメソッドによるパラメータの引き渡しですが、HTMLフォームの見た目はGETメソッドの時と変わらず、Webページを利用するユーザは特に意識することはありません。


ただし、上図に示す通りPOSTリクエストで送られたフォームの情報には異なる箇所が存在します。

まずリクエストラインの下線部①の箇所が、GETではなくPOSTになっています。

また、クエリ文字列がURLに含まれていません。

では何処にパラメータが含まれているかというと、下線部②のメッセージボディの部分に含まれています。


このようにメッセージボディを利用してパラメータを渡すことにより、Webブラウザのアドレスバーにパラメータが表示される事がないため、第三者に情報を見られる可能性が少なくなります。

また、通常メッセージボディをサーバのログに残す事は少ないため、ログが見られる事により情報漏洩する可能性も低くなります。

3-3. パラメータの受け取り

POSTメソッドにより引き渡されたパラメータが、アプリケーション側でどう処理されるのかをGETメソッドの時と同様に確認してみましょう。

以下はソースコードを一部抜粋したものです。


GETメソッドでパラメータを渡した場合との違いは、枠線部①の「$_GET」が「$_POST」に変化しただけでほとんど違いはありません。

よってGET/POSTのどちらのメソッドでパラメータを渡したとしても、受け取り側のアプリケーションの処理には大きな違いは無いと言えます。

4. GETとPOSTの使い分け

パラメータを引き渡しではPOSTリクエストの方が安全性が高いため、POSTリクエストのみ使用すれば良いのではないかと思う方もいると思います。

ただし、GETリクエストにはPOSTリクエストにはない利点があります。


上記はGoogleで「GETMethod」について調べた際のURLですが、下線部のようにGETメソッドを使用してパラメータの引き渡しを行っていることがわかります。


例えば皆さんがこの検索結果をあとでまた閲覧したい場合は、Webブラウザの「お気に入り」などに保存し、見たいときに目的のページを参照する事が出来ます。

また、検索結果をSNSなどで共有したい場合は、URLをコピーし貼り付けて投稿することにより様々な人とページを共有することができます。


このようにGETメソッドはURLにパラメータが含まれるので、パラメータ(検索語)ごと保存・共有でき、同じURLを使用すれば何度でも同一の結果が得られます。

一方POSTメソッドはメッセージボディにパラメータを格納するため、お気に入り登録などでパラメータを保存することはできません。


GETメソッドのように、同じ要求を複数回繰り返しても同じ結果が得られることを「副作用がない」と言います。

リクエストの結果によりシステムの状態に影響を与えないようになっていることが重要です。


GETリクエストとPOSTリクエストの使い分けを簡単にまとめると、上記の表のように表せます。

ユーザ名やパスワードのような機密情報を送信する場合(ログイン処理など)や、ショッピングサイトでの決済手続きなどの副作用を伴う処理は、POSTメソッドの使用が必須になります。


一方、Webブラウザで単語の意味を検索するといったセキュアな処理を必要としない場合は、パラメータ(検索語)ごとお気に入りに保存できるGETメソッドを使用すると便利になります。

5. 第6回 まとめ

今回はポートに対する攻撃やその対処方法、GET/POSTメソッドのパラメータ引き渡し方法の特徴などを
説明してきました。

Webアプリケーションは常に悪意のあるユーザの脅威にさらされています。


ポート解放の判断やパラメータ引き渡し時に使用するメソッドの選択を誤ると、大きな被害を被ることにつながります。

大切な情報を守るためにもセキュリティに関する知識は必要不可欠です。


次回はパラメータの渡し方をもう少しだけ解説予定です。