LINE Bug Bounty Programに参加した。脆弱性はプログラミングに関する知識でしょう。
利用規約の第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タグが動作する。
<script>
とか<img src=x onnerror=???>
とか試したけど動かず、とりあえずHTMLタグが動作すると言って報告したけど、ダメだった。装飾用のタグのみ有効になっているとのこと。
日程調整
普通にLINEクライアントを操作すると、次のことができる。
- 誰でもイベント名や説明を編集できる
- 誰でも日程を追加できる(ただし、未来の日程のみ)
- イベントを作成したユーザーはイベントの削除ができる
APIを直接叩くと、日程の削除ができた。過去の日程を追加することもできた。これによって嫌がらせができる。日程を削除し100年前とかの日程を追加すると、日程の選択が事実上不可能になる(中央の図)。日程選択のカレンダーが1900年の月を表示するので、ひたすら次の月を連打しないと、現在の日程が追加できない。
また、全ての日程を削除すると、サーバー側でエラーになりイベントには一切アクセスできなくなる(右の図)。イベントを削除できるのは作成したユーザーだけなのに、それ以外のユーザーが日程を削除してイベントを使えなくできるのは良くない。
ということも書いて報告したけど、イベントのURLが秘密の情報で、URLを知っているユーザーが編集可能なのは仕様らしい。
サーバーや開発者の情報の漏洩
細々と。
LINEギフトのクレジットカード登録APIに0000000000000000
を投げると次の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が入っていて、覗いてみたら、
<h1 class="mdCMN01Ttl">○○さんへ</h1>
<p class="mdCMN01Desc">JSONレスポンスのredirect_toに自動遷移して下さい。゚(゚∩´﹏`∩゚)゚。</p>
となぜかHTML中で業務連絡がされていたw
日程調整の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)を送っている。スタンプは何個かセットで売られていて、これがパッケージ。例えば、「しゃべる ごちうさスタンプ」とか。スタンプのIDはパッケージの中だけで一意なのではなく、全てのスタンプの中で一意なので、実はスタンプのIDだけでも事足りる。「しゃべる ごちうさスタンプ」のパッケージIDは5033で、「私いらない子だぁ!!」のIDは7115472。下記のメッセージをLINEのサーバーに送ると相手にスタンプが届く。
Message(
to = targetId,
contentType = ContentType.STICKER,
contentMetadata = {
"STKOPT": "S",
"STKVER": "1",
"STKID": "7115472",
"STKPKGID": "5033",
},
))
では、このIDを適当な数字にすると、買っていないスタンプを送れるのでは?と考えたが、そんなに甘くは無かった。LINEのサーバーで、スタンプのIDとパッケージのIDについて、送信者が所有しているものなのかどうかのチェックが行われる。
「しゃべる ごちうさスタンプ」を持っていない人が「私いらない子だぁ!!」を送る方法は次の通り。
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ドルの「課金をバイパスし、アイテムを購入可能」に準ずる扱いにならないかなと期待したものの、脆弱性の深刻性や新規性に基づき、脆弱性とは認定されなかったし、社内でも把握済みとのことだった。残念。
不正なURL
Android版のLINEユーザーに対して、line://ch/1412248049/"
(最後は"
)というURLを送り、相手がこのURLをクリックするとLINE(メッセージを見ているプロセスではなく別のプロセス?)が落ちる。端末での任意コード実行2万ドルか???と一瞬心が躍ったけど、そんなことはなかった。DDMSでログを見たところ、URLに不正な文字が含まれるという例外が飛んでいただけだった。line://ch/1412248049/
から始まるURLは日程調整のURLに変換される。パスの部分はそのまま使われるので、ここに"
が含まれると、そのまま"
を含んだURLを開こうとしてしまうとかそんな感じなのではなかろうか。深刻性や新規性に基づき(ry