セキュリティ

Webアプリケーション構築でのセキュリティ実装についてまとめます。

No 脆弱性 被害 対策
1 SQL インジェクション データベース内容漏洩。 "SELECT * FROM USER WHERE ID='" + user_id + "'"
※user_id は、フォームから入力された文字列とする。
のようなコードを書かないで下さい。

"SELECT * FROM USER WHERE ID=?"
のように動的SQL(バインド変数の使用)でコーディングして下さい。

過去、ニュースになったような個人情報漏洩事件は、これが主です。
2 OS コマンド・インジェクション サーバーシステム内容漏洩。 PerlやPHPなら注意が必要ですが、普通、JAVAでは起きません。
3 ディレクトリ・トラバーサル サーバーシステム内容漏洩。 フォーム入力値等をそのままファイルパス名としてファイルアクセスするような実装にしないで下さい。
4 セッション・ハイジャック サイト利用者の個人情報漏洩や金銭的被害等。 そのままのコーディングでは防げません。ログインを伴うページではSSLを併用して下さい。
また、ログインページのような認証ページのinputMainで1度セッションを再作成して下さい(Paraseleneは初回アクセスからセッションを自動作成しているため、ログイン以前からセッションが発生しています。そのためSSL開始前にセッションを奪われる可能性があります)。
例えば以下のようにして、攻撃を防ぐ事ができます。

public Forward inputMain( RequestParameter req, Forward fw ) throws PageException {
  javax.servlet.http.HttpSession session = req.makeNewSession();
  //以下、ログイン処理
  return fw;
}


攻撃者によるセッションIDの予測はJava EEでは困難です。その点は考慮する必要はないでしょう。

また、Paraseleneはセッションが奪われた可能性があると判断した場合(同一セッションを使用するアクセスが複数のクライアントから発生していると判断した場合)、そのセッションは破棄され新しいセッションが生成されます。
5 クロスサイト・スクリプティング フィッシング詐欺等。 Textクラスがエスケープ処理を行うため、通常、Paraseleneでは考慮する必要はありません。
ただし、以下の場合は注意が必要です。
  • PlainTextクラスを使っている場合。
  • フォーム入力値等を、<A>タグのhrefに埋め込むような処理がある場合。
6 クロスサイト・リクエスト・フォージェリ サイト利用者の金銭的被害等。 下記2点の実装により、この攻撃は不可能となります。
  • PageクラスのisCheckRepeatSameRequest()でtrueを返す。
    これがtrueを返すページを遷移先に持つURLにはリクエストIDが必須となります。
    この時、リクエストIDがURLに指定されていない場合、または存在しないリクエストIDが指定されると403エラーを返します。
  • DummyPageのinputで直接呼び出せないページはエラーをForwardする。
    1番は、「遷移元ページがある場合のURL仕様」です。遷移元ページが無いURLの場合、リクエストIDは必須ではありません。
    このため、遷移元ページが指定されていない時に実行されるDummyPageのinputで弾いて下さい。
    例えば、「ログインページ以外はログインページへForwardする」等の処理になります。
    ログイン後に利用可能なページと一般公開ページが多数混在していて切り分けが難しいサイトの場合は以下のようにするとよいでしょう。
    • モックアップを作成する際、ログイン後に利用できるページは特定サブディレクトリの配下になるよう配置する。
      例えば、/admin/配下に置きます。
    • スケルトンを作成した際、例えばパッケージ名を"site"とした場合は、/admin/index.htmlのクラス名は、site.logic.admin.IndexHtmlとなります。
    • DummyPageのinputを以下のようにします。
      public Forward input( RequestParameter req, Forward fw ) throws PageException {
        Page page = PageLoader.getPageFactory().getPage( fw.getPageID() );
        if ( page.getClass().getName().indexOf( "site.logic.admin." ) == 0 ) {
          fw = new Forward( 403 );
      // またはログインページへForward
        }
        return fw;
      }
7 HTTP ヘッダ・インジェクション サイト利用者の個人情報漏洩や金銭的被害等。 普通、JAVAでは起きません。
8 DoS攻撃 サーバーダウン。 1度アウトオブメモリー(メモリ不足によるヒープ割り当て不可)が発生すると、動作が不安定になります。リソースの余力を残すようにして、リクエスト処理を行うようにして下さい。
  • Paraseleneは、リクエスト発生時にメモリ使用量が使用可能メモリの93.75%を使い切っていると503エラーを返し、メインルーチン(ページインスタンス)を呼び出しません。
    また、使用可能メモリの87.5%を使い切っていると、Java VMにガベージコレクトを要求します。
  • データベースを使用している場合は、データベース接続数が不足する可能性があります。
    Gate#getRequestMaxCountで、一定数以上のアクセスは弾いて下さい。
  • tomcatの場合、POSTできるサイズは上限値(デフォルト2M)が設けられています。ただし、ファイルアップロード(enctype="multipart/form-data")にはこの制限値は効きません。
    巨大なPOSTを防ぐために、Page#getUploadMaxBytesで制限をかけて下さい。
tomcatの場合、examples等のコンテキストも同時にインストールされている可能性があります。こういった不要なものは削除して下さい。リソースの余裕ができます。
また、メモリ割り当て可能最大サイズも増やすと良いでしょう。一般的に、マシンの物理メモリの半分が割り当て目安と言われています。