スマホゲームセキュリティとWhite Box診断のススメ
2017/02/08

グリー株式会社 セキュリティ部
脆弱性診断チーム マネージャー
山村憲和

Copyright © GREE, Inc. All Rights Reserved.

自己紹介
山村憲和（やまむら のりかず）
1998年富士通株式会社入社
・2001年からセキュリティ部門
・主に海外対応2012年 グリー株式会社入社
・プロダクト脆弱性診断（主に自社プロダクト）の診断員
・診断チームのプロジェクトマネジメント

Copyright © GREE, Inc. All Rights Reserved.

アジェンダ1. スマホゲームセキュリティ• ゲームにおける攻撃とは？
• 攻撃パターン１、２、３
2. White Box診断のススメ• グリーの脆弱性診断体制• なぜWhite Box診断なのか• 実際の話
Copyright © GREE, Inc. All Rights Reserved.

１スマホゲームセキュリティ

Copyright © GREE, Inc. All Rights Reserved.

ゲームにおける攻撃とは？

Copyright © GREE, Inc. All Rights Reserved.

ゲームを攻撃する動機• レアカードやレアアイテムをGETしたい• 人より優位に立ちたい• 強くなりたい• お金を掛けたくない• そして楽して簡単に達成したい

チートが最も多い攻撃
Copyright © GREE, Inc. All Rights Reserved.

攻撃パターン１、２、３

Copyright © GREE, Inc. All Rights Reserved.

攻撃パターン１、２、３全体像
パターン１
Webゲーム時代

サーバー
リクエストを攻撃
内部データを攻撃
パターン３
Nativeゲーム時代

レスポンスを攻撃
パターン２
Web  〜～  Native
ゲーム移⾏行行期

Copyright © GREE, Inc. All Rights Reserved.

パターン１：リクエストの改ざん• 勝敗結果、攻撃⼒力力、防御⼒力力、アイテム数• 楽して簡単に⽬目的を達成する• 効果的、⼿手間が最⼩小限• ⽣生産性が⾼高く魅⼒力力的• ここをまずは狙う

Copyright © GREE, Inc. All Rights Reserved.

パターン１:  リクエストの改ざん

結果反映

サーバー

キャラ
回復復

キャラ回復復アイテム選択回復復完了了

送信

１消費

アイテム数  -‐‑‒1

送信

結果反映
Copyright © GREE, Inc. All Rights Reserved.

パターン１:  リクエストの改ざん
サーバー

キャラ
回復復

キャラ回復復-‐‑‒100消費

１消費

アイテム選択結果送信

結果反映
Copyright © GREE, Inc. All Rights Reserved.

パターン１:  リクエストの改ざん
サーバー

キャラ
回復復

キャラ回復復アイテム選択-‐‑‒100消費回復復完了了

アイテム数

１消費

+100

結果送信

結果反映
Copyright © GREE, Inc. All Rights Reserved.

パターン１:  リクエストの改ざん{!

u'ctag': None,!
u'payload': !
{!
u'dataCharacterId': 632, !
u'dataItemId': 399, !

u'dataItemNum': 1!
},!
u'sessionId': None,!
u'uuid': None!
}!
{!

u'ctag': None,!
u'payload': !
{!
u'dataCharacterId': 632, !
u'dataItemId': 399, !

u'dataItemNum': -100!
},!
u'sessionId': None,!
u'uuid': None!
}!
Copyright © GREE, Inc. All Rights Reserved.

パターン１:  リクエストの改ざん!
//リクエストパラメータの取得!
$dataItemNum = $this->getRequest()->getParameter('dataItemNum', 0);!
!

!
//アイテム数の減算処理!
$this->gameClientServiceItem ->insertDataItem($userId,$dataItem['masterItemId"], -$dataItemNum);!
!

!
//バリデーターでマイナス値が排除されていない!
$validateRules[] = array('dataItemNum", 'required", 'int");!
!

Copyright © GREE, Inc. All Rights Reserved.

ステップ１:  リクエストの改ざん• 効果的、⼿手間が最⼩小限• パラメータを変えるだけ• プロキシツール使うだけ• ⽣生産性が⾼高く魅⼒力力的• アイテムを地道に増やすことなく⼀一気に集められる。
• ⾃自分のキャラをいくらでも回復復できる
ブラウザゲーム主流流のころによくあったパターン
Copyright © GREE, Inc. All Rights Reserved.

ステップ１:  リクエストの改ざん• サーバー側でしっかり対策する• データを暗号化してても怠らない• データの正当性の確認• 想定外のデータの排除

Copyright © GREE, Inc. All Rights Reserved.

ステップ１:  リクエストの改ざん//バリデーターでマイナス値を排除する!
$validateRules[] = array('dataItemNum', 'int', 'min' => 1);!
// アイテムデータ所持数の確認!
if ($dataItemNum > $dataItem['num']) {!
ExceptionUtil::ClientException(!
ErrorMessage::ITEM_ENHANCE_ERROR,!
__METHOD__,!
sprintf('DataItem Num Short userId = %s, dataItemId = %s, %s> %s', $userId, $dataItemId, $dataItemNum, $dataItem['num'])!
);!
!

} elseif($dataItemNum < 1) {//マイナス値排除!

ExceptionUtil::ClientException(!
ErrorMessage::ITEM_ENHANCE_ERROR,!
__METHOD__,!
sprintf('Invalid DataItem Num: userId = %s, dataItemId = %s,%s', $userId, $dataItemId, $dataItemNum)!
);!
}!
Copyright © GREE, Inc. All Rights Reserved.

パターン１:  リクエストの改ざん//ログに記録し監視に活用する$this->gameClientServiceCharacter->insertLogCharacterEnhance($userId,$dataCharacterId,$dataItemId,$dataItem['masterItemId'],$dataItem['num'],$dataItem['num'] - $dataItemNum,$dataCharacterBefore['CharacterLevel'],$dataCharacterAfter['CharacterLevel'],$dataCharacterBefore['CharacterExp'],$dataCharacterAfter['CharacterExp']);

Copyright © GREE, Inc. All Rights Reserved.

さらにCopyright © GREE, Inc. All Rights Reserved.

パターン１:  リクエストの改ざん
リクエストデータの改ざん検知の仕組みを導⼊入!
{"ctag":None,"payload":{"dataCharacterId”:632,"dataItemId":399,"dataItemNum": 1},"sessionId":None,"uuid":None}!
!

=> 8cc7277ba0a9c8bf4cfd5420428302a8ddba0f84!
!
!
{"ctag":None,"payload":{"dataCharacterId”:632,"dataItemId":399,"dataItemNum": -100},"sessionId":None,"uuid":None}!
!

=> caf64fea1ac722b0785bba0b182f9ad22f950d92!
!
•

リクエストデータやその他の情報をベースにハッシュを⽣生成、ヘッダにつけてサーバへ送信•

改ざんしても、サーバーでの検証で改ざんが検知できる。

•

攻略略されてしまう現状はあるが、やらないよりはマシ。
Copyright © GREE, Inc. All Rights Reserved.

パターン２：レスポンス改ざん•

ステップ１の攻撃が対策されている場合•

クライアントに送られる攻撃⼒力力、防御⼒力力など•

スマホゲーム（ネイティブ）では効果的•

楽して簡単に⽬目的を達成する•

効果的、⼿手間が最⼩小限•

⽣生産性が⾼高く魅⼒力力的Copyright © GREE, Inc. All Rights Reserved.

パターン2:  レスポンスの改ざん

結果反映

サーバー

ゲーム
データ
⾃自分
バトル開始

WinorLose

敵キャラ
データ取得

戦闘

結果反映
Copyright © GREE, Inc. All Rights Reserved.

パターン2:  レスポンスの改ざん

結果反映

サーバー

⾃自分
バトル開始

攻撃 　 　３
防御 　 　２
精神⼒力力 　１速度度 　 　１

データ取得

WinorLose

敵キャラ
戦闘

結果反映
Copyright © GREE, Inc. All Rights Reserved.

パターン2:  レスポンスの改ざん

結果反映

サーバー

⾃自分バトル開始

攻撃 　  999
防御 　  999
精神⼒力力  999速度度 　  999

データ取得

Win
敵キャラ
戦闘

結果反映
Copyright © GREE, Inc. All Rights Reserved.

パターン2:  レスポンスの改ざん{"characters": !
{!
"id": "1",!
"master_character_id": "10001",!
"level": "2",!
"exp": "194",!
"hp": "999",!
"mp": "999",!
"atk": "999",!
"def": "999",!
"mentality": "999",!
”speed": "999",!
”aspeed": "999"!
}!
}!
Copyright © GREE, Inc. All Rights Reserved.

パターン２:  レスポンスの改ざん• 効果的、⼿手間が最⼩小限• パラメータを変えるだけ• プロキシツール使うだけ• ⽣生産性が⾼高く魅⼒力力的• 無敵になれる• 次々とバトルをクリアできる
ネイティブゲームに⾒見見られるパターン
Copyright © GREE, Inc. All Rights Reserved.

パターン２:  レスポンスの改ざん• 通信データの改ざんを検知（ハッシュ）• 通信データの暗号化• ただし突破されると思っておいたほうが良良い• 各種⾏行行動ログの取得• 異異常値の監視• など

Copyright © GREE, Inc. All Rights Reserved.

パターン２:  レスポンスの改ざん• 暗号化（例例えばAES）• 鍵が抜かれたら通信データは⾒見見れる• ハッシュによる改ざん検出• ハッシュ⽣生成前に改ざんしてしまう• クライアントのチェックロジックを消す

Copyright © GREE, Inc. All Rights Reserved.

パターン３：内部データの改ざん• リバースエンジニアリング• メモリ改ざん、バイナリ改ざん• パターン１、２よりは敷居が⾼高い• 選択肢として優先度度は低い• が、できれば基本何でも可能• ここから攻める⼈人ももちろんいる• 簡単にしてくれるツールも多々あり

Copyright © GREE, Inc. All Rights Reserved.

パターン３：内部データの改ざん
デバッガ

Copyright © GREE, Inc. All Rights Reserved.

パターン３：内部データの改ざん
リクエスト⽣生成
Break  Point

リクエスト内容を改ざん（メモリにある値を変更更）Hash値⽣生成改ざんされたデータを⽤用い
ハッシュ値が⽣生成されるリクエスト送信
サーバでの検証

リクエスト改ざん検出を通過（正しいリクエストとして処理理）
Copyright © GREE, Inc. All Rights Reserved.

Copyright © GREE, Inc. All Rights Reserved.

パターン３:  内部データの改ざん• 低レイヤーの知識識がある程度度必要• メモリ上にある値を操作• 通信の暗号化、改ざん検出は役に⽴立立たない• クライアントを完全コントロール• データ操作• ロジック操作
ネイティブゲームに⾒見見られるパターン
Copyright © GREE, Inc. All Rights Reserved.

パターン３:  内部データの改ざん••

安全にするのは難しい•

イタチごっこにならざるをえない•対策できることはやった⽅方がいい•

難読化、アンチデバッギング等•

専⽤用のソリューション（コストとの兼ね合い）

被害が⼤大きいところを⾒見見極め、ローカルで処理理しない•

コイン消費等、被害が⼤大きい機能は必ずサーバーサイドで処理理•サーバーかローカルか、⾒見見極めとバランス
Copyright © GREE, Inc. All Rights Reserved.

まとめ

Copyright © GREE, Inc. All Rights Reserved.

完璧を求めない。対策を組合わせ難しくする。
NATIVEゲ｜ム時代W
E
B
ゲ｜ム
時
代

パターン３

（ローカル改ざん）

パターン２（レスポンス改ざん）

サーバー
対策
パラメータ
チェック

（リクエスト改ざん）

改ざん検知

バリデーション
ログ

パターン１

通信保護
対策

通信データ
暗号化

ローカル対策アンチデバッグ
難読化
改ざん
防⽌止

監視

Copyright © GREE, Inc. All Rights Reserved.

２ White Box診断のススメ

Copyright © GREE, Inc. All Rights Reserved.

グリーの脆弱性診断体制
診断メニュー

診断数（年間）

工数/１プロダクト

内製脆弱性診断

約２０プロダクト

Web: 10営業日
Native: 15営業日

約２０プロダクト

Web: 10営業日
Native: 15営業日*内部リソースで診断

外注脆弱性診断*セキュリティベンダへ診断を発注•内製脆弱性診断•

ソースコードレビューによるWhite  box診断

•３名体制

•

新規リリースプロダクトが多い•診断調整  →  診断  →  レポート  →  修正トラッキングCopyright © GREE, Inc. All Rights Reserved.

なぜWhite  Box診断なのか
•

メリット
•

効率率率的

•

コードが⾒見見れる（全部書いてある）•

どこが悪いのかを指摘しやすい•

潜在的な脆弱性を発⾒見見できる•

開発側と連携がとりやすい

Copyright © GREE, Inc. All Rights Reserved.

実際の話

Copyright © GREE, Inc. All Rights Reserved.

みんな⼤大好きXSS

Copyright © GREE, Inc. All Rights Reserved.

皆さんどんなフィードバックしてます？
「安全なウェブサイトの作り⽅方」からいくつか参考として抜粋•

ウェブページに出⼒力力する全ての要素に対して、エスケープ処理理を施す。

•URL  を出⼒力力するときは、「http://」や  「https://」で始まる  URL  のみを許可する。

•

スタイルシートを任意のサイトから取り込めるようにしない。

Copyright © GREE, Inc. All Rights Reserved.

私たちはこんな感じに診断してフィードバックしています

Copyright © GREE, Inc. All Rights Reserved.

診断時の着眼点•開発フレームワークのセキュリティ機能、実装の確認、理理解•

XSS対策機能の設定が正しいか？

•

その対策機能が適切切に使われているか？

•対策機能をバイパスするように無理理くりいじられていないか？

•

XSSを作りこみやすい仕組み（設定、コーディング）になっていないか？

•

今問題なくても、将来的にXSSが発動する可能性はないか？

Copyright © GREE, Inc. All Rights Reserved.

FuelPHP  –  1.7出⼒力力エンコーディング
デフォルトでは、Fuel  は⼊入⼒力力フィルタリングより出⼒力力エンコーディングを好みます。その理理由は2つの要素からなります。  あなたのデータがどこから来たものであろうと、そしてそれがフィルタされていようがいまいが、出⼒力力エンコーディング
はそのデータを  クライアントに送信する際に無害にします。これは、すべての⼊入⼒力力は⽣生のまま、変更更のないかたちで保存され、何が起ころうと、  あなたはいつでも元データにアクセスできるとことも意味します。
Copyright © GREE, Inc. All Rights Reserved.

セキュリティ設定  –  conﬁg.php//デフォルト (fuel/core/config/config.php)!
'auto_filter_output" => true,!
!
//デフォルト (fuel/app/config/config.php)!
//'auto_filter_output' => true,!
//app設定フィルタ(fuel/app/config/config.php)のデフォルト設定値。!
'output_filter' => array('Security::htmlentities');!

//以下のようにoutput_filter自体をコメントアウトしても許可されておらずエラーになる。（Securityクラスの_init()でチェックされている）!
//'output_filter' => array('Security::htmlentities');!
!
//こんなことすれば無効化はできる。万一やっていたら経緯の把握と危険性を議論。!
'output_filter' => array();!

coreのレベルで設定値が有効となっているぞ。
htmlentitiesが使われているぞ。
Copyright © GREE, Inc. All Rights Reserved.

実装の部分（view.php）
public static function forge($file = null, $data = null,$auto_filter = null)!
{!
return new static($file, $data, $auto_filter);!
}!
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー!
public function __construct($file = null, $data = null,$filter = null)!
{ !
- snip -!
$this->auto_filter = is_null($filter) ?
\Config::get('security.auto_filter_output', true) : $filter;!
- snip -!
}!

$ﬁlterを明⽰示的にfalseにしていないかな？
conﬁgの設定値はtrueだから⼤大丈夫そうかな？
Copyright © GREE, Inc. All Rights Reserved.

実装の部分（外部テンプレートエンジン）
class View_Mustache extends \Parser\View_Mustache!
{!
public static function forge($file = null, $data = null,$auto_filter = false)!
{!

ここで無効になってた。。。。＞＜;<div class="Article-body"><div class="{{#mustache_fns.ucwords}}{{content_type}}{{/mustache_fns.ucwords}}-content"><h1 class="Article-title">{{{content.title}}}</h1>{{#content.description}}<p class="{{#mustache_fns.ucwords}}{{content_type}}{{/mustache_fns.ucwords}}-teaser">{{{content.description}}}</p>{{/content.description}}

⼀一⻫斉摘発$>  grep  ʻ‘{{{ʻ‘  /hoge/fuga/<tplのディレクトリ>
Copyright © GREE, Inc. All Rights Reserved.

最終的にこんなフィードバックになる•

フレームワークレベルでは対策が無効化されてますね•

テンプレートエンジンのエスケープ機能に依存してますね•

フレームワークかテンプレートエンジンのどっちかに寄せたかったんですよね？（⼆二重エスケープがイヤだった？）•

でも、テンプレート書く⼈人がこの実装、ルールを理理解しておかないと漏漏れが出ないですかね？

•

そのあたり開発ルールや、チェック体制を整備しておかないと将来的にxssを作り込みそうどうしましょっか？⼤大丈夫です？（にこやかに）
実装を理理解し、コードの⾏行行間を読み、潜在的な脆弱性にも気を配る努⼒力力
Copyright © GREE, Inc. All Rights Reserved.

まとめ•

実装を理理解することで効率率率的に脆弱性を検知できる•モノによっては⼀一⻫斉摘発可能•

コードレベルで開発部⾨門と対策を練ることができる•

具体的なので開発部⾨門もうれしい  (^_̲^)•

技術ベースで事業に貢献する（弊社開発本部の⽬目標）•

ユーザーの皆様へ安全な弊社サービスをお届けする！

•

そして、、、、、、、、

Copyright © GREE, Inc. All Rights Reserved.

インターネットを通じて、世界をより良良くする。

Copyright © GREE, Inc. All Rights Reserved.

Copyright © GREE, Inc. All Rights Reserved.