LINE Bug Bounty Programに報告して認定されなかった脆弱性（1）

[LINE Bug Bounty Program](https://linecorp.com/ja/security/bugbounty/)に参加した。脆弱性は[プログラミングに関する知識](http://qiita.com/about)でしょう。

[利用規約](https://static.line.naver.jp/_1/LINE-bug-bounty/pdf/LINE_Bug_Bounty_2015.pdf)の第9条によって、LINEが公表するまで（場合によっては公表した後も）脆弱性を公開することは禁止されているけれど、脆弱性と認定されなかった場合は適用対象外らしい。LINEに確認した。審査不可の通知のメールは「今回の脆弱性報告対象ではありません」というそっけない感じだったけど、認定されなかった理由も教えてくれた。ありがとうございます。

ということで、認定されなかった脆弱性を紹介する。

### グループチャットで誰が既読にしたかを知ることができる
LINEのグループチャットでは、既読の人数のみが表示される。ユーザーは読んだのが誰かは分からないという想定で使っているはず。Aさんは誰が既読にしたか分からないという想定でLINEを使っているのに、Bさんが何らかの手段で誰が既読にしたかを知ることができると、友情にヒビが入るかもしれない。

実は、LINEのサーバーから飛んでくる既読通知にはユーザーIDも載っていて、誰が既読にしたかを知ることができる。ということで報告したが、「意図している仕様」とのこと。

### SDカードに平文でファイルを保存する問題
AndroidではSDカードに保存したファイルは他のアプリからも読むことができる。LINEはスタンプや受信したファイルをSDカードに保存していて、SDカードを読むことで下記のような情報を知ることができる。

- ユーザーが受信したスタンプ。ただし、最初の1回のみ。スタンプの組み合わせで秘密の情報をやりとりしていたら、悪意のあるアプリに奪取される危険性がある。まあ、スタンプをそんな目的には使わないでしょう。
- ユーザーが受信したファイル。SDカードにそのまま保存されるので。メッセージそのものに比べると、ファイルの保護は弱いから、重要なファイルはLINEで送らないほうが良い。
- ファイルを送信したユーザーのID。受信したファイルは送信者のID別のディレクトリに保存されるので、送信者のIDを知ることができる。このIDは、友達追加などで使うものではなく、LINEが内部的に使用している、`u`に続く32桁の16進数。

これも「意図した仕様」だった。

### LINEギフトのメッセージ
LINEギフトの脆弱性を探すために、自分で自分にソフトクリームやらケーキやらを贈った。ファミマのソフトクリームを初めて食べたけど、美味しかった。

ギフトを贈るときにメッセージを入力できる。ここで入力したHTMLタグが動作する。

<img width="240" src="https://qiita-image-store.s3.amazonaws.com/0/25276/0bf8e2d1-5d03-9513-c112-fd14456f044e.png"> <img width="240" src="https://qiita-image-store.s3.amazonaws.com/0/25276/fba699a1-7eb3-7359-bcc0-dfe0bf5e67c5.png">

`<script>`とか`<img src=x onnerror=???>`とか試したけど動かず、とりあえずHTMLタグが動作すると言って報告したけど、ダメだった。装飾用のタグのみ有効になっているとのこと。

### 日程調整
普通にLINEクライアントを操作すると、次のことができる。

- 誰でもイベント名や説明を編集できる
- 誰でも日程を追加できる（ただし、未来の日程のみ）
- イベントを作成したユーザーはイベントの削除ができる

APIを直接叩くと、日程の削除ができた。過去の日程を追加することもできた。これによって嫌がらせができる。日程を削除し100年前とかの日程を追加すると、日程の選択が事実上不可能になる（中央の図）。日程選択のカレンダーが1900年の月を表示するので、ひたすら次の月を連打しないと、現在の日程が追加できない。

また、全ての日程を削除すると、サーバー側でエラーになりイベントには一切アクセスできなくなる（右の図）。イベントを削除できるのは作成したユーザーだけなのに、それ以外のユーザーが日程を削除してイベントを使えなくできるのは良くない。

ということも書いて報告したけど、イベントのURLが秘密の情報で、URLを知っているユーザーが編集可能なのは仕様らしい。

<img width="240" alt="写真 2015-10-28 5 23 31.png" src="https://qiita-image-store.s3.amazonaws.com/0/25276/25a65c77-57ae-e3af-cfc8-963ee3d21144.png"> <img width="240" alt="写真 2015-09-21 15 59 41.png" src="https://qiita-image-store.s3.amazonaws.com/0/25276/60b8ad1b-bcbb-29ea-3698-19350a9094f6.png"> <img width="240" alt="写真 2015-09-21 15 59 52.png" src="https://qiita-image-store.s3.amazonaws.com/0/25276/6293d45c-e5eb-7f48-4743-20ab265f7374.png">

### サーバーや開発者の情報の漏洩
細々と。

LINEギフトのクレジットカード登録APIに`0000000000000000`を投げると次のJSONが返ってくる。

```json
{"error_description":"\u30ab\u30fc\u30c9\u306e\u6709\u52b9\u671f\u9650\u306b\u8aa4\u308a\u304c\u3042\u308a\u307e\u3059","error":"invalid_request",
"debug_description":"Invalid card brand. at /home/????-dev/???????????/???/??????????/?/Card.pm line ??.","code":400}
```

念のために一部伏せ字にした。`-dev`とはいったい……。拡張子がpmはperlなのだろうか？　書いていて気が付いたけど、error_descriptionは「カードの有効期限に誤りがあります」で整合性が無いな……。

LINEギフトでサーバーとやりとりしているJSONの中のbodyというパラメタにはHTMLが入っていて、覗いてみたら、

```html
<h1 class="mdCMN01Ttl">○○さんへ</h1>
<p class="mdCMN01Desc">JSONレスポンスのredirect_toに自動遷移して下さい。ﾟ(ﾟ∩´﹏`∩ﾟ)ﾟ。</p>
```

となぜかHTML中で業務連絡がされていたw

日程調整のHTMLに下記の部分があった。

```html
<script src="https://scdn.line-apps.com/n/line_schedule_sp/js/lc.line.schedule.sp.event.main_1442371340.js"></script>
<!-- <script src="http://10.???.???.???/line_schedule_sp/dist/lc.line.schedule.sp.event.main.js"></script> -->
```

一応伏せ字。この10.???.???.???は、scdn.line-apps.comの開発環境版だろうか？

深刻性や新規性に基づき、脆弱性ではないとのこと。ですよね。

### 未購入のスタンプの使用
この脆弱性（？）が一番面白い。

LINEのスタンプは実際に画像や音声を送るわけではなく、スタンプのID（STKID）とパッケージのID（STKPKGID）を送っている。スタンプは何個かセットで売られていて、これがパッケージ。例えば、「[しゃべる ごちうさスタンプ](https://store.line.me/stickershop/product/5033/ja)」とか。スタンプのIDはパッケージの中だけで一意なのではなく、全てのスタンプの中で一意なので、実はスタンプのIDだけでも事足りる。「しゃべる ごちうさスタンプ」のパッケージIDは5033で、「私いらない子だぁ!!」のIDは7115472。下記のメッセージをLINEのサーバーに送ると相手にスタンプが届く。

```py
Message(
    to = targetId,
    contentType = ContentType.STICKER,
    contentMetadata = {
        "STKOPT": "S",
        "STKVER": "1",
        "STKID": "7115472",
        "STKPKGID": "5033",
    },
))
```

では、このIDを適当な数字にすると、買っていないスタンプを送れるのでは？と考えたが、そんなに甘くは無かった。LINEのサーバーで、スタンプのIDとパッケージのIDについて、送信者が所有しているものなのかどうかのチェックが行われる。

「しゃべる ごちうさスタンプ」を持っていない人が「私いらない子だぁ!!」を送る方法は次の通り。

```py
Message(
    to = targetId,
    contentType = ContentType.STICKER,
    contentMetadata = {
        "STKID": "7115472_",
        "STKPKGID": "1",
    },
))
```

パッケージIDの1は「ムーン・ジェームズ」のスタンプ。皆最初から持っているはず。自分が持っているパッケージのIDならば何でもチェックは通る。スタンプのIDは末尾に`_`が付いているのがポイント。数字以外なら何でも良い。LINEサーバーのチェックはブラックリストらしく、こうするとすり抜けられる。Android版のLINEはこのメッセージを受信してもスタンプを表示しないが、iOSのLINEはIDが7115472のスタンプを表示してしまう。ただし、1個だけ制限があって、相手がそのスタンプを事前にダウンロードしている必要がある。相手がスタンプを購入している必要は無く、誰か別の人が相手に対してスタンプを送信していればダウンロードされている。それ以外は、スタンプをクリックすると声が出たり、スタンプ一覧が出たり（買っている場合）、購入画面に遷移したり（買っていない場合）するので、正規に購入されたスタンプとは区別が付かない。

報奨金5,000ドルの「課金をバイパスし、アイテムを購入可能」に準ずる扱いにならないかなと期待したものの、脆弱性の深刻性や新規性に基づき、脆弱性とは認定されなかったし、社内でも把握済みとのことだった。残念。

<img width="240" alt="写真 2015-10-29 0 07 38.png" src="https://qiita-image-store.s3.amazonaws.com/0/25276/04558506-5e39-07df-9704-159fba5529ac.png">

### 不正なURL

Android版のLINEユーザーに対して、`line://ch/1412248049/"`（最後は`"`）というURLを送り、相手がこのURLをクリックするとLINE（メッセージを見ているプロセスではなく別のプロセス？）が落ちる。端末での任意コード実行2万ドルか？？？と一瞬心が躍ったけど、そんなことはなかった。DDMSでログを見たところ、URLに不正な文字が含まれるという例外が飛んでいただけだった。`line://ch/1412248049/`から始まるURLは日程調整のURLに変換される。パスの部分はそのまま使われるので、ここに`"`が含まれると、そのまま`"`を含んだURLを開こうとしてしまうとかそんな感じなのではなかろうか。深刻性や新規性に基づき（ry

<img width="240" src="https://qiita-image-store.s3.amazonaws.com/0/25276/10b923e2-3b58-3315-006b-cdf79fc53a6f.png">