Aqutras Members' Blog

株式会社アキュトラスのメンバーが、技術情報などを楽しく書いています。

セキュリティ・キャンプ2016全国大会で演習講義やってきました。

こんにちは、いるかさんです。

8月9日~8月13日の5日間にわたって開催された、セキュリティ・キャンプ2016全国大会。 たまたまご縁があり、3日目の4-C 「オンラインゲームアタック&ディフェンスチャレンジ」を担当させていただきました。
あいにく、いろいろと仕事が重なった関係で、準備時間があまりとれなかったことがとにかく悔やまれるんですが、
id:hi_igu くんの協力のおかげで、なんとか、「最低限ここまではやりたい!」というところまでは持っていくことができました。
補足なども含めて、ちょっといろいろ書きたいと思います。

何をやったか

「Capture the Frog」というMOゲーム(Webブラウザゲーム)を題材に、ゲームの運営側とプレイヤー側で、チート行為を行ったりそれを阻止したり、不正プレイヤーをBANしたりなど、してもらいました。
(本当はWebじゃなくてネイティブなゲームでやりたかったんですが、時間の都合でWebとなりました。)
プレ実施の結果、1回あたりの開催時間が1時間ぐらいで大丈夫そうだと分かったので、チームを変えながら2回実施しました。
1回目はα版、2回目はβ版としての位置づけとしました。

どうだったか

ゲーム側には、超致命的な脆弱性を1つと、ヤバメの脆弱性を2つ仕込んでいたんですが、2回目の実施では全部修正されました。
開催前は、結構厳しいかな?と懸念していたんですが、もっといろいろコンテンツ仕込んでおけばよかったなと反省してます。
受講生のレベルが高いとは聞いていましたが、なるほどびっくりデス(゜o゜;
結果として、2回目(β版)で(仕様的には)本番リリースできる状態にまでもっていけてました。パチパチ。

プレイヤー側には、チートを利用した育成や、育成の自動化を期待していました。チートを防がれた後は、いろいろな形の
自動化を試されていたように見えましたが、ここのフォローアップがこちらであんまりできてなかったです。受講生の方、スミマセン。

あと、SLAチェックがガバガバでした。1回目の開催では、その脆弱性をついて、プレイヤー側のスコアをマイナスにされました(ノД`)シクシクw
まだしっかり実施結果をチェックできてないんですが、BANフラグを下げる&&UUID書き換えて再BANすれば、無限にBANしつづけてプレイヤーのスコアを落とせるという穴がありました。
でも、こういう脆弱性をしっかり見つけられるってのは、ほんと大事なことなので、素晴らしいと思います。

仕込んでいた脆弱性と実例

レベルアップの脆弱性

最も致命的な脆弱性として、レベルアップ処理時に、経験値判定を抜かしておきました。
これは事前課題としても出していたので、開始早々、プレイヤーチームは続々と得点していました。
チューターのigutoくんは、0.3秒で最大レベルまで上げるスクリプト作ったりしてました。
この脆弱性を突かれると、ゲームバランスは崩壊しちゃいますし、ゲーム自体の寿命も一気に縮まってしまいます。

実際のゲームの多くは、サーバ側で経験値加算時に、レベルアップしていたら勝手にレベルアップさせると思います。
なので、この事例はちょっとイメージがつきづらい内容だったかもしれません。

ここで学んで欲しかった内容は、「クライアントにいくら制御を入れても、サーバには何でも送ることができる」という点です。
これは、送信内容を暗号化しようが何しようが、ハードルを上げることこそできても、送信内容自体をクライアント側で生成している以上、防ぎようがないと考えていいと思います。
なので、サーバ側でいろいろチェックしないといけないんだなぁ、面倒だなぁ( ;∀;)って思ってもらえたらよいかなと。

離れたカエルを捕まえられる脆弱性とワープできる脆弱性

プレイヤーは、キャラクターをカエルの隣まで移動させて、カエルを捕まえて経験値を得ます。
このとき、カエルの隣に移動しているかどうかという判定を抜かしておきました。
レベルアップの脆弱性と違い、一瞬で最大レベルまで上げられるわけではないですが、
いくらでも捕まえ放題なので、これも致命的な問題です。

さらに、プレイヤーは前後左右にしか移動できませんが、座標を指定して送ることで、好きなところに移動できていました。
なので、実質的には、離れたカエルを捕まえられる脆弱性と、ワープできる脆弱性を直さないといけませんでした。

実は、他の問題も含まれています。

マップ情報の同期

マップ上の全てのプレイヤーやカエルの情報をクライアントに送っていました。
これがそもそも問題で、マップのどこにカエルが居るのか分かってしまいます。
なので、プレイヤー周辺(描画される範囲)だけの情報を送るように修正する必要があります。
この修正を行うだけで、離れたカエルを捕まえていたチーターは、マップ上を移動しまくらないといけなくなります。

他プレイヤーやカエルの上に移動できる問題

クライアント上では、当たり判定があり、他プレイヤーやカエルの上に移動することはできません。
しかし、サーバ側には当たり判定がないので、どこにでも移動できてしまいました。
これはあまり大した問題ではないんですが、一般プレイヤーから見ると、チートしているのが即分かりますね。
(チーターとしては、「回線の問題でプレイヤーが見えてなかっただけだ!」とか言い訳もできます。)

移動が一瞬で完了する問題

これはクライアントでも仕様として扱っていたので、問題と気づけなかったかもしれませんが、
「ゲームの仕様自体が問題」というケースです。プレイヤーが移動にかかる時間は、0秒(実際には通信が完了するまで時間がかかるけど、無視できる範囲)です。
これはつまり、きちんとしたルートを移動するように通信すれば、現実的なワープが可能だということになります。
これでは、せっかく上下左右以外に移動できないように修正しても、意味が無いんですね。
この問題に気づいてかどうかは分かりませんが、移動やその他の通信も含めて、1秒のディレイを入れていた運営チームがいました。これはとても良い対策です。

その他

いくつか気づいた点を書きます。

ゲームの機能を一時的に制限してしまう

今回、プレイヤーのレベルが一切上がらないように修正したチームがいました。
サーバチェックがガバガバだったので、最初は運営チームにスコア加算が続いていたんですが、
現実問題としては、問題がある機能を一時的に使えなくするのはよくあると思います。

例えば、アップデートで追加された機能に問題があったりした時、問題の機能だけ使えなくするとか。
競技的に考えるなら、サーバチェックの内容を細かく切り分けて、重要な機能が落ちていたらマイナス点を大きくするとか、ですかねー。

  • 新規登録できる=2点加算、ログインできる=2点加算、移動できる=1点加算、チャットできる=1点加算、カエルを捕まえられる=3点加算、レベルアップできる=1点加算
  • 新規登録できない=10点減点、ログインできない=8点減点、移動できない=4点減点、チャットできない=2点減点、カエルを捕まえられない=10点減点、レベルアップできない=10点減点

とか。これなら、新規登録機能とログインは生かして(4点加算)、移動機能だけ切ろう(4点減産)、チャットは生かそう(1点加算)、合計1点は入るぞ、とか、戦略立てたりできそうですね。
(思いついたまま書いてるので穴たくさんありそうです。)

怪しいプレイヤーを自動BAN

ハードBAN(アカウントを無効化する)で実際にこれを取り入れているところがあるのかは知りませんが、
ソフトBAN(一部機能に制限を設ける)だと、ポケモンGOなどは取り入れていますね。
怪しい行動などをログや異常行動から検知できる仕組みを作ることは、とても大事だと思います。
Rubyならrspecなど、CIでテストコードを書くと思いますが、それと同じで、
ゲームの仕様的なものをコード化して、「X日経過した時点ではレベルXには到達しないはずである」とか、
「1日でXXという距離を移動することはできないはずである」とか、その辺を自動でチェックする仕組みとかいいかもですね。

今回は、プレイヤーキャラクターをRMTすると、プレイヤーのIDが変わるという仕様でした。
これに気づいた運営チームが、プレイヤーのIDが変わったらBANしようとしていました。
これは個人的に結構有効だと考えています。というのも、オンライゲームでパスワードを変更するタイミングって、
「パスワードを忘れたとき」か、システムによって定期変更を強制されて変えるとき」か、「誰かに譲ったとき」ぐらいしかないですよね。
しかもこれ、「誰かに譲ったとき」の変更の仕方と、それ以外の変更の仕方は、そもそもシステムの扱いが違うことが多いハズ。
自分もいろんなゲームやってますが、パスワード変更したことなんてほとんどなく・・(使いまわしていたものを一斉に全部違うパスに変更したことはある)。
通常のパスワード変更は、1つの怪しいindicationになる気がします。

プレイヤーへのペナルティ措置

プレイヤーのレベルを初期値に戻してしまうという案が出ている運営チームを見かけました。
問答無用で戻してしまうということなら、サーバチェックによっては減点対象ですが、
不正行為を行ったプレイヤーに対するペナルティということであれば、ソフトBANとハードBANの間ぐらいの処置になるかなと思います。
実際のネットゲームでも、不正行為を行ったプレイヤーについては、一部ステータスを初期値に戻すとか、そういうのもあります。
この場合、「これに懲りてもう不正なことはしないでね」って意味合いが強いのかなと思いますが、
効果としては、(´ε`;)ウーン…どうなんでしょうね。結構意見が分かれそうなところに思います。

プレイヤーからの野次

すごいリアルだな!って感じたのは、プレイヤーからの野次。
当たり前ですが、サーバが落ちてたら、プレイヤーから「ログインできねーぞ!」って文句が飛んできます。
実際に運営や開発の人が、ユーザと直接やりとりを行ったり触れ合うことはないと思いますが、
「とりあえずログインだけでもできるようにするか?」とか、「メンテページ出すか?」とか、
いろいろ検討してみると奥が深いとこだと思います。
某イラストサイトでは、メンテ中にミニゲームで遊べたりなど、工夫されてますね。

運営の暴走

暴走っていうとちょっと失礼かもですが、チューターさんの運営されたサーバでは、

  • カエルが透明表示
  • プレイヤーは全員カエルのグラフィック
  • レベル表記は常に1(内部ではちゃんと上がっている)

という、特殊なサーバに改造されていましたw

f:id:Dltn:20160813193949p:plain

ちなみに、脆弱性の一部は直されていなかったため、チートし放題でした。( ;∀;)
みんなでログインしてカエルになって、見えないカエルを囲ったりしてと、
なんか一番オンラインゲームっぽく(?)楽しんでいた気がします( ´∀`)

プレイヤー同士での通報機構

これは今回は触れていませんし、特にどのチームも実施していませんでしたが、
プレイヤー同士の監視社会を促すような仕組みを導入しているネットゲームもあります。
不正なプレイヤーを通報するだけでなく、直接的に自動操作していないかチェックしたり、など。
そして、これは、機械学習やAIが発達していくと、自動操作と人間の区別がつかなくなり、
近い将来、AIがネットゲーム上に氾濫してネトゲ社会が成り立ちづらくなってきてしまったりしないんだろうかとか。
この辺の議論を本当は1時間ぐらいやりたかったんですが!!全然時間が足らなくてできませんでした。。
2回目の競技を15分ほど縮めてもよかったかもしれない。。。(T_T)

現実的なところ

オンラインゲームのチートって、想定してない部分を突かれる事が多く(脆弱性もそうなんですが)、
作ってる側としては、「ここはこういう制御が入っているから大丈夫!」と思い込んだり、「これで動くからヨシ!」と妥協しちゃうことがあります。
特にオンラインゲームでは、クライアントとサーバに分かれているので、クライアントには制御を入れてあるのに、
サーバ側の制御に穴があって・・みたいなケースが結構見られます。クライアントの穴は、デバッグプレイで
見つかりやすいんですが、サーバ側の穴は、普通のプレイでは見つけられないことが多いのも影響してますね。
また、現実問題、納期や予算の都合で、そこまで入念なチェックをあえて行わなかったり、
「この部分はチートされても被害は少ないのでチートされてもやむを得ない」と割り切ることもあります。

もう一つ、今回用意した脆弱性もそうですが、全ての脆弱性を修正しても、ユーザや表からは、ゲーム的には、何も変わって見えないんですね。
これも相まって、セキュリティ対策費用って出づらいし、相手も出しづらいんだろうなあという面があります(ノД`)シクシク
そういう時に、しっかりと「どういう問題が発生する可能性がある」のか、「発生した場合の被害はどうなのか」などを伝えた上で納得してもらうとか。
でも、さらに会社的には、責任の切り分けとかもあって、闇が深いところですね。

さいごに

受講生のみなさん、お疲れ様でした!
本講義を通じて何か得るものがあったのであれば、幸いです。
そして、講義をサポートしてくださったチューターの方々、運営の方々、NOCの方々、ありがとうございました!
おかげ様で、安心して講義に集中することができました。
いろいろ手伝ってくれた id:hi_igu くんには感謝してもしきれません。。また社内でも面白いことやりましょ! ゲームの用意や資料に、かわいいフリー素材集 いらすとや の素材を使わせていただきました!ありがとうございました。

また、キャンプにお誘いくださった方や調整いただいた方々、事前に内容相談にのってくださった方々、
プレ実施にご協力いただいた方々のおかげで、ここまで来ることができました。本当にありがとうございました!

すごくどうでもいい話ですがTwitterのアイコンがミズゴロウの人が何人かいたのでミズゴロウのTシャツ着てました。すごくどうでもいい。

お知らせ

セキュリティ・ミニキャンプin中国 2016で、専門講座をやらせてもらいます。
詳細→ http://www.security-camp.org/minicamp/data/2016MC_Chugoku_senmon.pdf
OpenSSLの脆弱性、HeartBleedを題材として、コミットの歴史を追ってみたり、
オープンソースをどう読んでいくのかを手を動かしながら体験しつつ、
オープンソースと脆弱性について考える場にできたらなと考えています。
他にも面白い内容の専門講座やLTがよりどりみどりです。
申し込み締め切りが伸びて、15日まで受け付けているみたいなので、興味のある方はぜひ!

セキュリティ・ミニキャンプ in 中国 2016(広島):IPA 独立行政法人 情報処理推進機構
(こちらのページには1日までって書いてますが、PDFの方は15日までになってるので、多分15日までのハズ....?)