Slide 1

Slide 1 text

アプリに潜む脆弱性 - LINEの場合 - Tamaki Hidetsugu / @r_ralph_h Software Engineer @ LINE Corporation LINE Developer Meetup # 2020/04/28

Slide 2

Slide 2 text

自己紹介 Tamaki Hidetsugu (@r_ralph_h) • LINE Android のチャット周りの担当 • 2018/4 ~ • line/apng-drawable • line/feature-flag-android

Slide 3

Slide 3 text

目次 1. このセッションについて 2. 脆弱性とは 3. LINEにおける脆弱性対策 4. LINE Android にあった脆弱性の紹介 5. まとめ

Slide 4

Slide 4 text

目次 1. このセッションについて 2. 脆弱性とは 3. LINEにおける脆弱性対策 4. LINE Android にあった脆弱性の紹介 5. まとめ

Slide 5

Slide 5 text

このセッションについて • 話すこと LINE Androidアプリにあった脆弱性の紹介 • 話さないこと アプリに脆弱性を含めないための一般的なアドバイス 「あぁ~なるほど~」「へぇ~」みたいな感じで聞いてください

Slide 6

Slide 6 text

目次 1. このセッションについて 2. 脆弱性とは 3. LINEにおける脆弱性対策 4. LINE Android にあった脆弱性の紹介 5. まとめ

Slide 7

Slide 7 text

脆弱性とは 脆弱性(ぜいじゃくせい)とは、コンピュータのOSやソフト ウェアにおいて、プログラムの不具合や設計上のミスが原因と なって発生した情報セキュリティ上の欠陥 https://www.soumu.go.jp/main_sosiki/joho_tsusin/security/basic/risk/11.html 他のプラットフォーム上のアプリと同じように対策が必要になる。

Slide 8

Slide 8 text

目次 1. このセッションについて 2. 脆弱性とは 3. LINEにおける脆弱性対策 4. LINE Android にあった脆弱性の紹介 5. まとめ

Slide 9

Slide 9 text

LINEにおける脆弱性対策 • PRレビューなどによる相互のチェック • 専門のチームによるレビュー • API設計 • 実装コードのチェック • ステージング環境でのチェック • 社外報告者からの報告のチェック 1. 社内でのチェック

Slide 10

Slide 10 text

LINEにおける脆弱性対策 • LINE Security Bug Bounty Program を実施 • 有効な脆弱性報告に対し、報奨金を支払う • https://hackerone.com/line • LINE Android は Google Play Security Reward Program の対象 • Google Play上の著名なアプリに対して対象 • https://www.google.com/about/appsecurity/play-rewards/ 2. 社外報告者による報告

Slide 11

Slide 11 text

LINEにおける脆弱性対策 • 発見経路(社内・社外)に関わらず、重大な脆弱性は IPA や JPCERT/CC と連携してアナウンスやCVEの発番をしている • CVE: 共通脆弱性識別子 https://cve.mitre.org/index.html • HackerOne 上で、修正された脆弱性のレポートも順次公開 3. 重大な脆弱性の公表

Slide 12

Slide 12 text

目次 1. このセッションについて 2. 脆弱性とは 3. LINEにおける脆弱性対策 4. LINE Android にあった脆弱性の紹介 5. まとめ

Slide 13

Slide 13 text

LINE Android にあった脆弱性の紹介 • ここで紹介する脆弱性はすべて修正済みのものです。 • 各々の紹介ページに修正された年を併記しています。 注意点

Slide 14

Slide 14 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 15

Slide 15 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 16

Slide 16 text

#1 SQL Injection SQLクエリの生成時に不正なクエリを発行できる脆弱性 val input = "t' OR 't' = 't" val sql = "SELECT * FROM users WHERE name = '${input}';” db.rawQuery(sql, null) // 実際に実行されるSQL文 SELECT * FROM users WHERE name = 't' OR 't' = 't';

Slide 17

Slide 17 text

#1 SQL Injection • 不正なメッセージによってSQLiが起こせる脆弱性 • 非公式なクライアントから送信可能であった • アプリのクラッシュを引き起こすことが可能 • BugBounty 経由での報告 • 2018年に修正 概要

Slide 18

Slide 18 text

#1 SQL Injection • SQLクエリの生成コードに問題があった • 「?」によるプレースホルダー機能を使用していなかった • サーバー側でのバリデーションがなかった • リクエストの値をそのまま別ユーザーに送付するものだった 原因 val whereClause = "id = '${messageMetadata.id}'"

Slide 19

Slide 19 text

#1 SQL Injection • SQLiteDatabaseクラスのプレースホルダーを使用する • Room等のフレームワークを使用する 対策 @Query("SELECT * FROM users WHERE id = :id") fun getUser(id: String): User val selection = "id = ?" db.query(table, selection, arrayOf(id))

Slide 20

Slide 20 text

#1 SQL Injection • サーバー側でのバリデーションを行う 対策

Slide 21

Slide 21 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 22

Slide 22 text

#2 SQLite Journal Mode • トランザクション中の操作を管理するための方法 • WAL • トランザクション開始~終了までを「-shm」ファイルへ、コミット時 に「-wal」ファイルに、closeしたときに本体へ書き込む • DELETE • トランザクション開始~終了までを「-journal」ファイルへ、コミット 時に本体へ書き込む • Journalファイルはコミット時に削除する PRAGMA journal_mode=DELETE

Slide 23

Slide 23 text

#2 SQLite Journal Mode • 「送信取消」をしたメッセージの内容がDB(journalファイル) に残ってしまう • Rootedなデバイスなどでは内容を読み取られる危険 • 社内からの報告 • 2018年に修正 概要

Slide 24

Slide 24 text

#2 SQLite Journal Mode • Android 4.1.1より、デフォルトのモードがPERSISTになっていた • DELETEとほぼ同じ(トランザクション中はjournalファイル、コ ミット時に本体に反映)だが、journalファイルを削除しない 原因

Slide 25

Slide 25 text

#2 SQLite Journal Mode • 明示的にDELETEモードにする • パフォーマンスの問題もあるので、「消さなければいけない」 などの理由がない限りはやらないほうが吉 対策 db.rawQuery("PRAGMA journal_mode=DELETE", null)

Slide 26

Slide 26 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 27

Slide 27 text

#3 WebViewからのリソースアクセス • 中間者攻撃により、WebViewのリソースの差し替えが可能 • JavaScript経由で、アプリ内のデータの盗聴、書き換えが可能 • JPCERT/CC および IPA からの報告、BugBounty 経由での報告 • 2015年に修正 • 公式サイトでも脆弱性の修正の告知を行った • http://official-blog.line.me/ja/archives/24809761.html 概要

Slide 28

Slide 28 text

#3 WebViewからのリソースアクセス • WebView上で、HTTPなURLのページを読み込んでいた • 利用規約のページなど • WebView上のJavaScript機能が有効であった • JavaScript上からCordovaのAPIを呼ぶためのブリッジがあった 原因

Slide 29

Slide 29 text

#3 WebViewからのリソースアクセス • 読み込むリソースのHTTPS化 • どうしても難しい場合は、外部ブラウザで開くようにする • Android 9からはHTTPSが基本に • WebViewのJavaScript機能の無効化 • 不必要なCordovaのプラグインの削除 対策 webview.settings.isJavaScriptEnabled = false

Slide 30

Slide 30 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 31

Slide 31 text

#4 書換可能なファイルでのデバッグフラグ • 特定のモジュールのログを出すためのフラグが書換え可能に なっていた • IDなどのデータがLogcatのログ上に出力されてしまっていた • BugBounty 経由での報告 • 2018年に修正 概要

Slide 32

Slide 32 text

#4 書換可能なファイルでのデバッグフラグ • /sdcard 下のファイルに設定ファイルが置かれていた • テスト目的に書き換えが可能になっていた • Releaseビルドでも書き換えが可能だった 原因 foo.key=alpha

Slide 33

Slide 33 text

#4 書換可能なファイルでのデバッグフラグ • フラグを書き換え可能な状態にしない • BuildConfig と productFlavor/buildType による制御 • 書換えがどうしても必要な場合はReleaseビルドで無効になるよ うにする • productFlavor/buildType による制御 対策 val fooFlag = if (BuildConfig.DEBUG) { // load from file } else { false }

Slide 34

Slide 34 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 35

Slide 35 text

#5 TextViewでのHTMLタグ • ユーザー名を含んだテキストを表示するTextView • 「○○さんがあなたを招待しています。」 • HTMLタグが含まれたユーザー名が来ると装飾が適用されてしまう • TextViewで使えるタグにはないが、見た目を変更できる • 社内からの報告 • 2018年に修正 概要 <s>ユーザー名 ↓ ユーザー名さんがあなたを招待しています。

Slide 36

Slide 36 text

#5 TextViewでのHTMLタグ • エスケープせずにそのまま挿入していた 原因 getString(R.string.invited, inviterName)

Slide 37

Slide 37 text

#5 TextViewでのHTMLタグ • 特殊文字をエスケープする 対策 val escapedInviterName = inviterName .replace("<", "<") .replace(">", ">") // snip getString(R.string.invited, escapedInviterName)

Slide 38

Slide 38 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 39

Slide 39 text

#6 双方向テキストによるリンク偽装 • トークルーム内で送信できるリンク • 双方向テキスト文字による偽装が可能だった e.g. U+202E: Right to Left override / 強制的に左向きテキスト • 見た目のリンクとは別のページを開かせることができる • BugBounty経由での報告 • 2020年に修正 概要 example.com/pix[U+202E]gpj.apk ↓ example.com/pixkpa.jpg

Slide 40

Slide 40 text

#6 双方向テキストによるリンク偽装 • リンクをテキスト内から抽出するためのRegexが不十分だった • 「(」などを正常に処理するためにカスタムのリンク抽出クラスを作成 していた 原因

Slide 41

Slide 41 text

#6 双方向テキストによるリンク偽装 • androidx-coreのLinkifyCompatを使用する • RFC 3987 (国際化URI) で禁止されている文字を弾いてくれる • 実際には内部で使用している PatternsCompat に定義があるが、こちら は hide API になっている • ただし、リンクを使用して更になにかしたい場合には不向き 対策 LinkifyCompat.addLinks(spannableText)

Slide 42

Slide 42 text

#6 双方向テキストによるリンク偽装 • 双方向テキスト文字を削除、もしくは別の文字で置き換える 対策 example.com/pix[U+202E]gpj.apk ↓ example.com/pix gpj.apk

Slide 43

Slide 43 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 44

Slide 44 text

#7 ネイティブコードでの整数オーバーフロー • 不正な加工がされた画像ファイルを読み込もうとすると整数 オーバーフローが発生する • 高速化のためにC, C++で書かれた画像読み込みのコードに問題 があった • 社内からの報告 • 2019年に修正 概要

Slide 45

Slide 45 text

#7 ネイティブコードでの整数オーバーフロー • 画像ヘッダ内の縦横ピクセル数をもとにバッファサイズを計算 • 極端に大きな数字が埋め込まれた場合に、size_tの範囲を超えてしまう 原因 size_t width = load_width(file); size_t height = load_height(file); size_t bytes_per_pixel = 4; size_t buffer_size = width * height * bytes_per_pixel; byte* buffer = malloc(buffer_size);

Slide 46

Slide 46 text

#7 ネイティブコードでの整数オーバーフロー • 必要なバッファのサイズより小さく作られてしまうため、配列 外にデータを書き込む危険 • 最悪の場合は任意コード実行が起きる 影響 byte* buffer = malloc(buffer_size);

Slide 47

Slide 47 text

#7 ネイティブコードでの整数オーバーフロー • 外部からの値を使用した計算にはオーバーフローのチェックを 行う 対策 if (height > SIZE_MAX / width) { // error return; } size_t image_size = height * width;

Slide 48

Slide 48 text

#7 ネイティブコードでの整数オーバーフロー • LINEが出してるOSSの ApngDrawable を皮切りに発見 https://engineering.linecorp.com/ja/blog/intern-report-line-client/ • LINE 内で使用している他フォーマットのデコーダにも同様の問 題があった • ApngDrawableとLINE Android両方にCVEを発行する事になった • https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6007 • https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6010 余談

Slide 49

Slide 49 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 50

Slide 50 text

#8 パストラバーサル ファイルパスを構成する文字に、特別な意味のある文字を埋め込 むことで、制限外の領域へアクセスさせる攻撃 • "../" : 親ディレクトリへの参照 • Null文字 : 文字列の区切り目 /webroot/../etc/shadow ↓ /etc/shadow

Slide 51

Slide 51 text

#8 パストラバーサル • 別アプリからのファイル共有(ACTION_SEND)を受け取る箇所で の問題 • 受け取ったファイルパスの内容をメッセージとして送信 • 攻撃には悪意のあるアプリのインストールやユーザー操作が必 要 • BugBounty 経由での報告 • 2020年に修正 • 2018年, 2019年にも同様の報告があった 概要

Slide 52

Slide 52 text

#8 パストラバーサル • 外部からの値に対するチェックが行われていなかった • ファイルパスがアプリの内部パスを示していた場合、その内容を送信 してしまう 原因 /sdcard/../data/data/jp.naver.line.android/foo.key

Slide 53

Slide 53 text

#8 パストラバーサル • パスに対するチェックを外部から得られたデータに対して行う • 「..」などのパストラバーサルの可能性のあるパスをDrop • 内部パスを参照するようなパスをDrop • 外部アプリとの境界点を意識する • ACTION_SENDを受け取れるActivity等 • ACTION_GET_CONTENTによるファイルオープン 対策

Slide 54

Slide 54 text

LINE Android にあった脆弱性の紹介 1. SQL Injection 2. SQLite Journal Mode 3. WebViewからのリソースアクセス 4. 書換可能なファイルでのデバッグフラグ 5. TextViewでのHTMLタグ 6. 双方向テキストによるリンク偽装 7. ネイティブコードでの整数オーバーフロー 8. パストラバーサル 9. ZIPファイル関連

Slide 55

Slide 55 text

#9 ZIPファイル関連 • ZIPファイルを扱う処理に問題あった • 内部ストレージの任意のファイルの上書きが可能であった • 社内からの報告 • 2015年に修正 概要

Slide 56

Slide 56 text

#9 ZIPファイル関連 • ZIPファイルをダウンロードし、展開する処理があった • HTTPを使用していたため、中間者攻撃が可能であった • 展開処理にも問題があった • 展開処理には、Java標準のjava.util.zip.ZipInputStream を使用していた 原因

Slide 57

Slide 57 text

#9 ZIPファイル関連 • 不正なZIPファイルに差し替えられた場合 • パストラバーサルによるファイルの書換え • ZIP爆弾による攻撃 ZIP爆弾: ZIPファイルを展開すると膨大なファイルサイズになるように細工 されたZIPファイル 影響

Slide 58

Slide 58 text

#9 ZIPファイル関連 • HTTPSを使用する • ZIPファイルの展開時に、チェックを行うようにする • java.util.zip.ZipInputStream をラップしたZipInputStreamを作成 • getNextEntry()でのパストラバーサルチェック • read()時の展開後のファイルサイズチェック 対策

Slide 59

Slide 59 text

目次 1. このセッションについて 2. 脆弱性とは 3. LINEにおける脆弱性対策 4. LINE Android にあった脆弱性の紹介 5. まとめ

Slide 60

Slide 60 text

まとめ Thank you for the all reporters! 謝辞

Slide 61

Slide 61 text

まとめ • 常に最新版のアプリを使用するようにしてください。 • アップデートには脆弱性の修正も含まれます。 LINEからのお願い

Slide 62

Slide 62 text

まとめ • きちんと脆弱性のチェックを行いましょう • 社内でのチェック • Bounty Programのような社外からの報告 • 報告を受けた脆弱性はきちんと直しましょう • サービスの安定運用の妨げになったり、何より情報漏えい等、ユー ザーが被害を被る可能性があります。