Java / Android
セキュアコーディング入門	




17-E-5                  久保 正樹	
                        JPCERTコーディネーションセンター	
                        脆弱性アナリスト	
                                  	
         Developers Summit 2012
自己紹介	

 §    久保 正樹(くぼ まさき)
       masaki.kubo@jpcert.or.jp	

 	

 §    脆弱性アナリスト@JPCERTコーディネーションセンター	

 §    GSSP-Cプログラマ、ISO/IEC SC27 WG4 エキスパート	


 §  プログラミングとの出会いはコンピュータ音楽から。前職は
     ソニー(株)でVAIOのソフトウェア開発。退職後、ダートマス
     大学で電子音響音楽修士。2005年からJPCERTコーディ
     ネーションセンターで情報セキュリティに従事。	

 	

                         Developers Summit 2012
自己紹介	

 §  先月、本を出しました!	

                 『Javaセキュアコーディング CERT/Oracle版』
                  http://www.amazon.co.jp/dp/4048860704	


                  歌代 和正(監修)	
                  久保 正樹, 戸田 洋三(翻訳)	
                  アスキー・メディアワークス(2012/1/27)	




          Developers Summit 2012
今日お話すること	

§  モバイルアプリをとりまくセキュリティ問題

§  セキュアコーディングの実践と3つの軸
 §  Java / Android の世界の
  脆弱性の実例とその修正


§  Java セキュアコーディング(CERT/Oracle版)の
 紹介

              Developers Summit 2012
Android/Javaの
セキュリティのヘッドライン	
 §  スマホを狙ったワンクリックウェアを確認
 §  Android端末を狙う不正プログラム、2012年
     末までに12万個に!?
 §  SMS 詐欺に利用される偽の Android マー
     ケットが再登場
 §  Javaの脆弱性を悪用する攻撃が急速に猛
     威
 §  …	
        プラットフォーム、マルウェア
                     の話題が後を絶たない	
          Developers Summit 2012
マルウェアに狙われたAndroid	

§  モバイルマルウェアの
    63%がAndroid狙い

§  アプリを改ざんして配布

§  目的はお金



             Developers Summit 2012
 モバイル端末に対する脅威	

§  成熟度の異なるプラットフォーム

§  ユースケース、利用パターンの複雑化
  §  従来のウェブアプリの脅威と異なる


§  アプリ単体だけ考えていてはだめ
  §  ウェブサービスとの連携
  §  C2DMとのインテグレーション	

           Developers Summit 2012
モバイルアプリのトップ10リスク(OWASP)

  §    M1 危険なデータ保存
  §    M2 不十分なサーバー側のコントロール
  §    M3 トランスポート層の保護が不十分
  §    M4 クライアントサイドインジェクション
  §    M5 お粗末な認証・認可の実装
  §    M6 セッション管理不備
  §    M7 信頼できない入力に基いたセキュリティ上の判断
  §    M8 サイドチャンネルでの情報漏えい
  §    M9 暗号化メカニズムの欠陥
  §    M10 センシティブな情報の漏えい	


               Developers Summit 2012
§  モバイルアプリでどこに脅威があるのか、だ
    いたい分かってきた

§  どう対応・修正するか…それが問題




        Developers Summit 2012
モバイルアプリの脆弱性	

 §  Tencent QQPhotoのパスワードハッシュ漏
     えい
 §  Kaixin001のコンタクトと平文パスワードを読
     まれる問題
 §  360 MobileSafeのSMSメッセージを読まれ
     る問題
 §  …
        基本的な間違いが繰返されている…	

                  JVN iPedia を "Android"をキーワードに検索	

           Developers Summit 2012
JPCERTに届けられたAndroidの脆弱性	

 §  2011/7〜約30件のアプリの脆弱性
  §  Androidプラットフォームの脆弱性も数件


 §  脆弱性の種類
  §  ファイル(DB)のパーミッション系
  §  Webview系
  §  JSONハイジャック系	



           Developers Summit 2012
新しいプラットフォームで繰り返される
過去の過ち	
§  Androidという新しいプラットフォーム
  §  アプリ250億ダウンロード(2011)
  §  大きなマーケットシェア+金銭的価値=攻撃


§  繰り返される、過去の過ち
  §  暗号化鍵のハードコーディング: 42%
  §  乱数のエントロピー不足:61%
  §  センシティブな情報の外部送信:39%
  §  エラーメッセージにセンシティブな情報:6%
          Veracode, State of Software Security Report. 2011	
          Developers Summit 2012
なぜ同じ過ちが繰り返されるのか?	

§  プログラマが「知らない」
  §  古い脆弱性が新しい脆弱性
  §  プラットフォームが成熟過程
  §  新たな脅威・攻撃手法が日々発見される世の
      中
   §  経験年数がものを言わない
  §  サプライチェーン
§  知っている(分かっている)けどできない!	
      数年前のウェブアプリ脆弱性のデジャヴ	
           Developers Summit 2012
何を知らないのが問題?	

     言語非依存のセキュアコーディング	
1.	
 入力値検査、FileI/O


     Java言語特有のセキュアコーディング
2.	
 OOP, Javaの型システム, expressionsなど
   言語仕様、標準APIに関するコーディングテクニック


3.	
 APIやプラットフォーム固有の
     セキュアコーディング
   J2EE/Android SDK,プラットフォームのセキュリティモデル	
            Developers Summit 2012
セキュアコーディング	

 §  プログラムのある種の欠陥が脆弱性を生む
  §  仕様/デザインの欠陥
  §  コーディングエラー
  §  パターンがある


 §  セキュアコーディングとは
  §  プログラマが脆弱性を作り込まないコーディング
      を実践する
    §  言語、API、プラットフォームを安全に(安全なところだ
        け)使いこなす
           Developers Summit 2012
1. 言語非依存の
  セキュアコーディング	




       Developers Summit 2012
Apache StrutsのXSS(1)	

 §  最近JVNで公開したstrutsの脆弱性	




           Developers Summit 2012
Apache StrutsのXSS(2)	
import java.io.Serializable;!
                                                                  問題のあるコード	
import java.util.Locale;!
 !
import org.apache.commons.lang.StringUtils;!
   !
// The Default ActionProxy implementation!
     … !
      Protected DefaultActionProxy(…, String actionName, String
methodName, …) {!
         LOG.debug("Creating an DefaultActionProxy for namespace "!
                    + namespace + " and action name " + actionName);!
          "     "!
!
         "this.actionName = actionName;!
         "this.namespace = namespace;!
         "this.executeResult = executeResult;!
         "this.method = methodName;!                       ActionNameとmethodNameは	
    }!                                                       外部から受け取ったデータ	

                        https://issues.apache.org/jira/secure/attachment/12472293/WW-35791-4.patch
                                    Developers Summit 2012
Apache StrutsのXSS(3)	
                      エラー画面の出力でXSS	

                                                                               攻撃者	

           webサーバ	

                              細工された入力	
                              http://...home.action?...action!login<script>alert(document.cookie)</
                              script>:cantLogin=some_value
          struts


                         actionName = login<script>alert(document.cookie)</script>
action1                  methodName = cantLogin=some_value


      action2
                   action3

                                   Developers Summit 2012
Apache StrutsのXSS(4)	
                                                                         修正後	
import org.apache.commons.lang.StringEscapeUtils;!
import org.apache.commons.lang.StringUtils;!            Apache Commons ライブラリの	
import java.io.Serializable;!
                                                         escape*()を活用して無害化	
import java.util.Locale;!
   !
// The Default ActionProxy implementation!
…!
     Protected DefaultActionProxy(…, String actionName, String methodName, …) !
     {!
        LOG.debug("Creating an DefaultActionProxy for namespace "!
                   + namespace + " and action name " + actionName);!
     !
!
  this.actionName = StringEscapeUtils.escapeHtml(actionName);!
  this.namespace = namespace;!
  this.executeResult = executeResult;!
  this.method =
StringEscapeUtils.escapeJavaScript(StringEscapeUtils.escapeHtml(methodName));!
  }!

                     https://issues.apache.org/jira/secure/attachment/12472293/WW-35791-4.patch
                                Developers Summit 2012
言語非依存のセキュアコーディングルール	

§  入力値検査
  §  パス名は正規化してから検証する
  §  ユーザ入力は無害化してからログに保存
§  ファイル名やファイルパスにはASCII文字
    セットのみを使用する
§  File I/O、NW I/Oの両端で互換性のある文
    字エンコーディングを使う


            Developers Summit 2012
2. JAVA言語特有の
  セキュアコーディング	




       Developers Summit 2012
サブクラスの依存性を保つ(1)	
                                extends
 java.util.Hashtable!
                            java.util.Properties!             extends
        put()!

                                                   java.security.Provider!
      remove()!

                                                           put()!
     entrySet()!

                                                          remove()!

   JDK1.2で追加された	
                                                         entrySet()!
(スーパークラスに対する変更)	




                   entrySet()
                          Developers Summit 2012
サブクラスの依存性を保つ(2)	

 §  スーパークラスに変更を加える場合(コード
     の保守時)、サブクラスの不変条件が侵害さ
     れないよう考慮する




         Developers Summit 2012
ボクシングとアンボクシングに注意(1)	

 Q. このコードの問題は?

 HashSet<Short> s = new HashSet<Short>();!
 for(short i=0; i<100;i++) {!
     s.add(i);!
     s.remove(i - 1);!
 }	




              Developers Summit 2012
ボクシングとアンボクシングに注意(2)	

 修正例:
 HashSet<Short> s = new HashSet<Short>();!
 for(short i=0; i<100;i++) {!
     s.add(i);!
     s.remove((short)(i – 1));!
 }	




              Developers Summit 2012
条件演算子 ? :        (1)	


Q. System.out.println()は何を出力する?	

char alpha = ‘A’;!
int i = 0;!
System.out.println(true ? alpha : 0);!       A	
System.out.println(true ? alpha : 65536);!   65	
System.out.println(true ? alpha : i);	
      65	



                Developers Summit 2012
条件演算子 ? :                    (2)	
char alpha = ‘A’;!
int i = 0;!
System.out.println(true ? alpha : 0);!
System.out.println(true ? alpha : 65536);!
System.out.println(true ? alpha : i);	



§  型の評価はけっこう複雑
  §  alphaの型はchar型(符号無し16ビット)
  §  問題は3番目の式の型
      §  0: char型で表現可能な定数式→char
      §  65536: charの最大値より1だけ大きい→二項格上げの
          結果intに
      §  i: 二項格上げの結果intに

                            Developers Summit 2012
Java/Androidでも整数オーバーフロー(1)	
mezzofanti/AssetsManager.java:!
                                                 問題のあるコード	
//@return the free space on sdcard in bytes!
public static long GetFreeSpaceB() {!
    try {!
       String storageDirectory =!
     Environment.getExternalStorageDirectory().toString();!
       StatFs stat = new StatFs(storageDirectory);!
       return stat.getAvailableBlocks() * stat.getBlockSize();!
    }!
    catch (Exception ex) {!
       return -1;!
    }!
}	



                        Developers Summit 2012
Java/Androidでも整数オーバーフロー(2)	
(修正後) !
return (long) stat.getAvailableBlocks() * stat.getBlockSize();
      "!

§  StatFsクラスのgetAvailableBlocks()と
    getBlockSize()はintを返す!
   §  式の値はint!
   §  intの最大値は2,147,483,647(およそ2GB)!
   §  2GB以上のSDカードを指すとアプリが起動しなかった!


§  long幅にキャストして演算する!

                      Developers Summit 2012
言語仕様は意外に知らないポイントがある	

§  コードを見て直感的に想像するプログラム
    の動作と、言語仕様上の動作が異なるケー
    スが少なくない

§  セキュリティに限らず、プログラマの意図通
    り正しく動くプログラムを書くために必須の
    知識



        Developers Summit 2012
3. APIやプラットフォーム固有の
  セキュアコーディング
  〜ANDROIDアプリ編	



       Developers Summit 2012
Androidアプリの脆弱性事例(1)	
問題	
 不適切なファイルパーミッション	
脅威	
 ユーザがキー入力したプライバシー情報等、センシティブな情報を攻撃者に盗ま
     れる
原因	
 •  ユーザのキー入力は sqlite データベースファイル X と Y に平文で保存される。
        これらのファイルのパーミッションが他のアプリから読取り可能に設定されてい
        る。
     •  サードパーティ製ライブラリの中でデフォルトのパーミション
        (OPEN_READWRITE) でSQLiteのデータベースファイルを作成しており、そ
        れをそのまま使用しているのが原因。

       #ls –al /data/data/com.XXX.android.XXXX
       drwxr-xr-x   1 10119    10119     2048 Aug   29   12:20   .
       drwxrwx--x   1 1000      1000     2048 Aug   29   12:19   ..
       drwxrwx--x   1 10119    10119     2048 Aug   29   12:20   cache
       drwxrwx--x   1 10119    10119     2048 Aug   29   12:20   databases
       drwxrwx--x   1 10119    10119     2048 Aug   29   12:20   files
       drwxr-xr-x   1 1000      1000     2048 Aug   29   12:19   lib
       -rw-r--r--   1 10119    10119     5120 Aug   29   12:20   X
       -rw-r--r--   1 10119    10119     5120 Aug   29   12:20   Y	



                           Developers Summit 2012
Androidアプリの脆弱性事例(1)	

 §  SQLiteDatabase.openOrCreateDatabaseで指定
  できるパーミションはすべてworld redable!	
   §  サードパーティ製ライブラリはこちらを使っていた	

 §  android.database.sqlite.SQLiteOpenHelper
     クラスのgetWritableDatabaseを呼び出すと、	
   §  android.content.Context.openOrCreateDatabaseを呼んでく
       れる!
   §  パーミッションを細かく設定できる(mode_privateとか)!




                  Developers Summit 2012
Androidアプリの脆弱性事例(2)	
問題	
 ContentProviderの実装不備によるディレクトリトラバーサル	
原因	
 Uriクラスは基本的に入力値検査しない。そのため、無効な入力が行われても、
     例外をスローせず、ゴミデータを返す。
脅威	
 Uriオブジェクトは,URIを「/」でsegmentに分割し、各segmentをURLデコードす
     る。攻撃者はURIにURLエンコードした文字列を含めることで、デコードされた結
     果生成される文字列をコントロールできる。

public ParceFileDescriptor openFile(Uri uri, String mode) {!
  File file = new File("/mnt/sdcard/XXX/", uri.getLastPathSegment()):!
!
      return ParceFileDescriptor.open(file, ParceFileDescriptor.MODE_READ_ONLY);!
}	



                                      public abstract String getLastPathSegment()!

                                      Returns
                                         the decoded last segment or null if the path is empty	


                                Developers Summit 2012
Androidアプリの脆弱性事例(3)	
// getPathSegments()メソッドの実装から抜粋!
!                                         pathを取得	
2090    String path = getEncoded();!
2091    if (path == null) {!
2092        return pathSegments = PathSegments.EMPTY;!
2093    }!
2094!
2095    PathSegmentsBuilder segmentBuilder = new
PathSegmentsBuilder();!
2096!                                      pathから先頭の/を探す
2097    int previous = 0;!
2098    int current;!
2099    while ((current = path.indexOf('/', previous)) > -1) {!
2100        // This check keeps us from adding a segment if the path
starts!
2101        // '/' and an empty segment for "//".!
2102        if (previous < current) {!             pathを分割してデコード
2103            String decodedSegment!
2104                    = decode(path.substring(previous, current));!
2105            segmentBuilder.add(decodedSegment);!
2106        }!
2107        previous = current + 1;!
2108    }!
                             プラットフォーム側の問題とも言える…	
                         Developers Summit 2012
セキュアコーディングの実践	




      Developers Summit 2012
Java/Androidプログラマに求められる資質	

Java セキュアコーディング CERT/Oracle版

 1. 言語非依存の注意点

 2. Java言語特有の注意点


        +	
                            サポート	

                                   コード解析ツール
 3. APIやプラットフォーム固有の
   セキュアコーディングテクニック
          Developers Summit 2012
Javaセキュアコーディングスタンダード
CERT/Oracle版	
 https://www.jpcert.or.jp/java-rules/	




              Developers Summit 2012
Javaセキュアコーディングスタンダード
を活用するメリット	

 §  Java言語自体の理解が深まる

 §  コード例に学ぶ

 §  コード保守の負荷低減、品質安定、レビュー
     短縮	



          Developers Summit 2012
[宣伝1]
Androidセキュアコーディングセミナー	
 §  日時:3月14日 13:00〜19:00 @ 翔泳社
 §  タイトル『Androidセキュアコーディングセミナー〜
     安全なアプリ開発のための基礎知識』
   §  Androidセキュリティー概論から実機を使ったセキュリ
       ティコードレビューまで
   §  脆弱性を作り込まないテクニック教えます!
   §  初回限定35,000円(税込36,750円)	
 §  お申込みは、CodeZineのHPで!
       http://codezine.jp/seminar/

               Developers Summit 2012
[宣伝2]
出張セミナーやってます	
 §  C/C++, Javaのセキュアコーディング
  §  [実績] 大手家電メーカー、ゲームメーカー
  §  [時間、内容] ご相談に柔軟に応じます!
  §  全国どこへでも


 §  お問い合わせ、ご用命は
  §  セキュアコーディング担当:佐藤まで
  §  secure-coding@jpcert.or.jp	



              Developers Summit 2012
一緒に安全なアプリ開発に
  取り組みましょう!	




    Developers Summit 2012
ご清聴ありがとうございました	




    Q&A	

    Developers Summit 2012

Java/Androidセキュアコーディング