SlideShare une entreprise Scribd logo
1  sur  84
Télécharger pour lire hors ligne
Javaセキュアコーディングセミナー東京
第3回
入出力(File, Stream)と例外時の動作


2012年11月11日(日)
JPCERTコーディネーションセンター
脆弱性解析チーム
戸田 洋三
久保 正樹




                      1
本資料について
本セミナーに使用するテキストの著作権はJPCERT/CCに帰属します。
事前の承諾を受けた場合を除いて、本資料に含有される内容(一部か全部か
を問わない)を複製・公開・送信・頒布・譲渡・貸与・使用許諾・転載・再
利用できません。



本セミナーに関するお問い合わせ
JPCERTコーディネーションセンター
セキュアコーディング担当
E-mail:secure-coding@jpcert.or.jp
TEL:03-3518-4600




                                2
本セミナーについて
‣ 4回連続セミナーです
   ‣ 第1回 9月9日(日)
     ‣ オブジェクトの生成と消滅におけるセキュリティ
   ‣ 第2回 10月14日(日)
     ‣ 数値データの取扱いと入力値検査
   ‣ 第3回 11月11日(日)
     ‣ 入出力(ファイル,ストリーム)と例外時の動作
   ‣ 第4回 12月16日
     ‣ メソッドのセキュリティ

‣ 開発環境持参




                3
今日の時間割

‣ 講義 (13:30--15:00)
  ‣ 入出力
  ‣ 例外時の動作
‣ ハンズオン (15:10--16:30)




              4
入出力




      5
‣ Java の入出力ストリーム
‣ ファイルシステムの扱い
‣ 共有ディレクトリの危険性




            6
I/O streams in Java
 Java 言語では, データの入出力を「ストリーム」と
 いう形で抽象化している.
   - ディスクの読み書き
   - ネットワーク通信
   - 他のプログラムとのやりとりなど




from Basic I/O, The Java Tutorials

                                     7
I/O streams in Java
•バイトデータのストリーム
  •InputStream や OutputStream など
•文字データのストリーム
  •Reader や Writer など
•Filter{In,Out}putStream (他のストリームに機能を追加する)
 •Buffered ストリーム(バッファリング機能)
 •Data ストリーム(プリミティブ型やString型の値の入出力に使われる)
 •Object ストリーム(シリアライズの際, オブジェクトの入出力に使われる)




                       8
I/O streams in Java
•バイトデータのストリーム
  •InputStream や OutputStream など
        •InputStream
           •AudioInputStream

•文字データのストリーム
           •ByteArrayInputStream
           •FileInputStream
               •InflaterInputStream

  •Reader や Writer など
                  •GZIPInputStream
                  •ZipInputStream


•Filter{In,Out}putStream (他のストリームに機能を追加する)
                       •JarInputStream           •Reader
           •FilterInputStream                       •BufferedReader
               •BufferedInputStream                     •LineNumberReader
 •Buffered ストリーム(バッファリング機能)
             •DataInputStream     •CharArrayReader
             •PushbackInputStream •FilterReader
 •Data ストリーム(プリミティブ型やString型の値の入出力に使われる)
             •CheckedInputStream       •PushbackReader
             •CipherInputStream   •InputStreamReader
 •Object ストリーム(シリアライズの際, オブジェクトの入出力に使われる)
             •DeflaterInputStream       •FileReader
               •DigestInputStream                   •PipedInputStream
               •ProgressMonitorInputStream          •StringReader
           •ObjectInputStream                    •AudioFileReader
           •PipedInputStream                     •ImageReader
           •SequenceInputStream                  •MidiFileReader
        •FileCacheImageInputStream               •SoundbankReader
        •FileImageInputStream
        •MemoryCacheImageInputStream


                                             9
サンプルコード: xanadu.txt を outagain.txt にバイト単位でコピー

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyBytes {
  public static void main(String[] args) throws IOException {
    FileInputStream in = null;
    FileOutputStream out = null;
    try {
      in = new FileInputStream(“xanadu.txt”);
      out = new FileOutputStream(“outagain.txt”);
      int c;
      while ((c = in.read()) != -1){
        out.write(c);
      }
    } finally {
        if (in != null){
          in.close();
        }
        if (out != null){
          out.close();
        }
    }
  }
}
                                   10
FIO08-J: 文字やバイトを読み取るメソッドの返り値は int で受ける

byte[] c = new byte[1];
while ((c[0] = (byte)in.read()) != -1){
    out.write(c);
}




 read() の返り値を byte 型にキャストする
とどうなる?




                          11
FIO08-J: 文字やバイトを読み取るメソッドの返り値は int で受ける


int read() throws IOException

       入力ストリームからデータの次のバイトを読み込む.
       値のバイトは 0 から 255 の範囲の int 型データ.
       ストリームの終わりに達した場合は -1 が返される.

•read()      ... 0xff を読み込んだら返り値は0x000000ff
•(byte)read() ... 0xff (下位1バイト)に切り捨てられる
•... != -1   ... 比較演算で int 型の 0xffffffff に格上げされる
 byte 型は符号付き整数型なので, 0xff は -1(decimal) として扱わ
れ, 0xffffffff に格上げされ, end-of-stream と区別できなくなる
   DoS 攻撃に悪用されるかも!

                        12
FIO04-J: 不要になったリソースは解放する

•データ入出力に使われるストリームは限りある
 リソース
•不適切なリソース管理はリソース枯渇攻撃に悪
 用される危険がある
•不要になったら適切にクローズしましょう




              13
サンプルコード: データベースとのやりとり

public void getResults(String sqlQuery) {
  try {
    Connection conn = getConnection();
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery(sqlQuery);
    processResults(rs);
    stmt.close();
    conn.close();
  } catch (SQLException e) { /* ハンドラに処理を移す */ }
}




              executeQuery()やprocessResults()で例外が
              発生するとデータベース接続がクローズ
              されないじゃないか!




                         14
サンプルコード: データベースとのやりとり

public void getResults(String sqlQuery) {
  Statement stmt = null;
  ResultSet rs = null;
  Connection conn = getConnection();
  try {
    stmt = conn.createStatement();
    rs = stmt.executeQuery(sqlQuery);
    processResults(rs);
  } catch(SQLException e) {
    // ハンドラに処理を移す
    } finally {
        if (rs != null) { rs.close(); }
        if (stmt != null) { stmt.close(); }
        if (conn !=null) { conn.close(); }
    }
}
                             close() メソッドで SQLException が発
                            生したら finally 節は途中で終了しちゃ
                            うよ!

                            15
サンプルコード: データベースとのやりとり
public void getResults(String sqlQuery) {
  Statement stmt = null;                  try-catch-finally を駆使して
  ResultSet rs = null;
  Connection conn = getConnection();      全ての close() メソッドを
  try {                                   ガードすればなんとか...
    stmt = conn.createStatement();
    rs = stmt.executeQuery(sqlQuery);
    processResults(rs);
  } catch (SQLException e) { ... ハンドラに処理を移す ...
  } finally {
    try {
      if (rs != null) {rs.close();}
    } catch (SQLException e) { ... ハンドラに処理を移す ...
    } finally {
      try {
        if (stmt != null) {stmt.close();}
      } catch (SQLException e) { ... ハンドラに処理を移す ...
        } finally {
          try {
            if (conn != null) {conn.close();}
          } catch (SQLException e) { ... ハンドラに処理を移す ...
}}}}}


                               16
サンプルコード: データベースとのやりとり
public void getResults(String sqlQuery) {
  try (Connection conn = getConnection();
       Statement stmt = conn.createStatement();
       ResultSet rs = stmt.executeQuery(sqlQuery)) {
    processResults(rs);
  } catch (SQLException e) {
    // ハンドラに処理を移す
    }
}




                Java7 の try-with-resources を使
                うと簡潔なコードになるよ!


                           17
ストリーム入出力に関連するコーディングルール
‣ FIO04-J. 不要になったらリソースを解放する
‣ FIO05-J. wrap() や duplicate() メソッドで作成したバッファを信頼できないコード
 にアクセスさせない
‣ FIO06-J. ひとつの InputStream に対して複数のバッファ付きラッパーを作成しない
‣ FIO07-J. 外部プロセスに IO バッファをブロックさせない
‣ FIO08-J. 文字やバイトを読み取るメソッドの返り値は int で受ける
‣ FIO09-J. 0 から 255 の範囲に収まらない整数値を出力するときには write() メソッ
 ドを信用しない
‣ FIO10-J. read() を使って配列にデータを読み込むときには配列への読み込みが意
 図した通りに行われたことを確認する
‣ FIO11-J. バイナリデータを文字データとして読み込もうとしない
‣ FIO12-J. リトルエンディアン形式のデータを読み書きするメソッドを用意する
‣ FIO13-J. センシティブな情報を信頼境界の外に記録しない
‣ FIO14-J. プログラムの終了時には適切なクリーンアップを行う



                           18
‣ Java の入出力ストリーム
‣ ファイルシステムの扱い
‣ 共有ディレクトリの危険性




           19
ディレクトリトラバーサル

 ディレクトリトラバーサル攻撃
 アクセス可能であることを意図していない
 ファイルへのアクセスを行う攻撃.


‣ ファイル関連の脆弱性で典型的なもの
‣ 前回, 東京セミナpart2で, ディレクトリトラバーサルの問題を
  作り込んだコード例を紹介
‣


            https://www.owasp.org/index.php/Path_Traversal
            http://ja.wikipedia.org/wiki/ディレクトリトラバーサル

                        20
サンプルプログラム: ディレクトリトラバーサル
class filecat {

    static private String BASEDIR="/home/yozo/tmp/";    対象とするディレクトリ
    static public void cat(String s) throws IOException {
        BufferedReader bf =
            new BufferedReader(new FileReader(BASEDIR + s));
        String line;
        while (null != (line = bf.readLine())){
          System.out.println(line);
        }                                                 単純な文字列連結だけ
    }
                                                         行っている
    public static void main(String[] args) throws IOException {
      String filename = args[0];
      cat(filename);
    }
}

                                      ファイル名を期待



前回part2で紹介

                                     21
サンプルプログラム: ディレクトリトラバーサル
                                             想定通りの動作
$ java filecat choi
hoihoi
$ java filecat ../Documents/WORK/SecureCoding/20121014.Tokyo_part2/
filecat.java
import java.io.BufferedReader;
import java.io.FileReader;                     想定外の入力!!
import java.io.FileNotFoundException;
import java.io.IOException;
class filecat {

  static private String BASEDIR="/Users/yozo/tmp/";

(...... 以下省略 ......)




前回part2で紹介

                                   22
サンプルプログラム修正例
class filecat1 {

    static private String BASEDIR="/home/yozo/tmp/";

    static public void cat(String s) throws IOException {
        File f = new File(BASEDIR + s);
        String fs = f.getCanonicalFile().toString();
        if (!fs.startsWith(BASEDIR)) {
              throw (new IllegalArgumentException(fs));
        }
        BufferedReader bf =
            new BufferedReader(new FileReader(f));
        String line;
        while (null != (line = bf.readLine())){
          System.out.println(line);
        }
    }

    public static void main(String[] args) throws IOException {
      String filename = args[0];
      cat(filename);
    }
}

                   対策: canonicalパスで想定通りのディレ
                   クトリを指していることを確認する
                                     23
File I/O

 「最終的に、どんな OS でも実行できるコード
 になった。JVM (および、Java 環境)が提供する
 抽象化を利用して、OS とファイルシステムの差
 異を隠   したおかげだ。」

              Java The Good Parts, 6章 Java 仮想マシン




              24
File I/O
   Java アプリ            ファイルシステム


   Java 仮想マシン

オペレーティングシステム


                        ファイルシステム

•JVM は OS 層への統一的なインタ
フェースを提供する.
•OS 層はファイルシステムへの統一
的なインタフェースを提供する.
                 25
ファイルシステムにもいろいろ
ファイルシステムの例
•POSIX 系ファイルシステム
 •アクセスパーミッションによるアクセス制御

•NFSv4, NTFS
 •Access Control List によるアクセス制御

•FAT (MS-DOS)
 •file attribute によるアクセス制御



                         26
File I/O
ファイルシステムにはファイルと
ディレクトリが収められている.
それらに対するアクセス制御の機
能が実装されている.



ファイルシステムにはその実装形態
によってそれぞれ固有の特徴があ
り, それらを理解して適切に扱う必
要がある.



              file separator, ファイル名の最大長, ディレク
             トリ階層の深さ, ファイル名に使える文字種, ...



                      27
File I/O
ポータビリティに関する Java のスローガン
“Write once, run anywhere”
     JRE(Java実行環境)は OS に依らない API を
     Java アプリに提供してくれる

      しかし


    セキュアなファイル操作を行うためには,
    ファイルシステムの詳細を理解しておく必
    要がある

                  28
File I/O
  Java アプリ              ファイルシステム


   Java 仮想マシン

オペレーティングシステム


                         ファイルシステム




ファイル操作は JVM, OS, ファイル
システムを通じて行われている!


                 29
File I/O
POSIX
$ ls -al showAttributesPosix.java
-rw-r--r-- 1 yozo staff 764 Nov 9 14:51 showAttributesPosix.java
$



NTFS
C:>dir /q showAttributesACL.java
......
2012/11/09 15:07     611 earlgreyyozo    showAttributesACL.java
......
C:>icacls showAttributesACL.java
showAttributesACL.java NT AUTHORITYSYSTEM:(I)(F)
                        BUILTINAdministrators:(I)(F)
                        earlgreyyozo:(I)(F)
......
C:>




                               30
File I/O
POSIX
class showAttributesPosix {
  public static void main(String[] args)
        throws IOException {
    if (args.length <= 0){ return; }
    Path p = FileSystems.getDefault().getPath(args[0]);
    PosixFileAttributes attrs =
        Files.getFileAttributeView(p, PosixFileAttributeView.class)
          .readAttributes();
    System.out.format(“%s %s%n”,
            attris.owner().getName(),
            PosixFilePermissions.toString(attrs.permissions()));
  }
}




$ java showAttributesPosix showAttributesPosix.java
yozo -rw-r--r--
$


                                 31
File I/O
ACL
class showAttributesACL {
  public static void main(String[] args) throws IOException {
    if (args.length <= 0){ return; }
    Path p = FileSystems.getDefault().getPath(args[0]);
    List<AclEntry> acls =
        Files.getFileAttributeView(p, AclFileAttributeView.class)
          .getAcl();
    for(AclEntry acl : acls) {
      System.out.println(acl.toString());
    }
  }
}

C:> java showAttributesACL showAttributesACL.java
NT AUTHORITYSYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/
WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/
DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
BUILTINAdministrators:READ_DATA/WRITE_DATA/APPEND_DATA/
READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/
WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
earlgreyyozo:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/
WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/
DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW

C:>
                                    32
File I/O

 OS とファイルシステムの差異を隠   したって
 言っても、隠しきれないものもある。
 ポータビリティを確保するのは難しい。




            33
‣ Java の入出力ストリーム
‣ ファイルシステムの扱い
‣ 共有ディレクトリの危険性




           34
共有ディレクトリの危険性

[共有ディレクトリ]
マルチユーザシステムにおいて, 複数のユーザに対してアクセスが許されて
いるディレクトリのことを「共有ディレクトリ」と呼ぶ.



POSIX 系における “/tmp” や Windows における
“C:WindowsTemp” など.

共有ディレクトリは危険!
他のユーザがファイルを改ざん/削除したり, 他の
ファイルへのリンクを作るかもしれない.

                  35
Symlink 攻撃
通常の動作


                                 program
                                  program
                   shared         プログラム



 プログラム

         削除




              他のプログラムがファイルにアク
              セスしなければ問題は発生しない.




                            36
Symlink 攻撃
symlink attack(1)                         攻撃者はターゲットファイルを
                                          削除する権限を持っていない
                    ターゲット

                            shared

    プログラム
                                               攻撃者




                            攻撃者はプログラムが操作するファイル
                            をあらかじめ削除し, ターゲットファイル
                            へのシンボリックリンクを作る.



                                     37
Symlink 攻撃
symlink attack(2)



                         ターゲット

                                 shared

    プログラム
                                                 攻撃者
                    削除




                                      プログラムは, シンボリックリン
                                      クに置き換えられているとは知ら
                                      ずに問題のファイルを削除する...


                                          38
Symlink 攻撃
symlink attack(3)



                         ターゲット

                                 shared

    プログラム
                                                      攻撃者
                    削除




                                      ... そして target ファイルは削除
                                      されてしまった!




                                          39
セキュアディレクトリ

[セキュアディレクトリ]
自分(とシステム管理者)のみにアクセスを制限し
ているディレクトリ
 他のユーザがファイルを改ざん
 しないことが保証される



         セキュアディレクトリ
                       secure

    他のユーザはこれらのファイ
      ルを改変できない.


                  40
Summary
 ‣ JRE(Java 実行環境)はOS層を抽象化してくれる
 ‣ しかし以下のような処理が必要な場合は OS
 やファイルシステムの基本的な特徴を理解し
 ておくべき.
  ‣ ファイル操作(作成, 変更, 削除など)
  ‣ ファイルのアクセス制御に関する操作




               41
ファイル入出力に関連するコーディングルール
‣ FIO00-J. 共有ディレクトリにあるファイルを操作しない
‣ FIO01-J. 適切なパーミッションを設定してファイルを作成する
‣ FIO02-J. ファイル関連エラーを検知し、処理する
‣ FIO03-J. 一時ファイルはプログラムの終了前に削除する
‣




                     42
例外時の動作




         43
例外とは

‣ exception = exceptional event


‣ 定義
  ‣ 例外(exception)とは、プログラムの実行中に発生し、プロ
    グラム実行の正常な流れを分断するイベントのこと。
    ‣ 例:ゼロ除算、配列の境界外アクセス




                          44
例外とは



 throws する       exception
                  object




メソッド                         JVM

     エラーが起こった!




                     45
例外とは

  ‣ コールスタック(call stack)



例外オブジェクトが        エラーが発生したメソッド
  飛んできた!
だれがハンドルする                          メソッド呼出し
  んだっけ?        例外ハンドラを持たないメソッド

                                   メソッド呼出し
 JVM            例外ハンドラを持つメソッド

                                   メソッド呼出し

                          main()

                      call stack

                            46
例外とは

  ‣ コールスタッフを調べ、例外ハンドラをみつける


 例外をスローする
                  エラーが発生したメソッド

                                   適切なハンドラを探す

例外をフォワードす        例外ハンドラを持たないメソッド
    る

   catchされた                        適切なハンドラを探す

                  例外ハンドラを持つメソッド
     exception
       object


君が処理してね               main()


    JVM               call stack

                         47
例外とは

‣ 例外 = オブジェクト
  ‣ エラー発生時のプログラムの状態を、コールスタックの上位
    に伝える
  ‣ エラーを種類によってグループ化/差異化
  ‣ 拡張できる

‣ 通常の処理を行うコードと、エラー処理のコードの分離




               48
Object
                                                 例外のクラス階層

                         Throwable
                                                     84種類のサブクラス
                                                         を持つ
Error                             Exception

    IOError
                                         IOException

   VirtualMachineError                        FileNotFoundException

         StackOverflowError            RuntimeException

         OutOfMemoryError                     NullPointerException

                                              ArithmeticException

                                              IndexOutOfBoundsException
チェック例外        未チェック例外


                                 49
3つの例外

‣ 未チェック例外 (unchecked exception)
  ‣ Error
  ‣ RuntimeException
     ‣ コンパイラはチェックしてくれない
    ‣ throws 宣言しなくてもよい
    ‣ アプリは例外から戻れないという想定

      ‣ 「実行時例外」という訳語

‣ チェック例外 (checked exception)
  ‣ ハンドラを必ず実装
  ‣ コンパイラがチェック


                       50
未チェック例外

‣ Error と RuntimeException
   ‣ コンパイラによるチェックは行われない
   ‣ メソッドで必ずしもthrowしなくてもよい
   ‣ ランタイム(Javaの実行環境)が出す例外なのでプログラムで
     はどうしようもない、という発想




                 51
未チェック例外

 未チェック例外クラスであるエラークラス(Errorとそのサブクラ
 ス)は、プログラム中の様々な場所で発生する可能性があり、そう
 いったものの回復は難しく、あるいは不可能であるため、コンパイ
 ル時にはチェックされない

 ......

 実行時例外クラス(RuntimeExceptionとそのサブクラス)は、こう
 いった例外の宣言を強制してもJavaプログラムの正当性を確立する
 ための著しい助けにはならないだろう、というプログラミング言語
 の設計者達による判断によって、コンパイル時にはチェックされな
 い。


               Java 言語仕様
                11.2.4 コンパイル時の例外のチェックされない理由
                11.2.5 実行時例外がチェックされない理由



                   52
チェック例外

‣ ハンドラを必ず実装しないとだめ
‣ コンパイラがチェックする
‣




               53
try-catch-finallyの制御構造


 try {
   // 何らかの処理
     // X, Y, Z を throw
  // するかもしれない
                               例外 X が               例外 Y が                例外 Z が
 }                                                 スローされた                スローされた
                              スローされた




 例外はスローされなかった             catch (X e) {         catch (Y e) {        catch (Z e) {
                            // handle e of X      // handle e of Y     // handle e of Z
                          }                     }                    }




 finally {
   // 必ず実行される
 }




                                           54
例外処理のアンチパターンとセキュリティ

‣ 例外をキャッチしない (CWE-248)
‣ チェック例外を無視/抑制する (ERR00-J, CWE-390,
  CWE-391)
‣ プログラム制御に例外を使用する (EffectiveJava 57)
‣ エラーメッセージを通じたセンシティブな情報を漏洩する
  (CWE-209)
‣ NullPointerExceptionをキャッチする (ERR08-J, CWE-395)
‣ 例外スロー時にリソースのクリーンアップを適切に行わない
  (CWE-460)
‣ スローする例外が一般的すぎる (CWE-397)
‣ プログラムの異常状態や例外条件を適切にチェックしない
  (CWE-754)



                       55
アンチパターン1
例外をキャッチしない




             56
例外をキャッチしない

‣ あとでオブジェクトを使うときにエラーが発生する
‣ 現実にはこのアプローチをとるコードが非常に多い(らしい)

protected void doPost (
HttpServletRequest req, HttpServletResponse res) throws IOException {
   String ip = req.getRemoteAddr();
   InetAddress addr = InetAddress.getByName(ip);
   ...
   out.println("hello " + addr.getHostName());
}




‣ DNS lookupに失敗するとServletは例外をスローするにもかか
  わらず、キャッチしていない
‣ アプリがクラッシュ、DoS攻撃に悪用される



                                  57
アンチパターン2
チェック例外を無視/抑制する




           58
チェック例外を無視/抑制する

public String readFile(String filename) {
                                                   例外が発生するのは
   String retString = null;                           どこ?
   try {
      // File および FileReader オブジェクトを初期化
       File file = new File(filename);
       FileReader fr = new FileReader(file);

       // 文字バッファを初期化
       long fLen = file.length();
       char[] cBuf = new char[(int) fLen];

       // ファイルからデータを読込む
       int iRead = fr.read(cBuf, 0, (int) fLen);

       // クローズ処理
       fr.close();

       retString = new String(cBuf);
    } catch (Exception ex) { }
    return retString;
}

                                 59
public String readFile(String filename) throws FileNotFoundException, IOException, Exception {
   String retString = null;
   try {
      // initialize File and FileReader objects
      File file = new File(filename);
      FileReader fr = new FileReader(file);

       // initialize character buffer
       long fLen = file.length();
       char [] cBuf = new char[(int) fLen];
                                                           各例外に対するハンドラを実装
       // read data from file
       int iRead = fr.read(cBuf, 0, (int) fLen);           (この場合、例外に関する情報をユーザに
                                                           出力してから、例外を再スローしている)
       // close file
       fr.close();

       retString = new String(cBuf);
    } catch (FileNotFoundException ex) {
       System.err.println ("Error: FileNotFoundException opening the input file: " + filename );
       System.err.println ("" + ex.getMessage() );
       throw new FileNotFoundException(ex.getMessage());
    } catch (IOException ex) {
       System.err.println("Error: IOException reading the input file.n" + ex.getMessage() );
       throw new IOException(ex);
    } catch (Exception ex) {
       System.err.println("Error: Exception reading the input file.n" + ex.getMessage() );
       throw new Exception(ex);
    }
    return retString;
}



                                               60
FileNotFoundException

‣ FileNotFoundExceptionはチェック例外
‣ 指定されたファイルが開けない場合、APIは、呼出し元がなん
  らかのアクションをとることを期待する
   ‣ 例:ユーザに別のファイルを指定させる

‣ 前述のコードでは、呼出し元に処理を委譲するため、再度例外
  をスローしていた

 java.lang.Object

      java.lang.Throwable

           java.lang.Exception

                java.io.IOException


                      java.io.FileNotFoundException

                                  61
アンチパターン3
制御フローに例外を使う




              62
例外の誤用

     public class Antipattern {
    public static void main(String[] args) {
      try {
         int i = 0;
         while (true) {
           System.out.println(args[i++]);
         }
      } catch (ArrayIndexOutOfBoundsException e) {
      }
    }
}




                             63
通常の制御フローに例外を使わない

public class Antipattern {
  public static void main(String[] args) {
    int i = 0;
    for (i = 0; i < args.length(); i++) {
      System.out.println(args[i]);
    }
  }
}


‣ 例外はコードの最適化に役立たない
  ‣ JVMによる最適化を排除する可能性がある




                           64
アンチパターン4
例外を通じてセンシティブな情報を漏洩する




           65
例外に含まれるセンシティブな情報

‣ 実行スタックのスナップショット
‣ 例外メッセージ
‣ 例外の種類




  例外オブジェクトに含まれるこれらの情報は、
  攻撃の手がかりを与えてしまう




               66
センシティブな情報を含む例外
例外名                                                漏洩する情報/脅威

java.io.FileNotFoundException                      ファイルシステムの構成、ユーザ名の列挙

java.sql.SQLException                              データベースの構成、ユーザ名の列挙

                                                   信頼できないクライアントがサーバのポートを選択
java.net.BindException
                                                   できる場合、開いているポートを列挙

java.util.ConcurrentModificationException          スレッドセーフでないコードに関する情報

javax.naming.InsufficientResourcesException        不十分なサーバーリソース (DoSにつながる可能性)

java.util.MissingResourceException                 リソースの列挙

java.util.jar.JarException                         ファイルシステムの構成

java.security.acl.NotOwnerException                所有者の列挙

java.lang.OutOfMemoryError                         DoS

java.lang.StackOverflowError                       DoS


                                              67
問題のあるコード

class FileOpen {
  public static void main(String[] args)
            throws FileNotFoundException, IOException {
    FileReader fr = null;
    try {
      fr = new FileReader("fff.txt");
    } finally {
      if (fr != null){
                                                  fff.txtが見つからないと、
        fr.close();                              FileNotFoundException
      }
    }                                                   がスローされる
  }
}


  Exception in thread "main" java.io.FileNotFoundException: fff.txt
  (No such file or directory)
      at java.io.FileInputStream.open(Native Method)
      at java.io.FileInputStream.<init>(FileInputStream.java:120)
      at java.io.FileInputStream.<init>(FileInputStream.java:79)
      at java.io.FileReader.<init>(FileReader.java:41)
      at FileOpen0.main(FileOpen0.java:9)



                                   68
問題のあるコード

class FileOpen {
  public static void main(String[] args)
            throws FileNotFoundException, IOException {
    FileReader fr = null;
    try {
      fr = new FileReader(args[0]);
    } catch (FileNotFoundException ex) {
      String logMessage = “Unable to find file:” + arg[1];
      Logger.getLogger(FileOpen.class.getName()).log(Level.SEVERE, logMessage, ex);
    } finally {
      if (fr != null){
        fr.close();                         指定されたファイルが見つからない
      }                                    と、エラーメッセージが作られ、ログ
    }
  }                                               ファイルに出力される
}


  ‣ ファイルシステムに「あるファイル」が存在するかどうかがロ
    グを見れば分かってしまう



                                       69
センシティブな情報をフィルターする

 import java.io.FileReader;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 class FileOpen {
   public static void main(String[] args)
             throws FileNotFoundException, IOException {
     FileReader fr = null;
     try {
         fr = new FileReader("fff.txt");
     } catch (FileNotFoundException f){
         throw new FileNotFoundException("not found");
     } finally {
         if (fr != null){
               fr.close();                        ファイル名を例外から削る
         }
     }
   }
 }




Exception in thread "main" java.io.FileNotFoundException: not found
! at FileOpen.main(FileOpen.java:11)


                               70
センシティブな情報をフィルターする

 import java.io.FileReader;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 class FileOpen {
   public static void main(String[] args)
             throws FileNotFoundException, IOException {
     FileReader fr = null;
     try {
         fr = new FileReader("fff.txt");
     } catch (FileNotFoundException f){
         throw new IOException("something wrong!");
     } finally {
         if (fr != null){
               fr.close();         IOExceptionをスローする
         }
     }
   }
 }




Exception in thread "main" java.io.IOException: something wrong!
! at FileOpen.main(FileOpen.java:11)


                                 71
アンチパターン5
NullPointerException()をキャッチする




                72
java.lang.NullPointerException

‣ RuntimeExceptionを継承している
   ‣ つまり未チェック例外
‣ オブジェクトが要求されるコードでnullが使われるとスローさ
  れる:
   ‣ nullオブジェクトのインスタンスメソッド呼出し
   ‣ nullオブジェクトのフィールドのアクセス/変更
   ‣ 配列だと思ってnullのlength取得する
   ‣ 配列だと思ってnullのスロットへアクセス/変更
   ‣ Throwableの値だと思ってnullをスローする




                    73
なぜNullPointerExceptionをキャッチしてはいけないのか

‣ 理由1. NullPointerExceptionをキャッチする方が、値がnullかどうか
  チェックするコードを追加するより、オーバーヘッドがはるかに大きい

‣ 理由2. tryブロック中の複数の式がNullPointerExceptionをスローする可
  能性がある場合、どの式が例外を発生させたのかを判断することは困難/
  不可能

‣ 理由3. NullPointerExceptionがスローされた後、プログラムが想定通り
  に動作する状態であることはまれ



    結論:キャッチするんじゃなくて、例外が発生す
        る根本原因を修正すべきである



                       74
問題のあるコード

     boolean isName(String s) {                          このコードの何が問題?
    try {
      String names[] = s.split(" ");

      if (names.length != 2) {
        return false;
      }
      return (isCapitalized(names[0]) && isCapitalized(names[1]));
    } catch (NullPointerException e) {
      return false;
    }
}




                                       75
引数のStringがnullでないことを確認する

      boolean isName(String s) {  sを使う前にnullチェックを行う
    if (s == null) {                      (メソッドの引数を検証)
       return false;
    }
    String names[] = s.split(" ");
    if (names.length != 2) {
       return false;
    }
    return (isCapitalized(names[0]) && isCapitalized(names[1]));
}




‣ NullPointerExceptionをキャッチすると、null参照を隠 した
  り、アプリのパフォーマンスが低下したり、保守性の低いコー
  ドを生み出すことになりかねません。気をつけましょう。



                                 76
脆弱性事例
Apache ActiveMQ の認証不備




            77
Apache ActiveMQ (AMQ-1272)
 Apache ActiveMQ: メッセージングサーバ
 JMS (Java Message Service)を実装したミドルウェア
 システムコンポーネント間のメッセージ通信を実
 現する



AMQ-1272(https://issues.apache.org/jira/browse/AMQ-1272)
ユーザ認証に失敗すると認証モジュールは例外を発生.
しかし, その例外は無視されて認証に成功したものとされてしまう.
その結果, どんなユーザ名/パスワードでもサービスを利用できた.




                                       78
Apache ActiveMQ (AMQ-1272)

               無効なユーザ名/パスコード




                  メッセージ送信
認証失敗
認証モジュールは
例外をスロー



 例外は無視され,
 そのままメッセージ受付




                    79
Apache ActiveMQ (AMQ-1272)
public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {

    if (context.getSecurityContext() == null) {
        // Check the username and password.
        String pw = (String)userPasswords.get(info.getUserName());
        if (pw == null || !pw.equals(info.getPassword())) {
            throw new SecurityException("User name or password is invalid.");
        }

        final Set groups = (Set)userGroups.get(info.getUserName());
        SecurityContext s = new SecurityContext(info.getUserName()) {
            public Set<?> getPrincipals() {
                return groups;
            }
        };

        context.setSecurityContext(s);
        securityContexts.add(s);
    }
    super.addConnection(context, info);
}                                                        パスワード不一致により認証失敗.
                                                         SecurityException をスロー.



                                                                 ActiveMQ-4.1.1
                                                                 SimpleAuthenticationBroker.java

                                                 80
Apache ActiveMQ (AMQ-1272)
......
connectionInfo.setResponseRequired(true);                                    ActiveMQ-4.1.1
connectionInfo.setUserName(login);
connectionInfo.setPassword(passcode);

sendToActiveMQ(connectionInfo, new ResponseHandler() {
    public void onResponse(ProtocolConverter converter, Response response) throws IOException {



        final SessionInfo sessionInfo = new SessionInfo(sessionId);
        sendToActiveMQ(sessionInfo, null);

        final ProducerInfo producerInfo = new ProducerInfo(producerId);
        sendToActiveMQ(producerInfo, new ResponseHandler() {
            public void onResponse(ProtocolConverter converter, Response response) throws IOException {
                ......
                ......


                                                      認証失敗のとき例外がスローされ,
                                                      response にその情報がはいってくる.
                                                      しかし, なにもチェックしていない.


                                                                             ActiveMQ-4.1.1
                                                                             ProtocolConverter.java

                                                 81
Apache ActiveMQ (AMQ-1272)
  ......
  connectionInfo.setResponseRequired(true);                                   ActiveMQ-5.0.0
  connectionInfo.setUserName(login);
  connectionInfo.setPassword(passcode);

  sendToActiveMQ(connectionInfo, new ResponseHandler() {
      public void onResponse(ProtocolConverter converter, Response response) throws IOException {

          if (response.isException()) {
              // If the connection attempt fails we close the socket.
              Throwable exception = ((ExceptionResponse)response).getException();
              handleException(exception, command);
              getTransportFilter().onException(IOExceptionSupport.create(exception));
              return;
          }

          final SessionInfo sessionInfo = new SessionInfo(sessionId);
          sendToActiveMQ(sessionInfo, null);

          final ProducerInfo producerInfo = new ProducerInfo(producerId);
          sendToActiveMQ(producerInfo, new ResponseHandler() {
              public void onResponse(ProtocolConverter converter, Response response) throws IOException {
                  ......
                  ......




response に例外がはいっていた場合には接続中断の処理
                                                                               ActiveMQ-5.0.0
                                                                               ProtocolConverter.java

                                                   82
summary

  「最適に使用された場合、例外はプログラム
  の読みやすさ、信頼性、保守性を改善しま
  す。不適切にしようされた場合、逆効果とな
  ります。

           Effective Java 第2版, 第9章 例外




             83
参考情報
‣ Java Tutorials(http://docs.oracle.com/javase/tutorial/index.html)
   ‣ Essential Classes
      ‣ Exceptions
      ‣ Basic I/O



‣ Java I/O, 2nd Edition
   ‣ Elliotte Rusty Harold, O’reilly




                                 84

Contenu connexe

Tendances

JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるKoichi Sakata
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルなおき きしだ
 
“Design and Implementation of Generics for the .NET Common Language Runtime”他...
“Design and Implementation of Generics for the .NET Common Language Runtime”他...“Design and Implementation of Generics for the .NET Common Language Runtime”他...
“Design and Implementation of Generics for the .NET Common Language Runtime”他...Masahiro Sakai
 
C#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive ExtensionsC#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive ExtensionsYoshifumi Kawai
 
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Yoshifumi Kawai
 
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE).NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)Tusyoshi Matsuzaki
 
Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016Yoshio Terada
 
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するそうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するshigeki_ohtsu
 
【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream APIdcomsolution
 
Java SE 7 InvokeDynamic in JRuby
Java SE 7 InvokeDynamic in JRubyJava SE 7 InvokeDynamic in JRuby
Java SE 7 InvokeDynamic in JRubyHiroshi Nakamura
 
Reactive Extensions v2.0
Reactive Extensions v2.0Reactive Extensions v2.0
Reactive Extensions v2.0Yoshifumi Kawai
 
Node-v0.12の新機能について
Node-v0.12の新機能についてNode-v0.12の新機能について
Node-v0.12の新機能についてshigeki_ohtsu
 
PHP AST 徹底解説(補遺)
PHP AST 徹底解説(補遺)PHP AST 徹底解説(補遺)
PHP AST 徹底解説(補遺)do_aki
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ信之 岩永
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎信之 岩永
 
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しようUnity Technologies Japan K.K.
 
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Takefumi MIYOSHI
 

Tendances (20)

JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
 
“Design and Implementation of Generics for the .NET Common Language Runtime”他...
“Design and Implementation of Generics for the .NET Common Language Runtime”他...“Design and Implementation of Generics for the .NET Common Language Runtime”他...
“Design and Implementation of Generics for the .NET Common Language Runtime”他...
 
C#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive ExtensionsC#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive Extensions
 
講座Java入門
講座Java入門講座Java入門
講座Java入門
 
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)
 
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE).NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
 
Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016Java Puzzlers JJUG CCC 2016
Java Puzzlers JJUG CCC 2016
 
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するそうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
 
【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API
 
ret2libc
ret2libcret2libc
ret2libc
 
Java SE 7 InvokeDynamic in JRuby
Java SE 7 InvokeDynamic in JRubyJava SE 7 InvokeDynamic in JRuby
Java SE 7 InvokeDynamic in JRuby
 
Reactive Extensions v2.0
Reactive Extensions v2.0Reactive Extensions v2.0
Reactive Extensions v2.0
 
Node-v0.12の新機能について
Node-v0.12の新機能についてNode-v0.12の新機能について
Node-v0.12の新機能について
 
PHP AST 徹底解説(補遺)
PHP AST 徹底解説(補遺)PHP AST 徹底解説(補遺)
PHP AST 徹底解説(補遺)
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
Objc lambda
Objc lambdaObjc lambda
Objc lambda
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
 
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
 
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512
 

Similaire à Javaセキュアコーディングセミナー東京第3回講義

第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」yoshiaki iwanaga
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説JPCERT Coordination Center
 
明日から使える Java SE 7
明日から使える Java SE 7明日から使える Java SE 7
明日から使える Java SE 7Yuichi Sakuraba
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 TipsTakaaki Suzuki
 
Project Loom - 限定継続と軽量スレッド -
Project Loom - 限定継続と軽量スレッド - Project Loom - 限定継続と軽量スレッド -
Project Loom - 限定継続と軽量スレッド - Yuichi Sakuraba
 
ひのきのぼうだけで全クリ目指す
ひのきのぼうだけで全クリ目指すひのきのぼうだけで全クリ目指す
ひのきのぼうだけで全クリ目指すAromaBlack
 
Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習JPCERT Coordination Center
 
Apache Torqueについて
Apache TorqueについてApache Torqueについて
Apache Torqueについてtako pons
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するYoshifumi Kawai
 
きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjava
きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjavaきつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjava
きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjavabitter_fox
 
クラウド時代の並列分散処理技術
クラウド時代の並列分散処理技術クラウド時代の並列分散処理技術
クラウド時代の並列分散処理技術Koichi Fujikawa
 
研究生のためのC++ no.2
研究生のためのC++ no.2研究生のためのC++ no.2
研究生のためのC++ no.2Tomohiro Namba
 
Couchbase MeetUP Tokyo - #11 Omoidenote
Couchbase MeetUP Tokyo - #11 OmoidenoteCouchbase MeetUP Tokyo - #11 Omoidenote
Couchbase MeetUP Tokyo - #11 Omoidenotekitsugi
 
Python Kyoto study
Python Kyoto studyPython Kyoto study
Python Kyoto studyNaoya Inada
 
Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義JPCERT Coordination Center
 

Similaire à Javaセキュアコーディングセミナー東京第3回講義 (20)

第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
 
Introduction of Python
Introduction of PythonIntroduction of Python
Introduction of Python
 
20010901
2001090120010901
20010901
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説
 
明日から使える Java SE 7
明日から使える Java SE 7明日から使える Java SE 7
明日から使える Java SE 7
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
Project Loom - 限定継続と軽量スレッド -
Project Loom - 限定継続と軽量スレッド - Project Loom - 限定継続と軽量スレッド -
Project Loom - 限定継続と軽量スレッド -
 
ひのきのぼうだけで全クリ目指す
ひのきのぼうだけで全クリ目指すひのきのぼうだけで全クリ目指す
ひのきのぼうだけで全クリ目指す
 
Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習
 
Apache Torqueについて
Apache TorqueについてApache Torqueについて
Apache Torqueについて
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjava
きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjavaきつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjava
きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjava
 
クラウド時代の並列分散処理技術
クラウド時代の並列分散処理技術クラウド時代の並列分散処理技術
クラウド時代の並列分散処理技術
 
研究生のためのC++ no.2
研究生のためのC++ no.2研究生のためのC++ no.2
研究生のためのC++ no.2
 
Couchbase MeetUP Tokyo - #11 Omoidenote
Couchbase MeetUP Tokyo - #11 OmoidenoteCouchbase MeetUP Tokyo - #11 Omoidenote
Couchbase MeetUP Tokyo - #11 Omoidenote
 
Rakuten tech conf
Rakuten tech confRakuten tech conf
Rakuten tech conf
 
Project lambda
Project lambdaProject lambda
Project lambda
 
Python Kyoto study
Python Kyoto studyPython Kyoto study
Python Kyoto study
 
Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義
 

Plus de JPCERT Coordination Center

いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~JPCERT Coordination Center
 
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)JPCERT Coordination Center
 
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』JPCERT Coordination Center
 
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)JPCERT Coordination Center
 
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)JPCERT Coordination Center
 
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性JPCERT Coordination Center
 
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...JPCERT Coordination Center
 
クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策JPCERT Coordination Center
 
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)JPCERT Coordination Center
 
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」JPCERT Coordination Center
 
ソフトウェアセキュリティ保証成熟度モデル
ソフトウェアセキュリティ保証成熟度モデルソフトウェアセキュリティ保証成熟度モデル
ソフトウェアセキュリティ保証成熟度モデルJPCERT Coordination Center
 
Lessons (to be) Learned from Handling OpenSSL Vulnerabilities
Lessons (to be) Learned from Handling OpenSSL VulnerabilitiesLessons (to be) Learned from Handling OpenSSL Vulnerabilities
Lessons (to be) Learned from Handling OpenSSL VulnerabilitiesJPCERT Coordination Center
 
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)JPCERT Coordination Center
 
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)JPCERT Coordination Center
 
Apache Tomcat における クロスサイトリクエストフォージェリ (CSRF) 保護メカニズム回避の脆弱性
Apache Tomcat における クロスサイトリクエストフォージェリ (CSRF) 保護メカニズム回避の脆弱性Apache Tomcat における クロスサイトリクエストフォージェリ (CSRF) 保護メカニズム回避の脆弱性
Apache Tomcat における クロスサイトリクエストフォージェリ (CSRF) 保護メカニズム回避の脆弱性JPCERT Coordination Center
 
Spacewalkにおけるクロスサイト リクエストフォージェリ(CSRF)の脆弱性
Spacewalkにおけるクロスサイト リクエストフォージェリ(CSRF)の脆弱性Spacewalkにおけるクロスサイト リクエストフォージェリ(CSRF)の脆弱性
Spacewalkにおけるクロスサイト リクエストフォージェリ(CSRF)の脆弱性JPCERT Coordination Center
 

Plus de JPCERT Coordination Center (20)

いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
 
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
 
DLL読み込みの問題を読み解く
DLL読み込みの問題を読み解くDLL読み込みの問題を読み解く
DLL読み込みの問題を読み解く
 
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
 
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
 
脆弱性情報はこうしてやってくる
脆弱性情報はこうしてやってくる脆弱性情報はこうしてやってくる
脆弱性情報はこうしてやってくる
 
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
 
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
 
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
 
クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策
 
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
 
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
 
ソフトウェアセキュリティ保証成熟度モデル
ソフトウェアセキュリティ保証成熟度モデルソフトウェアセキュリティ保証成熟度モデル
ソフトウェアセキュリティ保証成熟度モデル
 
Lessons (to be) Learned from Handling OpenSSL Vulnerabilities
Lessons (to be) Learned from Handling OpenSSL VulnerabilitiesLessons (to be) Learned from Handling OpenSSL Vulnerabilities
Lessons (to be) Learned from Handling OpenSSL Vulnerabilities
 
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
 
Android Secure Coding
Android Secure CodingAndroid Secure Coding
Android Secure Coding
 
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
 
Apache Axis2におけるXML署名検証不備
Apache Axis2におけるXML署名検証不備Apache Axis2におけるXML署名検証不備
Apache Axis2におけるXML署名検証不備
 
Apache Tomcat における クロスサイトリクエストフォージェリ (CSRF) 保護メカニズム回避の脆弱性
Apache Tomcat における クロスサイトリクエストフォージェリ (CSRF) 保護メカニズム回避の脆弱性Apache Tomcat における クロスサイトリクエストフォージェリ (CSRF) 保護メカニズム回避の脆弱性
Apache Tomcat における クロスサイトリクエストフォージェリ (CSRF) 保護メカニズム回避の脆弱性
 
Spacewalkにおけるクロスサイト リクエストフォージェリ(CSRF)の脆弱性
Spacewalkにおけるクロスサイト リクエストフォージェリ(CSRF)の脆弱性Spacewalkにおけるクロスサイト リクエストフォージェリ(CSRF)の脆弱性
Spacewalkにおけるクロスサイト リクエストフォージェリ(CSRF)の脆弱性
 

Javaセキュアコーディングセミナー東京第3回講義

  • 3. 本セミナーについて ‣ 4回連続セミナーです ‣ 第1回 9月9日(日) ‣ オブジェクトの生成と消滅におけるセキュリティ ‣ 第2回 10月14日(日) ‣ 数値データの取扱いと入力値検査 ‣ 第3回 11月11日(日) ‣ 入出力(ファイル,ストリーム)と例外時の動作 ‣ 第4回 12月16日 ‣ メソッドのセキュリティ ‣ 開発環境持参 3
  • 4. 今日の時間割 ‣ 講義 (13:30--15:00) ‣ 入出力 ‣ 例外時の動作 ‣ ハンズオン (15:10--16:30) 4
  • 6. ‣ Java の入出力ストリーム ‣ ファイルシステムの扱い ‣ 共有ディレクトリの危険性 6
  • 7. I/O streams in Java Java 言語では, データの入出力を「ストリーム」と いう形で抽象化している. - ディスクの読み書き - ネットワーク通信 - 他のプログラムとのやりとりなど from Basic I/O, The Java Tutorials 7
  • 8. I/O streams in Java •バイトデータのストリーム •InputStream や OutputStream など •文字データのストリーム •Reader や Writer など •Filter{In,Out}putStream (他のストリームに機能を追加する) •Buffered ストリーム(バッファリング機能) •Data ストリーム(プリミティブ型やString型の値の入出力に使われる) •Object ストリーム(シリアライズの際, オブジェクトの入出力に使われる) 8
  • 9. I/O streams in Java •バイトデータのストリーム •InputStream や OutputStream など •InputStream •AudioInputStream •文字データのストリーム •ByteArrayInputStream •FileInputStream •InflaterInputStream •Reader や Writer など •GZIPInputStream •ZipInputStream •Filter{In,Out}putStream (他のストリームに機能を追加する) •JarInputStream •Reader •FilterInputStream •BufferedReader •BufferedInputStream •LineNumberReader •Buffered ストリーム(バッファリング機能) •DataInputStream •CharArrayReader •PushbackInputStream •FilterReader •Data ストリーム(プリミティブ型やString型の値の入出力に使われる) •CheckedInputStream •PushbackReader •CipherInputStream •InputStreamReader •Object ストリーム(シリアライズの際, オブジェクトの入出力に使われる) •DeflaterInputStream •FileReader •DigestInputStream •PipedInputStream •ProgressMonitorInputStream •StringReader •ObjectInputStream •AudioFileReader •PipedInputStream •ImageReader •SequenceInputStream •MidiFileReader •FileCacheImageInputStream •SoundbankReader •FileImageInputStream •MemoryCacheImageInputStream 9
  • 10. サンプルコード: xanadu.txt を outagain.txt にバイト単位でコピー import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyBytes { public static void main(String[] args) throws IOException { FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream(“xanadu.txt”); out = new FileOutputStream(“outagain.txt”); int c; while ((c = in.read()) != -1){ out.write(c); } } finally { if (in != null){ in.close(); } if (out != null){ out.close(); } } } } 10
  • 11. FIO08-J: 文字やバイトを読み取るメソッドの返り値は int で受ける byte[] c = new byte[1]; while ((c[0] = (byte)in.read()) != -1){ out.write(c); } read() の返り値を byte 型にキャストする とどうなる? 11
  • 12. FIO08-J: 文字やバイトを読み取るメソッドの返り値は int で受ける int read() throws IOException 入力ストリームからデータの次のバイトを読み込む. 値のバイトは 0 から 255 の範囲の int 型データ. ストリームの終わりに達した場合は -1 が返される. •read() ... 0xff を読み込んだら返り値は0x000000ff •(byte)read() ... 0xff (下位1バイト)に切り捨てられる •... != -1 ... 比較演算で int 型の 0xffffffff に格上げされる byte 型は符号付き整数型なので, 0xff は -1(decimal) として扱わ れ, 0xffffffff に格上げされ, end-of-stream と区別できなくなる DoS 攻撃に悪用されるかも! 12
  • 14. サンプルコード: データベースとのやりとり public void getResults(String sqlQuery) { try { Connection conn = getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sqlQuery); processResults(rs); stmt.close(); conn.close(); } catch (SQLException e) { /* ハンドラに処理を移す */ } } executeQuery()やprocessResults()で例外が 発生するとデータベース接続がクローズ されないじゃないか! 14
  • 15. サンプルコード: データベースとのやりとり public void getResults(String sqlQuery) { Statement stmt = null; ResultSet rs = null; Connection conn = getConnection(); try { stmt = conn.createStatement(); rs = stmt.executeQuery(sqlQuery); processResults(rs); } catch(SQLException e) { // ハンドラに処理を移す } finally { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } if (conn !=null) { conn.close(); } } } close() メソッドで SQLException が発 生したら finally 節は途中で終了しちゃ うよ! 15
  • 16. サンプルコード: データベースとのやりとり public void getResults(String sqlQuery) { Statement stmt = null; try-catch-finally を駆使して ResultSet rs = null; Connection conn = getConnection(); 全ての close() メソッドを try { ガードすればなんとか... stmt = conn.createStatement(); rs = stmt.executeQuery(sqlQuery); processResults(rs); } catch (SQLException e) { ... ハンドラに処理を移す ... } finally { try { if (rs != null) {rs.close();} } catch (SQLException e) { ... ハンドラに処理を移す ... } finally { try { if (stmt != null) {stmt.close();} } catch (SQLException e) { ... ハンドラに処理を移す ... } finally { try { if (conn != null) {conn.close();} } catch (SQLException e) { ... ハンドラに処理を移す ... }}}}} 16
  • 17. サンプルコード: データベースとのやりとり public void getResults(String sqlQuery) { try (Connection conn = getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sqlQuery)) { processResults(rs); } catch (SQLException e) { // ハンドラに処理を移す } } Java7 の try-with-resources を使 うと簡潔なコードになるよ! 17
  • 18. ストリーム入出力に関連するコーディングルール ‣ FIO04-J. 不要になったらリソースを解放する ‣ FIO05-J. wrap() や duplicate() メソッドで作成したバッファを信頼できないコード にアクセスさせない ‣ FIO06-J. ひとつの InputStream に対して複数のバッファ付きラッパーを作成しない ‣ FIO07-J. 外部プロセスに IO バッファをブロックさせない ‣ FIO08-J. 文字やバイトを読み取るメソッドの返り値は int で受ける ‣ FIO09-J. 0 から 255 の範囲に収まらない整数値を出力するときには write() メソッ ドを信用しない ‣ FIO10-J. read() を使って配列にデータを読み込むときには配列への読み込みが意 図した通りに行われたことを確認する ‣ FIO11-J. バイナリデータを文字データとして読み込もうとしない ‣ FIO12-J. リトルエンディアン形式のデータを読み書きするメソッドを用意する ‣ FIO13-J. センシティブな情報を信頼境界の外に記録しない ‣ FIO14-J. プログラムの終了時には適切なクリーンアップを行う 18
  • 19. ‣ Java の入出力ストリーム ‣ ファイルシステムの扱い ‣ 共有ディレクトリの危険性 19
  • 20. ディレクトリトラバーサル ディレクトリトラバーサル攻撃 アクセス可能であることを意図していない ファイルへのアクセスを行う攻撃. ‣ ファイル関連の脆弱性で典型的なもの ‣ 前回, 東京セミナpart2で, ディレクトリトラバーサルの問題を 作り込んだコード例を紹介 ‣ https://www.owasp.org/index.php/Path_Traversal http://ja.wikipedia.org/wiki/ディレクトリトラバーサル 20
  • 21. サンプルプログラム: ディレクトリトラバーサル class filecat { static private String BASEDIR="/home/yozo/tmp/"; 対象とするディレクトリ static public void cat(String s) throws IOException { BufferedReader bf = new BufferedReader(new FileReader(BASEDIR + s)); String line; while (null != (line = bf.readLine())){ System.out.println(line); } 単純な文字列連結だけ } 行っている public static void main(String[] args) throws IOException { String filename = args[0]; cat(filename); } } ファイル名を期待 前回part2で紹介 21
  • 22. サンプルプログラム: ディレクトリトラバーサル 想定通りの動作 $ java filecat choi hoihoi $ java filecat ../Documents/WORK/SecureCoding/20121014.Tokyo_part2/ filecat.java import java.io.BufferedReader; import java.io.FileReader; 想定外の入力!! import java.io.FileNotFoundException; import java.io.IOException; class filecat { static private String BASEDIR="/Users/yozo/tmp/"; (...... 以下省略 ......) 前回part2で紹介 22
  • 23. サンプルプログラム修正例 class filecat1 { static private String BASEDIR="/home/yozo/tmp/"; static public void cat(String s) throws IOException { File f = new File(BASEDIR + s); String fs = f.getCanonicalFile().toString(); if (!fs.startsWith(BASEDIR)) { throw (new IllegalArgumentException(fs)); } BufferedReader bf = new BufferedReader(new FileReader(f)); String line; while (null != (line = bf.readLine())){ System.out.println(line); } } public static void main(String[] args) throws IOException { String filename = args[0]; cat(filename); } } 対策: canonicalパスで想定通りのディレ クトリを指していることを確認する 23
  • 24. File I/O 「最終的に、どんな OS でも実行できるコード になった。JVM (および、Java 環境)が提供する 抽象化を利用して、OS とファイルシステムの差 異を隠 したおかげだ。」 Java The Good Parts, 6章 Java 仮想マシン 24
  • 25. File I/O Java アプリ ファイルシステム Java 仮想マシン オペレーティングシステム ファイルシステム •JVM は OS 層への統一的なインタ フェースを提供する. •OS 層はファイルシステムへの統一 的なインタフェースを提供する. 25
  • 26. ファイルシステムにもいろいろ ファイルシステムの例 •POSIX 系ファイルシステム •アクセスパーミッションによるアクセス制御 •NFSv4, NTFS •Access Control List によるアクセス制御 •FAT (MS-DOS) •file attribute によるアクセス制御 26
  • 28. File I/O ポータビリティに関する Java のスローガン “Write once, run anywhere” JRE(Java実行環境)は OS に依らない API を Java アプリに提供してくれる しかし セキュアなファイル操作を行うためには, ファイルシステムの詳細を理解しておく必 要がある 28
  • 29. File I/O Java アプリ ファイルシステム Java 仮想マシン オペレーティングシステム ファイルシステム ファイル操作は JVM, OS, ファイル システムを通じて行われている! 29
  • 30. File I/O POSIX $ ls -al showAttributesPosix.java -rw-r--r-- 1 yozo staff 764 Nov 9 14:51 showAttributesPosix.java $ NTFS C:>dir /q showAttributesACL.java ...... 2012/11/09 15:07 611 earlgreyyozo showAttributesACL.java ...... C:>icacls showAttributesACL.java showAttributesACL.java NT AUTHORITYSYSTEM:(I)(F) BUILTINAdministrators:(I)(F) earlgreyyozo:(I)(F) ...... C:> 30
  • 31. File I/O POSIX class showAttributesPosix { public static void main(String[] args) throws IOException { if (args.length <= 0){ return; } Path p = FileSystems.getDefault().getPath(args[0]); PosixFileAttributes attrs = Files.getFileAttributeView(p, PosixFileAttributeView.class) .readAttributes(); System.out.format(“%s %s%n”, attris.owner().getName(), PosixFilePermissions.toString(attrs.permissions())); } } $ java showAttributesPosix showAttributesPosix.java yozo -rw-r--r-- $ 31
  • 32. File I/O ACL class showAttributesACL { public static void main(String[] args) throws IOException { if (args.length <= 0){ return; } Path p = FileSystems.getDefault().getPath(args[0]); List<AclEntry> acls = Files.getFileAttributeView(p, AclFileAttributeView.class) .getAcl(); for(AclEntry acl : acls) { System.out.println(acl.toString()); } } } C:> java showAttributesACL showAttributesACL.java NT AUTHORITYSYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/ WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/ DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW BUILTINAdministrators:READ_DATA/WRITE_DATA/APPEND_DATA/ READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/ WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW earlgreyyozo:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/ WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/ DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW C:> 32
  • 33. File I/O OS とファイルシステムの差異を隠 したって 言っても、隠しきれないものもある。 ポータビリティを確保するのは難しい。 33
  • 34. ‣ Java の入出力ストリーム ‣ ファイルシステムの扱い ‣ 共有ディレクトリの危険性 34
  • 35. 共有ディレクトリの危険性 [共有ディレクトリ] マルチユーザシステムにおいて, 複数のユーザに対してアクセスが許されて いるディレクトリのことを「共有ディレクトリ」と呼ぶ. POSIX 系における “/tmp” や Windows における “C:WindowsTemp” など. 共有ディレクトリは危険! 他のユーザがファイルを改ざん/削除したり, 他の ファイルへのリンクを作るかもしれない. 35
  • 36. Symlink 攻撃 通常の動作 program program shared プログラム プログラム 削除 他のプログラムがファイルにアク セスしなければ問題は発生しない. 36
  • 37. Symlink 攻撃 symlink attack(1) 攻撃者はターゲットファイルを 削除する権限を持っていない ターゲット shared プログラム 攻撃者 攻撃者はプログラムが操作するファイル をあらかじめ削除し, ターゲットファイル へのシンボリックリンクを作る. 37
  • 38. Symlink 攻撃 symlink attack(2) ターゲット shared プログラム 攻撃者 削除 プログラムは, シンボリックリン クに置き換えられているとは知ら ずに問題のファイルを削除する... 38
  • 39. Symlink 攻撃 symlink attack(3) ターゲット shared プログラム 攻撃者 削除 ... そして target ファイルは削除 されてしまった! 39
  • 41. Summary ‣ JRE(Java 実行環境)はOS層を抽象化してくれる ‣ しかし以下のような処理が必要な場合は OS やファイルシステムの基本的な特徴を理解し ておくべき. ‣ ファイル操作(作成, 変更, 削除など) ‣ ファイルのアクセス制御に関する操作 41
  • 42. ファイル入出力に関連するコーディングルール ‣ FIO00-J. 共有ディレクトリにあるファイルを操作しない ‣ FIO01-J. 適切なパーミッションを設定してファイルを作成する ‣ FIO02-J. ファイル関連エラーを検知し、処理する ‣ FIO03-J. 一時ファイルはプログラムの終了前に削除する ‣ 42
  • 44. 例外とは ‣ exception = exceptional event ‣ 定義 ‣ 例外(exception)とは、プログラムの実行中に発生し、プロ グラム実行の正常な流れを分断するイベントのこと。 ‣ 例:ゼロ除算、配列の境界外アクセス 44
  • 45. 例外とは throws する exception object メソッド JVM エラーが起こった! 45
  • 46. 例外とは ‣ コールスタック(call stack) 例外オブジェクトが エラーが発生したメソッド 飛んできた! だれがハンドルする メソッド呼出し んだっけ? 例外ハンドラを持たないメソッド メソッド呼出し JVM 例外ハンドラを持つメソッド メソッド呼出し main() call stack 46
  • 47. 例外とは ‣ コールスタッフを調べ、例外ハンドラをみつける 例外をスローする エラーが発生したメソッド 適切なハンドラを探す 例外をフォワードす 例外ハンドラを持たないメソッド る catchされた 適切なハンドラを探す 例外ハンドラを持つメソッド exception object 君が処理してね main() JVM call stack 47
  • 48. 例外とは ‣ 例外 = オブジェクト ‣ エラー発生時のプログラムの状態を、コールスタックの上位 に伝える ‣ エラーを種類によってグループ化/差異化 ‣ 拡張できる ‣ 通常の処理を行うコードと、エラー処理のコードの分離 48
  • 49. Object 例外のクラス階層 Throwable 84種類のサブクラス を持つ Error Exception IOError IOException VirtualMachineError FileNotFoundException StackOverflowError RuntimeException OutOfMemoryError NullPointerException ArithmeticException IndexOutOfBoundsException チェック例外 未チェック例外 49
  • 50. 3つの例外 ‣ 未チェック例外 (unchecked exception) ‣ Error ‣ RuntimeException ‣ コンパイラはチェックしてくれない ‣ throws 宣言しなくてもよい ‣ アプリは例外から戻れないという想定 ‣ 「実行時例外」という訳語 ‣ チェック例外 (checked exception) ‣ ハンドラを必ず実装 ‣ コンパイラがチェック 50
  • 51. 未チェック例外 ‣ Error と RuntimeException ‣ コンパイラによるチェックは行われない ‣ メソッドで必ずしもthrowしなくてもよい ‣ ランタイム(Javaの実行環境)が出す例外なのでプログラムで はどうしようもない、という発想 51
  • 52. 未チェック例外 未チェック例外クラスであるエラークラス(Errorとそのサブクラ ス)は、プログラム中の様々な場所で発生する可能性があり、そう いったものの回復は難しく、あるいは不可能であるため、コンパイ ル時にはチェックされない ...... 実行時例外クラス(RuntimeExceptionとそのサブクラス)は、こう いった例外の宣言を強制してもJavaプログラムの正当性を確立する ための著しい助けにはならないだろう、というプログラミング言語 の設計者達による判断によって、コンパイル時にはチェックされな い。 Java 言語仕様 11.2.4 コンパイル時の例外のチェックされない理由 11.2.5 実行時例外がチェックされない理由 52
  • 54. try-catch-finallyの制御構造 try { // 何らかの処理 // X, Y, Z を throw  // するかもしれない 例外 X が 例外 Y が 例外 Z が } スローされた スローされた スローされた 例外はスローされなかった catch (X e) { catch (Y e) { catch (Z e) { // handle e of X // handle e of Y // handle e of Z } } } finally { // 必ず実行される } 54
  • 55. 例外処理のアンチパターンとセキュリティ ‣ 例外をキャッチしない (CWE-248) ‣ チェック例外を無視/抑制する (ERR00-J, CWE-390, CWE-391) ‣ プログラム制御に例外を使用する (EffectiveJava 57) ‣ エラーメッセージを通じたセンシティブな情報を漏洩する (CWE-209) ‣ NullPointerExceptionをキャッチする (ERR08-J, CWE-395) ‣ 例外スロー時にリソースのクリーンアップを適切に行わない (CWE-460) ‣ スローする例外が一般的すぎる (CWE-397) ‣ プログラムの異常状態や例外条件を適切にチェックしない (CWE-754) 55
  • 57. 例外をキャッチしない ‣ あとでオブジェクトを使うときにエラーが発生する ‣ 現実にはこのアプローチをとるコードが非常に多い(らしい) protected void doPost ( HttpServletRequest req, HttpServletResponse res) throws IOException { String ip = req.getRemoteAddr(); InetAddress addr = InetAddress.getByName(ip); ... out.println("hello " + addr.getHostName()); } ‣ DNS lookupに失敗するとServletは例外をスローするにもかか わらず、キャッチしていない ‣ アプリがクラッシュ、DoS攻撃に悪用される 57
  • 59. チェック例外を無視/抑制する public String readFile(String filename) { 例外が発生するのは String retString = null; どこ? try { // File および FileReader オブジェクトを初期化 File file = new File(filename); FileReader fr = new FileReader(file); // 文字バッファを初期化 long fLen = file.length(); char[] cBuf = new char[(int) fLen]; // ファイルからデータを読込む int iRead = fr.read(cBuf, 0, (int) fLen); // クローズ処理 fr.close(); retString = new String(cBuf); } catch (Exception ex) { } return retString; } 59
  • 60. public String readFile(String filename) throws FileNotFoundException, IOException, Exception { String retString = null; try { // initialize File and FileReader objects File file = new File(filename); FileReader fr = new FileReader(file); // initialize character buffer long fLen = file.length(); char [] cBuf = new char[(int) fLen]; 各例外に対するハンドラを実装 // read data from file int iRead = fr.read(cBuf, 0, (int) fLen); (この場合、例外に関する情報をユーザに 出力してから、例外を再スローしている) // close file fr.close(); retString = new String(cBuf); } catch (FileNotFoundException ex) { System.err.println ("Error: FileNotFoundException opening the input file: " + filename ); System.err.println ("" + ex.getMessage() ); throw new FileNotFoundException(ex.getMessage()); } catch (IOException ex) { System.err.println("Error: IOException reading the input file.n" + ex.getMessage() ); throw new IOException(ex); } catch (Exception ex) { System.err.println("Error: Exception reading the input file.n" + ex.getMessage() ); throw new Exception(ex); } return retString; } 60
  • 61. FileNotFoundException ‣ FileNotFoundExceptionはチェック例外 ‣ 指定されたファイルが開けない場合、APIは、呼出し元がなん らかのアクションをとることを期待する ‣ 例:ユーザに別のファイルを指定させる ‣ 前述のコードでは、呼出し元に処理を委譲するため、再度例外 をスローしていた java.lang.Object java.lang.Throwable java.lang.Exception java.io.IOException java.io.FileNotFoundException 61
  • 63. 例外の誤用 public class Antipattern { public static void main(String[] args) { try { int i = 0; while (true) { System.out.println(args[i++]); } } catch (ArrayIndexOutOfBoundsException e) { } } } 63
  • 64. 通常の制御フローに例外を使わない public class Antipattern { public static void main(String[] args) { int i = 0; for (i = 0; i < args.length(); i++) { System.out.println(args[i]); } } } ‣ 例外はコードの最適化に役立たない ‣ JVMによる最適化を排除する可能性がある 64
  • 66. 例外に含まれるセンシティブな情報 ‣ 実行スタックのスナップショット ‣ 例外メッセージ ‣ 例外の種類 例外オブジェクトに含まれるこれらの情報は、 攻撃の手がかりを与えてしまう 66
  • 67. センシティブな情報を含む例外 例外名 漏洩する情報/脅威 java.io.FileNotFoundException ファイルシステムの構成、ユーザ名の列挙 java.sql.SQLException データベースの構成、ユーザ名の列挙 信頼できないクライアントがサーバのポートを選択 java.net.BindException できる場合、開いているポートを列挙 java.util.ConcurrentModificationException スレッドセーフでないコードに関する情報 javax.naming.InsufficientResourcesException 不十分なサーバーリソース (DoSにつながる可能性) java.util.MissingResourceException リソースの列挙 java.util.jar.JarException ファイルシステムの構成 java.security.acl.NotOwnerException 所有者の列挙 java.lang.OutOfMemoryError DoS java.lang.StackOverflowError DoS 67
  • 68. 問題のあるコード class FileOpen { public static void main(String[] args) throws FileNotFoundException, IOException { FileReader fr = null; try { fr = new FileReader("fff.txt"); } finally { if (fr != null){ fff.txtが見つからないと、 fr.close(); FileNotFoundException } } がスローされる } } Exception in thread "main" java.io.FileNotFoundException: fff.txt (No such file or directory) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(FileInputStream.java:120) at java.io.FileInputStream.<init>(FileInputStream.java:79) at java.io.FileReader.<init>(FileReader.java:41) at FileOpen0.main(FileOpen0.java:9) 68
  • 69. 問題のあるコード class FileOpen { public static void main(String[] args) throws FileNotFoundException, IOException { FileReader fr = null; try { fr = new FileReader(args[0]); } catch (FileNotFoundException ex) { String logMessage = “Unable to find file:” + arg[1]; Logger.getLogger(FileOpen.class.getName()).log(Level.SEVERE, logMessage, ex); } finally { if (fr != null){ fr.close(); 指定されたファイルが見つからない } と、エラーメッセージが作られ、ログ } } ファイルに出力される } ‣ ファイルシステムに「あるファイル」が存在するかどうかがロ グを見れば分かってしまう 69
  • 70. センシティブな情報をフィルターする import java.io.FileReader; import java.io.FileNotFoundException; import java.io.IOException; class FileOpen { public static void main(String[] args) throws FileNotFoundException, IOException { FileReader fr = null; try { fr = new FileReader("fff.txt"); } catch (FileNotFoundException f){ throw new FileNotFoundException("not found"); } finally { if (fr != null){ fr.close(); ファイル名を例外から削る } } } } Exception in thread "main" java.io.FileNotFoundException: not found ! at FileOpen.main(FileOpen.java:11) 70
  • 71. センシティブな情報をフィルターする import java.io.FileReader; import java.io.FileNotFoundException; import java.io.IOException; class FileOpen { public static void main(String[] args) throws FileNotFoundException, IOException { FileReader fr = null; try { fr = new FileReader("fff.txt"); } catch (FileNotFoundException f){ throw new IOException("something wrong!"); } finally { if (fr != null){ fr.close(); IOExceptionをスローする } } } } Exception in thread "main" java.io.IOException: something wrong! ! at FileOpen.main(FileOpen.java:11) 71
  • 73. java.lang.NullPointerException ‣ RuntimeExceptionを継承している ‣ つまり未チェック例外 ‣ オブジェクトが要求されるコードでnullが使われるとスローさ れる: ‣ nullオブジェクトのインスタンスメソッド呼出し ‣ nullオブジェクトのフィールドのアクセス/変更 ‣ 配列だと思ってnullのlength取得する ‣ 配列だと思ってnullのスロットへアクセス/変更 ‣ Throwableの値だと思ってnullをスローする 73
  • 74. なぜNullPointerExceptionをキャッチしてはいけないのか ‣ 理由1. NullPointerExceptionをキャッチする方が、値がnullかどうか チェックするコードを追加するより、オーバーヘッドがはるかに大きい ‣ 理由2. tryブロック中の複数の式がNullPointerExceptionをスローする可 能性がある場合、どの式が例外を発生させたのかを判断することは困難/ 不可能 ‣ 理由3. NullPointerExceptionがスローされた後、プログラムが想定通り に動作する状態であることはまれ 結論:キャッチするんじゃなくて、例外が発生す る根本原因を修正すべきである 74
  • 75. 問題のあるコード boolean isName(String s) { このコードの何が問題? try { String names[] = s.split(" "); if (names.length != 2) { return false; } return (isCapitalized(names[0]) && isCapitalized(names[1])); } catch (NullPointerException e) { return false; } } 75
  • 76. 引数のStringがnullでないことを確認する boolean isName(String s) { sを使う前にnullチェックを行う if (s == null) { (メソッドの引数を検証) return false; } String names[] = s.split(" "); if (names.length != 2) { return false; } return (isCapitalized(names[0]) && isCapitalized(names[1])); } ‣ NullPointerExceptionをキャッチすると、null参照を隠 した り、アプリのパフォーマンスが低下したり、保守性の低いコー ドを生み出すことになりかねません。気をつけましょう。 76
  • 78. Apache ActiveMQ (AMQ-1272) Apache ActiveMQ: メッセージングサーバ JMS (Java Message Service)を実装したミドルウェア システムコンポーネント間のメッセージ通信を実 現する AMQ-1272(https://issues.apache.org/jira/browse/AMQ-1272) ユーザ認証に失敗すると認証モジュールは例外を発生. しかし, その例外は無視されて認証に成功したものとされてしまう. その結果, どんなユーザ名/パスワードでもサービスを利用できた. 78
  • 79. Apache ActiveMQ (AMQ-1272) 無効なユーザ名/パスコード メッセージ送信 認証失敗 認証モジュールは 例外をスロー 例外は無視され, そのままメッセージ受付 79
  • 80. Apache ActiveMQ (AMQ-1272) public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception { if (context.getSecurityContext() == null) { // Check the username and password. String pw = (String)userPasswords.get(info.getUserName()); if (pw == null || !pw.equals(info.getPassword())) { throw new SecurityException("User name or password is invalid."); } final Set groups = (Set)userGroups.get(info.getUserName()); SecurityContext s = new SecurityContext(info.getUserName()) { public Set<?> getPrincipals() { return groups; } }; context.setSecurityContext(s); securityContexts.add(s); } super.addConnection(context, info); } パスワード不一致により認証失敗. SecurityException をスロー. ActiveMQ-4.1.1 SimpleAuthenticationBroker.java 80
  • 81. Apache ActiveMQ (AMQ-1272) ...... connectionInfo.setResponseRequired(true); ActiveMQ-4.1.1 connectionInfo.setUserName(login); connectionInfo.setPassword(passcode); sendToActiveMQ(connectionInfo, new ResponseHandler() { public void onResponse(ProtocolConverter converter, Response response) throws IOException { final SessionInfo sessionInfo = new SessionInfo(sessionId); sendToActiveMQ(sessionInfo, null); final ProducerInfo producerInfo = new ProducerInfo(producerId); sendToActiveMQ(producerInfo, new ResponseHandler() { public void onResponse(ProtocolConverter converter, Response response) throws IOException { ...... ...... 認証失敗のとき例外がスローされ, response にその情報がはいってくる. しかし, なにもチェックしていない. ActiveMQ-4.1.1 ProtocolConverter.java 81
  • 82. Apache ActiveMQ (AMQ-1272) ...... connectionInfo.setResponseRequired(true); ActiveMQ-5.0.0 connectionInfo.setUserName(login); connectionInfo.setPassword(passcode); sendToActiveMQ(connectionInfo, new ResponseHandler() { public void onResponse(ProtocolConverter converter, Response response) throws IOException { if (response.isException()) { // If the connection attempt fails we close the socket. Throwable exception = ((ExceptionResponse)response).getException(); handleException(exception, command); getTransportFilter().onException(IOExceptionSupport.create(exception)); return; } final SessionInfo sessionInfo = new SessionInfo(sessionId); sendToActiveMQ(sessionInfo, null); final ProducerInfo producerInfo = new ProducerInfo(producerId); sendToActiveMQ(producerInfo, new ResponseHandler() { public void onResponse(ProtocolConverter converter, Response response) throws IOException { ...... ...... response に例外がはいっていた場合には接続中断の処理 ActiveMQ-5.0.0 ProtocolConverter.java 82
  • 83. summary 「最適に使用された場合、例外はプログラム の読みやすさ、信頼性、保守性を改善しま す。不適切にしようされた場合、逆効果とな ります。 Effective Java 第2版, 第9章 例外 83
  • 84. 参考情報 ‣ Java Tutorials(http://docs.oracle.com/javase/tutorial/index.html) ‣ Essential Classes ‣ Exceptions ‣ Basic I/O ‣ Java I/O, 2nd Edition ‣ Elliotte Rusty Harold, O’reilly 84