こんにちは、R&D統括本部 開発推進室 セキュリティプラットフォーム技術 セキュリティスペシャリストの戸田 薫です。 今回は、私たちが普段からヤフーのシステムに対する入力にどのような注意を払っているのか、そのいくつかをご紹介致します。
入力とは?
Webサイトを運営している場合、どのような入力があるでしょうか?
たとえば、Webサービスには、以下の入力があります。
- Cookie
- URL
- GET/POSTのデータ
- ファイルのアップロード
- その他リクエストヘッダ
そのほかにもいくつもあります。
- 環境変数
- 設定ファイル
- クローラが取得したデータ
- パートナー企業のAPIから取得したデータ(XMLやJSONなど)
- パートナー企業の入稿用 FTP サーバ
- メール
入力チェックはなぜするのか?
入力されたデータをなぜチェックするのでしょうか? それは、さまざまな目的があります。
- お客様の情報をお守りするため
- お客様を脅威からお守りするため
- 不快になるようなコンテンツを掲載しないため
- システムが安全に動作するため
- 意図したサービス・データを提供するため
データの経路は複数存在する
ヤフーへ入ってくるデータの経路は複数存在します。 お客様にご利用頂いているサービスやパートナー企業様へ提供しているツールや連携しているシステムなどさまざまです。
お客様にご提供しているサービスで例をいくつか挙げます。
- Webサービス(HTTP)
- メール(SMTP/POP, IMAP)
- FTP
データが入力されるすべての経路で、入力値のチェックをしなければなりません。
何も信じるな
ヤフーの社内向けのセキュリティの研修では、よく以下のことを言っています。
入力されるものは、何も信じてはいけません。 あなたの開発するシステムは、あなた以外が守ることはできません。 すべてに対して憶病になり、疑いを持ち、あらゆるものを心配してください。
そういった姿勢が大切だと考えています。
たとえば、セレクトボックスで項目を選択するフォームを作ることがあります。 そのページに訪れたお客様は、セレクトボックスを選択して、送信ボタンを押します。
そのページから送信されてくるデータはすべて信頼できるのでしょうか? すべてのリクエストのデータは、誰でも書き換えられます。 そういったツールも充実しており、簡単に変更することが可能です。 POST/GETも関係はありません。URL、Cookieもそれ以外のリクエストヘッダも何もかもが変更可能です。 クライアント側でのいかなる制限も無効であると考えなければなりません。
私たちが本来提供したいサービスとは異なる現象を発生させないために、期待したデータがきたのか、きちんとチェック(インプットバリデーション)をしなければなりません。 おかしなデータを登録されたときに、カスタマーサポートなどに余計な手を煩わせることにもなります。 システムで防げることはシステムで防ぎ、お客様も私たち自身も楽になるべきなのです。
ホワイトリストとブラックリスト
入力のチェックには、いくつものチェックがあります。 入力を許したいもの、許したくないものがあるとき、ホワイトリストやブラックリストを使用します。
ヤフーでは、ホワイトリストの利用を推奨しています。 ホワイトリストとブラックリストは、ケースバイケースで使い分けられます。 ホワイトリストを推奨している背景には、「登録漏れ」を避けるためです。
ブラックリストは、利用させたくない対象をすべて列挙しなければなりません。 ホワイトリストは、許可したい対象を列挙しなければなりません。 どちらも許可したいもの、許可したくないものを列挙しなければなりません。
ホワイトリストで「登録漏れ」があった場合には、「登録漏れ」が利用できないだけです。 ブラックリストは漏れがあった場合に被害が生じる可能性があるからです。
許可したいもの、許可したくないものは、いつまでも同じものしか存在しないでしょうか? たとえば、HTMLのタグを許すリスト、許さないリストを想像してみてください。 新しい HTML 規格のバージョンが出来たときに、それ以前には存在しなかった HTML タグや属性が増えているかもしれません。 ブラウザベンダがブラウザをバージョンアップしたときに新しい独自タグが追加されるかもしれません。 このような変化があったときに、ホワイトリストアプローチの方がセキュリティ上の問題が起きにくいと考えられます。
入力チェックライブラリ
ヤフーのWebアプリケーションに入力された情報やパラメータは、すべての入力がチェックされます。 テキストデータの入力チェックは、 ヤフーのセキュリティに対する取り組みについて 第2回目 で紹介したヤフーの入力チェックライブラリで行います。 基本的にすべてのサービスで共通のライブラリを利用しています。 入力チェックライブラリでは、危険な文字列の除去やデータの形式の確認を行えます。 C言語で実装されたライブラリで、いくつもの言語のエクステンションとして提供されています。 入力された目的に応じて、チェックのオプションを使い分けます。
いつ入力チェックをするのか
ヤフーでは、入力チェックをするタイミングは、入力時に実施されることが多いですが、ページを生成するときにチェックしている場合もあります。 ヤフーのサービスでは、デフォルトで入力時に危険なHTMLタグが除去されます。
入力チェックは、システムの仕様に応じて、適切だと考えられるタイミングで実行すればよいですが、 入力チェックは、「値が使われる」ときや「お客様に表示される」ときに、漏れがなくチェックされていることが重要です。
データの形式でチェックする
入力されるデータには、それぞれに目的があります。
- メールアドレスを登録するフォームでは、メールアドレスが入力されなければなりません。
- ブックマークを登録させるフォームでは、URLが入力されなければなりません。
- 誕生年月日を入力するフォームでは、年、月、日の数字が入力されなければなりません。
入力された文字列が適切な形式であるかチェックします。 ヤフーの入力ライブラリでは、以下のような形式をチェックできます。
- 整数
- 負の値
- 実数
- URL
- メールアドレス
数値のチェック
一般的に数値を入力するフォームで、テキストが入っていたらエラーを表示して、再度入力していただくような実装をします。 そういったときに、数値のパラメータに、数値が入ってきたのか、確認しなければなりません。 データの形式をチェックするとともに、数値の範囲もチェックすべきです。 たとえば、金額であれば、0円以上になるはずです。
数値を扱うときには、以下のことを意識すべきです。
- オーバーフローの可能性がないかチェックしなければなりません。
- すべての数値には、最小値と最大値の制限を設けなければなりません。
- 整数は整数として扱い、実数は実数として処理されるべきです。
URLのチェック
登録処理が終わったら、元のページにリダイレクトして返すときに、URLのパラメータでURLを受け取るような場合に、そのパラメータが妥当なURLであるかをチェックしています。 ヤフーでは、そのようなリダイレクトをする場合には、URLの妥当性をチェックするとともに、リダイレクト先ドメインが許可したサイトであるかどうかも確認しています。 なぜなら、そういったパラメータをフィッシングに悪用されない対策が必要だからです。 フィッシングについては、 ヤフーにおけるフィッシング対策 をご覧ください。
文字列のチェック
すべての文字列には、最大サイズを設けなければなりません。 それは、入力される悪意のある命令を最小限にするためです。
文字列は、危険なHTMLタグや制御文字列をストリップしなければなりません。 危険なHTMLタグを取り除くのは、XSS(Cross Site Scripting)の対策です。
入力チェックライブラリでは、HTMLタグの除去やHTMLエンティティへ変換できます。 さらに、HTMLのフィルターの機能を持っており、許可したHTMLタグや属性以外を取り除くこともできます。 このフィルターは、マクロで簡単に新しいフィルターを追加できるようになっています。 HTMLタグを許すフィルターは、ホワイトリスト形式で実装されています。
マニュアルでデコードしたデータは信用しない
データを受け渡す過程で、データをあるエンコーディングに変換することがあります。 たとえば、 BASE64 エンコードや URL エンコードです。 BASE64 デコード や URL デコード した場合には、そのデコードしたデータを信用してはいけません。
ヤフーでは、デコードしたデータは、入力チェックライブラリでチェックしています。 デコードしたデータのチェック漏れを防ぐために、ヤフーのソースコードスキャナーが検出します。
変換も信用しない
サービスの要件によって文字列をあるルールで変換することもあります。 たとえば、一部の文字を全角から半角に変換する、といったものです。 こういった変換は、モバイルサイトの場合に行われます。 文字列が全角の間は無害であっても、半角に変換したときに、その文字列が無害であることは保障されません。 そのため、デコードと同様に変換を行ったあとに、入力チェックを行う必要があります。
環境変数も信用しない
環境変数で設定されている値を使用しているシステムもあります。 環境変数であってもバリデーションしなければなりません。
ヤフーでは、ソースコードスキャナーによる「マニュアルのデコードの入力チェック漏れ」のチェックと同様に、「環境変数の入力チェック漏れ」のチェックを行っています。
JavaScriptやCSS向けのチェック
入力された値を、JavaScriptのコードに埋め込むことやCSS の属性の値に設定することがあります。 ブラウザによっては、文字列の間にブランクがあっても連続した文字列として認識されてJavaScriptとして解釈し実行するものや全角文字のコードをJavaScriptとして認識するものもあります。 JavaScript/CSSに入力値を扱うときでも XSS の危険性がないように入力ライブラリの専用のオプションでフィルタリングすることが可能です。
クライアントサイドのチェック
ブラウザでJavaScriptを利用し、クライアントサイドの入力チェックを実装することがあります。 たとえば、フォームに入力されたデータの形式が正しいか、長さは適切か、といったものです。
クライアントサイドのチェックは、サーバとの通信を発生させずにチェックができるため、お客様にとっても、サービスプロバイダにとってもパフォーマンスの面で有用です。 しかしながら、クライアントサイドでチェックしているから、サーバサイドでチェックしなくてよいという意味には、なりません。 クライアントは、どのようなデータでもサーバに送信ができるため、送信されてきたデータを信頼することはできません。 HTMLタグの属性で文字数制限を設定することも可能ですが、これも無視されるものとして、サーバサイドで文字数の制限を別途しなければなりません。
入力チェックの品質を一定にする目的のために、FlashやSilverlightのアプリケーションで、HTMLの入力を受け取る場合には、Flash/Silverlight側ではチェックせずに、サーバサイドのヤフーの入力ライブラリでチェックするようにしています。
Cookie
ヤフーの発行するCookieは、多くの場合、シグネチャが含んでいるか、暗号化されています。 これは、改ざんを防止し、お客様の情報を守るためです。 ヤフーがサービス全体で利用しているCookieは、yApache(Yahoo!バージョンのApache Web Server)がデフォルトで利用するモジュールの中で自動的にバリデーションが行われます。 サービスがサービスのために独自に発行しているCookieについては、それぞれのプログラムでチェックされます。 Cookieのライブラリを利用することで、暗号化/復号化やシグネチャのチェックが自動的に行われます。
もう1つのURLチェック
URLとして入力されるべきテキストがURLの構造をしているかチェックすることや、URLのドメインのチェックは、入力ライブラリで行われると説明しました。 ヤフーでは、もう1つのURLのチェックの機能を持っています。 入力されたURLが以下のサイトでないか、確認するための URL データベースを持っています。
- フィッシングサイト
- マルウェアやウイルスを配信しているサイト
- 不適切なコンテンツのサイト
このURLのチェックは、リダイレクトなども追跡して、バリデーションが行われます。
テキストのチェック
ここでの入力チェックは、セキュリティのためではないチェックを行っています。 サービスに表示するテキストが適切なものであるか、というのもチェックしなければなりません。
たとえば、以下のチェックが必要になります。
- ヤフーのレギュレーションに沿ったものであるか
- 薬事法を守っているか これは、ショッピングやオークションなどで出品されたデータの確認です。
ショッピングやオークションにおけるストアの開設や商品の登録でも入力チェックを行っています。
SQL インジェクション
ヤフーの入力ライブラリによって値のチェックなどを行っていますが、SQL インジェクションの対策としては不十分です。 そのため、SQL インジェクションの対策には、プリペアドステートメントで対応します。 ただし、プリペアドステートメントでは、XSS の対策にはならないため、入力ライブラリと併用する必要があります。
CSRF
入力チェックには、 CSRF (Cross Site Request Forgery)の対策も含まれます。 お客様のデータの更新(データベースやCookie)や参照(たとえばお客様の情報を返すJSONで返すAPI)を行う場合に、チェックが必要です。 CSRF のチェックでは、セッションやタイムアウトの確認も併せて行います。
ウイルススキャンによるチェック
ヤフーでは、パートナー企業などから入稿されたデータのウイルススキャンを念のために行っています。 これは、ヤフーがウイルス配信のプラットフォームにならないためであり、ヤフーをご利用になっているお客様を守らなければならないからです。
ファイルのチェック
拡張子は、jpg であっても、ファイルの中身は JavaScript の場合、Internet Explorer 6 だと JavaScript が実行されるといった問題がありました。 そのため、画像を配信しているドメインの権限で、JavaScriptが実行できる、つまり XSS の問題がありました。 アップロードされた画像ファイルがちゃんとした画像ファイルであるかを確認することや、サービス用のドメイン以外(.yahoo.co.jpドメイン以外)で配信するといった対策が必要になります。 この対策には、サービス用のFQDNやVIP、リアルサーバのホスト名などが yahoo.co.jp ドメインではない、もしくは、 yahoo.co.jp のFQDNでインターネットからアクセスができないようになっていなければなりません。
実際にこの対策を行っているサービスを1つ紹介します。 Yahoo!メールで添付ファイルを開くときに、 ファイルのURLのドメインの部分が yahoo.co.jp ドメインではなく、IPアドレスになっているのは、セキュリティ対策の一環です。
最後に
お客様の情報を守り、脅威からお客様を守りするためにいろいろなタイプの入力チェックがあることをご理解いただけたと思います。本稿で紹介したチェック以外にもサービスの要件などによっていくつものチェックが行われています。 サービスの規模に関係がなく、1つでも穴があいていると、サービス全体に影響をおよぼしかねません。 そのために、ソースコードスキャナーによるチェックやリリース前に脆弱性スキャナーでアプリケーションのチェックを実施することを義務付け、定期的にサービスの脆弱性チェックを行っています。 今後もよりよいサービス提供のために、厳しくチェックをしていきたいと思います。
こちらの記事のご感想を聞かせください。
- 学びがある
- わかりやすい
- 新しい視点
ご感想ありがとうございました