🐈‍⬛

TwilioのLookup APIを使ってSMS Pumping Risk Scoreをみてみた #ヌーラボ真夏のブログリレー2024

2024/07/31に公開

ヌーラボのgillaxです。このブログは、ヌーラバー真夏のブログリレー2024の13日目のブログとして更新しています。

先日、TwilioのLookup APIにおいてSMS Pumping Risk Scoreコアパッケージが一般利用可能となりました。そこで、実際にどのような情報が取得できるのか試してみるとともに、この情報をどのように活用できるかを考察してみました。

SMS Pumping Risk Scoreとは?

Twilioが提供するこのスコアは、Verify Fraud Guardからのシグナル、危険なキャリア、異常な SMSトラフィックパターン、低いコンバージョン率に関連するその他のシグナルなど、Twilioネットワーク全体のデータを基に構築された独自のリスクモデルによって算出されます。

また、このスコアはTwilioのアカウントSIDごとに固有のもので、他のアカウントのトラフィックが影響することはありません。

スコアは0から100の数値で表され、数値が高ければそれだけリスクが高く、SMSポンピング詐欺に利用されている可能性が高い電話番号ということになります。

このスコアを活用することで、SMSポンピング詐欺の被害を未然に防ぐための有効な対策が実現できると(わたしが勝手に)期待しています。
https://www.twilio.com/docs/lookup/v2-api/sms-pumping-risk

Lookup APIの準備

TwilioのLookup APIを利用するにはTwilioアカウントが必要です。Twilioサイトからアカウントを作成したら、TwilioコンソールにログインしてSIDとAuth Tokenを取得しましょう。

あとは、検査したい電話番号です。今回は下記2つを使用します。

  • 私が所有する日本のキャリアの電話番号(A)
  • Twilioが提供するテスト用の電話番号(B)

テスト用の電話番号を利用する際は、テスト用のSIDとAuth Tokenが必要です。Twilioコンソールから取得してください。
https://www.twilio.com/docs/lookup/magic-numbers-for-lookup/testing-sms-pumping-risk-with-magic-numbers

Lookup APIを実行してみる

Lookup APIのベースURLはとてもシンプルです。電話番号はE.164形式で記述する必要があります。

https://lookups.twilio.com/v2/PhoneNumbers/{電話番号}

ベースURLに認証情報をつけてcURLすると、電話番号が有効であるか(E.164形式であるか、プレフィクスや桁数が適切かなど)を示す valid や、フォーマットされた電話番号の情報が取得できます。ちなみに、このAPIには料金は発生しません

私が所有する電話番号(A)で実行してみます。

curl -X GET \
  'https://lookups.twilio.com/v2/PhoneNumbers/+8180XXXXXXXX' \
  -u "$ACCOUNT_SID:$AUTH_TOKEN"

レスポンス:

{
  "call_forwarding": null,
  "caller_name": null,
  "calling_country_code": "81",
  "country_code": "JP",
  "identity_match": null,
  "line_status": null,
  "line_type_intelligence": null,
  "national_format": "080-XXXX-XXXX",
  "phone_number": "+8180XXXXXXXX",
  "phone_number_quality_score": null,
  "pre_fill": null,
  "reassigned_number": null,
  "sim_swap": null,
  "sms_pumping_risk": null,
  "url": "https://lookups.twilio.com/v2/PhoneNumbers/+8180XXXXXXXX",
  "valid": true,
  "validation_errors": []
}
// 見やすいようにjqで整形しています

レスポンスを見る限り、そこまで有益な情報はありませんでした。

続いて、有料データパッケージである 回線種別情報 を取得してみます。

回線種別情報の取得

さきほどのリクエストにクエリパラメータFields=line_type_intelligenceを追加します。このAPIはリクエストごとに $0.008(執筆時点で約¥2) の費用が発生します。

curl -X GET \
  'https://lookups.twilio.com/v2/PhoneNumbers/+8180XXXXXXXX?Fields=line_type_intelligence' \
  -u "$ACCOUNT_SID:$AUTH_TOKEN"

レスポンス:

{
  "call_forwarding": null,
  "caller_name": null,
  "calling_country_code": "81",
  "country_code": "JP",
  "identity_match": null,
  "line_status": null,
  "line_type_intelligence": {
    "carrier_name": "Rakuten Communications",
    "error_code": null,
    "mobile_country_code": "440",
    "mobile_network_code": "11",
    "type": "mobile"
  },
  "national_format": "080-XXXX-XXXX",
  "phone_number": "+8180XXXXXXXX",
  "phone_number_quality_score": null,
  "pre_fill": null,
  "reassigned_number": null,
  "sim_swap": null,
  "sms_pumping_risk": null,
  "url": "https://lookups.twilio.com/v2/PhoneNumbers/+8180XXXXXXXX",
  "valid": true,
  "validation_errors": []
}

さきほどはnullだった line_type_intelligence に値が入ってきました。

  • carrier_name: キャリア名
  • mobile_country_code: MCC
  • mobile_network_code: MNC
  • type: 電話番号のタイプ

また、 type には下記のような値が設定されます。

  • landline: 固定電話番号
  • mobile: 携帯電話番号
  • nonFixedVoip: Google Voiceなど物理デバイスに紐づいていない仮想電話番号
  • tollFree: フリーダイヤル
  • premium: プレミアム・レートの電話番号で通常よりも高い料金を請求する
  • voicemail: ボイスメールサービスに関連する電話番号
  • などなど

この​​回線種別情報を使うと、下記のようなユースケースにおいて配信性を向上するのに役立ちそうです。

  • 2段階認証でのSMS送信であればmobileだけに限定する
  • テレマーケティングやテレアポの対象からpremiumtollFreeは除外する
  • キャリアごとに架電に使用する電話番号を変える

また、身に覚えのない電話やSMSを受信した際もこの情報からキャリアやタイプを割り出せるので、判断の材料にできるかもしれません。

SMS Pumping Risk Scoreの取得

それでは今回の目的である SMS Pumping Risk Score を取得します。

さきほどと同様にクエリパラメータにFields=sms_pumping_riskを追加します。このAPIはリクエストごとに $0.035(執筆時点で約¥5) の費用が発生します。

まずは電話番号(A)で実行してみます。

curl -X GET \
  'https://lookups.twilio.com/v2/PhoneNumbers/+8180XXXXXXXX?Fields=sms_pumping_risk' \
  -u "$ACCOUNT_SID:$AUTH_TOKEN"

レスポンス:

{
  "sms_pumping_risk": {
    "carrier_risk_category": "low",
    "error_code": null,
    "number_blocked": false,
    "number_blocked_date": null,
    "number_blocked_last_3_months": null,
    "sms_pumping_risk_score": 2
  },
}
// sms_pumping_riskだけを抜粋

sms_pumping_riskの各項目:

  • sms_pumping_risk_score: SMSポンピング詐欺に利用されている可能性を0から100までで表した数値
  • carrier_risk_category: リスクスコアに基づくキャリアのリスクカテゴリー。low < mild < moderate < high のいずれか
  • number_blocked: Verify Fraud Guardによって現在ブロックされている場合trueとなる
  • number_blocked_date: Verify Fraud Guardによって直近にブロックされた日付。ISO8601の拡張形式でタイムゾーンはUTCで表記される。ブロックされていない場合はnull
  • number_blocked_last_3_months: 過去3か月間にVerify Fraud Guardによってブロックされていたらtrue。ブロックされていない場合はnull

このことから、私の国内キャリアの電話番号(A)はSMSポンピング詐欺の関与は極めて低いことがわかりました。

次に電話番号(B)を使って、SMS Pumping Risk Scoreが高い場合のレスポンスを確認してみます。こちらはTwilioが指定する固定値がレスポンスされます。

電話番号(B)を使う場合はテスト用のSIDとAuth Tokenで実行します。

curl -X GET \
  'https://lookups.twilio.com/v2/PhoneNumbers/+621234567890?Fields=sms_pumping_risk' \
  -u "$TEST_ACCOUNT_SID:$TEST_AUTH_TOKEN"

レスポンス:

{
  "sms_pumping_risk": {
    "carrier_risk_category": "high",
    "error_code": null,
    "number_blocked": false,
    "number_blocked_date": "2023-07-12T17:03:13Z",
    "number_blocked_last_3_months": true,
    "sms_pumping_risk_score": 44
  },
}
// sms_pumping_riskだけを抜粋

SMS Pumping Risk Scoreの活用

number_blockedについては、自アカウント以外のTwilioアカウントで番号がブロックされている場合も true となります。よって、この場合はSMSを送信しないという判断でよさそうですが、その他の値はどう見ればよいのでしょうか?

リスクを極力避けたいケースであればcarrier_risk_category == "high"ならSMSを送信しないという判断もできるかなと思いました。しかし、リスクが高いキャリアの番号全てを拒否するというのは少々荒いので、やはりsms_pumping_risk_scoreを判断するのが良いと思われます。

Twilioでは、sms_pumping_risk_scoreのスコアを下記に分類しており、一般的なガイドラインを提供しています。

  • 低リスク: 0 - 60
    • SMSを送信しても安全
  • 軽度リスク: 60 - 75
    • 再度リクエストを送信させるか、他の確認手段を追加する
  • 中程度のリスク: 75 - 90
    • リクエストを疑う
  • 高リスク: 90 - 100
    • SMSを送信しない

https://www.twilio.com/docs/lookup/v2-api/sms-pumping-risk#suggested-implementation-logic

SMSポンピング詐欺の場合はBotで大量にリクエストを送信してくることが予想されるので、スコアが軽度や中程度リスクであれば、CAPTCHAテストなどを追加で送信させるようにアプリケーションに組み込むことで悪意あるリクエストのみを弾くことができると思います。

まとめ

今回の検証で、TwilioのSMS Pumping Risk Scoreを詐欺防止にどのように活用できそうかが見えてきました。
具体的には、電話番号ごとのリスクスコアを判断し、リスクの高い番号にはCAPTCHAテストなど追加の確認手続きやメッセージ送信のブロックを行うことで、安全性を高めることができると思います。また、number_blockedを利用して他のTwilioアカウントでブロックされている番号も考慮することで、さらに詐欺リスクを低減することが可能になると感じました。

実際に実装してみる編はまた別の機会に書こうと思います。

Discussion