@shin1x1
2016/02/27 TwilioJP-UG大阪&AWScean合同勉強会
Twilio と Web アプリ

連携におけるセキュリティ
https://github.com/shin1x1/twilio-api-security-demo
TwilioとWebアプリの連携
サンプルアプリケーション
(c) 2016 Masashi Shinbara @shin1x1
• 会員向けポイント管理システム
• 電話をかけると現在のポイントが聞ける
• 電話番号で認証
(c) 2016 Masashi Shinbara @shin1x1
電話をかける
図図 - twilio
図図 - twilio
Twilio Webサーバ会員
090-xxxx-xxxx
(c) 2016 Masashi Shinbara @shin1x1
電話番号が送られる
図図 - twilio
図図 - twilio
HTTPリクエスト

From: 090-xxxx-xxxx
(発信元電話番号)
(c) 2016 Masashi Shinbara @shin1x1
会員認証
図図 - twilio
図図 - twilio
090-xxx-xxx で DB を参照して
会員を特定する
(c) 2016 Masashi Shinbara @shin1x1
情報をXMLで返す
図図 - twilio
図図 - twilio
TwiML(XML)を返す
(c) 2016 Masashi Shinbara @shin1x1
情報をTwiMLで返す
図図 - twilio
図図 - twilio
TwiML(XML)を返す
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say voice="woman" language="ja-JP">

鈴木さんのポイントは 50 ポイントです。
</Say>
</Response>
(c) 2016 Masashi Shinbara @shin1x1
音声を流す
図図 - twilio
図図 - twilio
音声再生
(c) 2016 Masashi Shinbara @shin1x1
デモ
(c) 2016 Masashi Shinbara @shin1x1
起こりうる問題
(c) 2016 Masashi Shinbara @shin1x1
HTTPの世界
図図 - twilio
図図 - twilio
Twilio Webサーバ会員
(c) 2016 Masashi Shinbara @shin1x1
偽装リクエスト
図図 - twilio
図図 - twilio
電話番号を
POST
(c) 2016 Masashi Shinbara @shin1x1
偽装リクエスト
図図 - twilio
図図 - twilio
TwiMLを
取得
(c) 2016 Masashi Shinbara @shin1x1
偽装リクエスト
図図 - twilio
図図 - twilio
Twilio Webサーバ会員
$ curl -d "From=%2B819012345678"

https://example.com/api/calling
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say voice="woman" language="ja-JP">

田中さんのポイントは 100 ポイントです。
</Say>
</Response>
(c) 2016 Masashi Shinbara @shin1x1
Twilio を偽ったリクエスト
•偽装したリクエストをWebアプリに送信
•情報取得、操作などの不正利用の可能性
(c) 2016 Masashi Shinbara @shin1x1
対策
偽装リクエスト対策
(c) 2016 Masashi Shinbara @shin1x1
1. 通信経路の暗号化
2. 通信元を制限
3. リクエストを検証
(c) 2016 Masashi Shinbara @shin1x1
1. 通信経路の暗号化
• HTTPS を利用する
• 自己署名の証明書は NG
• TLS を利用(SSLv3 は、廃止予定)
(c) 2016 Masashi Shinbara @shin1x1
Webアプリケーションのエンドポイント
https:// にする
(c) 2016 Masashi Shinbara @shin1x1
2. 通信元を制限
• HTTP Basic認証 / Digest認証
• ユーザ、パスワードを URL に含める
• https://user:pass@example.com/
(c) 2016 Masashi Shinbara @shin1x1
IPアドレスによる制限は?
https://www.twilio.com/help/faq/twilio-basics/which-ip-addresses-will-twilios-requests-come-
from
• Twilio の送信元 IP アドレスは非公開
• 代わりにリクエストの検証を行う
• どうしても必要なら相談
(c) 2016 Masashi Shinbara @shin1x1
3. リクエストの検証
・Twilio からのリクエストであることを確認
• 妥当であれば処理を実行
• そうでなければ処理を中断(エラー)
(c) 2016 Masashi Shinbara @shin1x1
HMAC-SHA1署名による検証
・ X-Twilio-Signatureヘッダ
• 所定のアルゴリズムで署名を算出
• 上記、2つを比較して合致すれば ok
X-Twilio-Signatureヘッダ
X-Twilio-Signature: +sndfa0paQ+m2P0PZ4U/2lnLkHw=
署名算出
・URL - https://example.com/calling
・POSTパラメータ(キーでソート)

Key2=value2
Key1=value1
From=+819012345678
https://example.com/calling

From+819012345678Key1value1Key2value2
署名算出
・AuthTokenをキーにして、HMAC-SHA1署名
・base64でエンコード
+sndfa0paQ+m2P0PZ4U/2lnLkHw=
https://example.com/calling

Key1value1Key2value2From+819012345678
署名が一致するか
生成した署名 +sndfa0paQ+m2P0PZ4U/2lnLkHw=
X-Twilio-Signature: +sndfa0paQ+m2P0PZ4U/2lnLkHw=
合致するので、Twilioからのリクエストとみなす
twilio/sdk による検証
$validator = new Services_Twilio_RequestValidator($authToken);



// ヘッダから署名取得
$signature = $request->header('X-Twilio-Signature');



// URL 取得
Request::setTrustedProxies([$request->getClientIp()]);

$url = $request->getUri();



// POST パラメータ取得
$postParameters = $request->input();



// 署名検証
if (!$validator->validate($signature, $url, $postParameters)) {

// OK

} else {

// NG

}
まとめ
(c) 2016 Masashi Shinbara @shin1x1
•Twilio と Web アプリケーションは

HTTP(S) で連携
•偽装リクエストが送信されることを意識
•Twilio 公式ドキュメントを参考に
https://jp.twilio.com/docs/api/security

日本語消えたスライド