ウェブサイト構築時のセキュリティのポイント

IPA(独立行政法人情報処理推進機構)の「安全なウェブサイトの作り方」というドキュメントは、なかなかまとまっていて、良い。すべてのウェブアプリ開発者は目を通しておくべきだ。ここではこのドキュメントから注意点をピックアップしてまとめてみた。
  1. SQL インジェクション
  2. OS コマンド・インジェクション
  3. パス名パラメータの未チェック/ディレクトリ・トラバーサル
  4. セッション・ハイジャック
  5. クロスサイト・スクリプティング
  6. クロスサイト・リクエスト・フォージェリ (CSRF)
  7. HTTP ヘッダ・インジェクション
  8. メールの第三者中継
以下は、各ポイントの問題と対策。
  1. SQL インジェクション (問題) リクエスト URL を https://www.yourdomain.com/post.php?param=XXXXX とすると、攻撃者が XXXXX のところにSQL 文を書いて SQL を実行してしまうこと。 (対策) XXXXX に SQL が書かれても大丈夫なようにサーバスクリプト側でエスケープする必要がある。また、サーバ側のスクリプトのエラーメッセージもブラウザに表示されてしまうと、攻撃者にとっては攻撃の手がかりとなるため、カスタムエラーを表示させるようにすると良いかもしれない。
  2. OS コマンド・インジェクション (問題) Perl の場合は open(), system(), eval()、PHP の場合は passthru(), shell_exec(), system(), popen() など、サーバ側スクリプト(プログラム)からOS 上にある他のプログラムを呼び出す関数を利用し、さらにこの外部アプリ呼び出し関数にパラメータを与えて外部アプリ を起動している場合などは、SQL インジェクションの時と同様にクエリパラメータ(?param=XXXXX)の XXXXX の部分にコマンドを書くと、攻撃者がリクエスト URL を使ってサーバ側のプログラムを実行できてしまう可能性がある。 (対策) パラメータをチェックするか、これらの関数の呼び出しをできるだけ避ける、または、しない。
  3. パス名パラメータの未チェック/ディレクトリ・トラバーサル (問題) リクエスト URL にファイル名を直接渡している。この場合、攻撃者が意図しないファイル名を指定してブラウザに表示できてしまう可能性がある。 (対策) テンプレートファイルなど、直接渡すファイル名をチェックするか、そもそもこのような作りにしない。また、スクリプトからファイルを読み込むのだから読み込むファイルはウェブサーバのルート(たとえば、/home/yourname/public_html など) 配下に置かないようにして、または、アクセス権をきちんと設定して、テンプレートファイルなどがブラウザから見えないようにする。ファイル名にディレクトリ名まで含めないようにする。
  4. セッション・ハイジャック (問題) 1つのセッションでセッションIDが固定化している場合などは、攻撃者がネットワークを盗聴し、セッションIDを知ってしまった場合には、そのセッションIDを使ってなりすましができてしまう可能性がある。 (対策) リクエスト URL にセッション ID を含めない。なぜなら HTTP_REFERRER で取れてしまうからである。ということはなるべく cookie を使うか、セッション ID が推測困難なようにするしかないが、そうは言ってもケータイからのアクセスの場合は cookie が使えないので、やはり同一セッションでセッション ID がずっと同じままサーバにアクセスされてくるような作りにできるだけしないようにする。アイディアとしては、まずはケータイからのアクセスの場合はすべて https 経由(SSL)にする。これだとパフォーマンスとパケット代が犠牲になるが仕方がない。https ではリクエスト URL も暗号化されるので、これ以上のセキュリティはない。cookie の場合は有効期限に注意する。 他には、セッション ID+シーケンシャル番号+サーバ側のシークレット(あなたが決めたパスワード。1文字でもいい)の 3つの文字列を連結して、そのハッシュ値を取り、セッション ID=セッション ID+シーケンシャル番号+ハッシュ値(またはチェックサム)としてはどうだろう?同一セッションは基本的に同じブラウザからアクセスされるのだから、ハッシュ値を取る際に HTTP_USERAGENT を含めるといいかもしれない。HTTP_USERAGENT は、ネットワークを盗聴している攻撃者にもわかってしまう情報ではあるが、アルゴリズムをあなたしか知りえないものにすれば、セキュリティは高まると思う。
  5. クロスサイト・スクリプティング (問題) ブログのコメント欄、掲示板の投稿など、テキスト情報をサーバ側に submit できるサイトの場合、攻撃者は でスクリプトを submit し、HTTP レスポンスでブラウザに返された HTML の中でスクリプトを実行できてしまえたりするかもしれない。 (対策) 基本は、ユーザーが情報を書き込むときに使える HTML タグを制限すること。また、リンクについても http と https しか許可しないようにするとか、細かい話だとスタイルシートを外部サイトから取り込めるようにしないとか注意が必要。
  6. クロスサイト・リクエスト・フォージェリ (CSRF) (問題) オンラインショッピングなどで、「入力画面 → 確認画面 → 登録処理」の画面遷移の場合、フィッシングのなどの目的で最初または途中の画面をハックされると、意図しない処理が実行されてしまうかもしれない。 (対策) 画面遷移時にセッション ID とそのハッシュ値(セッション ID のほかにもいろいろな情報を組み合わせたハッシュ値を生成する)を hidden パラメータに埋め込んでおいてサーバ側でチェックするとか、HTTP_REFERRER をチェックする、そして https であっても念のため最終処理を実行する場面でユーザーに取引用の暗証番号を入力させる、といったことが考えられる。
  7. HTTP ヘッダ・インジェクション (問題) 攻撃者が HTTP ヘッダの書き換えに成功すると、サーバ側のキャッシュを書き換えて攻撃者が用意したキャッシュを置き、ユーザーをそのキャッシュページに誘導することができる。 (対策) HTTP ヘッダに改行を許さないようにする。ヘッダは通常、改行で区切られているため。
  8. メールの第三者中継 (問題) サイトが問い合わせフォームなどで送信先が指定できる場合は、サイトが迷惑メール送信の踏み台にされる可能性がある。 (対策) 送信先のメールアドレスを任意に指定できないようにする。ユーザーとのやり取りはユーザー登録画面で登録されたメールアドレスとやり取りするようにする。
Update: 2006/11/06 Orignal: 2006/11/02
トラックバック URL: https://perltips.twinkle.cc/trackback/136