同期が作ったアプリをハッキングしてみた

f:id:ryoutaku_jo:20190227201120p:plain

【結論】
・ハッキングは、攻撃する側の方が圧倒的に有利

・HTTPリクエスト/レスポンスを読み解けば、
 アプリの仕様が分かる


【目次】


【本題】

同期のアプリをハッキングした

同じプログラミングスクールに通っている同期が
簡単なミニアプリを作られました。

わだゆうま@33歳からエンジニア (@nekotter222) | Twitter

http://mugenpochi.herokuapp.com/

始めは普通に遊んでいたのですが、
優秀なエンジニアの方にハッキングしているのを見た時・・・

f:id:ryoutaku_jo:20190227201135p:plain

「こんな遊び方もあるんだ!」と感銘を受け、
私もハッキングする事にしました(笑)

※注意※
あまり親しくない人のアプリを勝手にハッキングするのはやめましょう!
礼節を重んじてハッキングしましょう!

アプリ概要

アプリの簡単な概要は下記の通りです。
1:ボタンをクリックすると、ランダムで点数が付与される
2:ボタンをクリックすると、ランダムでゲームオーバーになる
3:ゲームオーバーまでに獲得した点数が、過去最高ならハイスコアに記録される
4:ユーザー毎のハイスコアがランキング形式で表示できる

今回はランキングで一位を獲得すべく、ハッキングを試みました。

点数の改竄(バージョン1.0)

まずアプリが、どの様な通信が行っているか確認します。

GoogleChromeの場合、デベロッパーツールの「Network」から
HTTPリクエスト/レスポンスを確認する事が出来ます。

デベロッパーツールを開くには、
Macであれば「command+option+i」か、右クリック後の「検証」をクリックします。

f:id:ryoutaku_jo:20190228152203p:plain

※非同期で通信している様なので「Sources」からJavaScriptのコードを見た方が
手取り早いのですが、HTTPリクエスト見た方がハッカーっぽいと思ったので
基本は見ない方針でやっていきます。

実際に確認して見ると、ボタンを押した時点では、サーバーサイドとの通信は行われず、
「GAME OVER」になった直後に通信が行われている事が分かりました。
※「Status」の項目を見ると、「GAME OVER」になった直後の「Scores」で
リクエストが成功したという意味の「200」のステータスが表示されています。

f:id:ryoutaku_jo:20190228151742g:plain

「GAME OVER」になった直後のHTTPリクエストは下記の様な内容です。

f:id:ryoutaku_jo:20190228153326p:plain
f:id:ryoutaku_jo:20190228153340p:plain
※当時の本番環境の画像を残して無かったので、
ローカル環境で当時のコードを再現した際の画像を使っています
ーーーーーーーーーーーーーーーーーーー
Request URL: http://mugenpochi.herokuapp.com/scores
Request Method: POST
Farm Date highscore: 40
ーーーーーーーーーーーーーーーーーーー
これは、「http://mugenpochi.herokuapp.com/scores」に対して、
「highscore: 40」というデータを「POST送信」しているという内容です。

highscoreの値は、ビューに表示されている合計点数と一致しました。

f:id:ryoutaku_jo:20190228153825p:plain

つまり、フロントサイドで集計した合計点数を、
そのままサーバーサイドに渡して、DBに保存しているという事が分かります。

フロントサイドで合計点を集計する場合、
JavaScriptの変数に点数を保持させて、それを最後に送信する方法と、
ビューで集計した合計点をそのまま送る方法が考えられます。

というわけで、まずビューの合計点を改竄するJavaScriptjQuery)のコードを作ります。

f:id:ryoutaku_jo:20190228160127p:plain

<span id="score">40</span>

合計点のHTML構造は上記の通りなので、
これを改竄するJavaScriptjQuery)のコードは、下記になります。

$('#score').html('<span id="score">1000</span>');

実際に実行して見ましょう。

f:id:ryoutaku_jo:20190228160523p:plain
f:id:ryoutaku_jo:20190228160534p:plain
f:id:ryoutaku_jo:20190228160559p:plain

すると、ランキングの点数にも合計点が反映され、
ハッキングに成功しました!

非同期通信の突破(バージョン2.0)

ハッキングに成功した事を伝えると、直ぐに対策を講じられました。

今度は、ビューの値を直接変更しても、点数が直ぐに書き換わってしまいます。

f:id:ryoutaku_jo:20190228162924g:plain

そこで、再度HTTPリクエストを確認して見ると
ボタンを押すたびにHTTPリクエストが送信されていました。

f:id:ryoutaku_jo:20190228163207g:plain


ボタンを押した直後のHTTPリクエストは下記の様な内容です。
ーーーーーーーーーーーーーーーーーーー
Request URL: http://mugenpochi.herokuapp.com/scores/keep_score
Request Method: POST
Farm Date highscore: 4
ーーーーーーーーーーーーーーーーーーー

ここから、都度点数をサーバーサイドに渡している事が分かりました。

ここまで分かれば、後はHTTPリクエストの内容を再現した
JavaScriptjQuery)のコードを実行すれば良いだけです。

改竄する為のコードは下記の様な記述にしています。

  $.ajax({
    type: "post",
    url: "/scores/keep_score",
    data: {highscore: 100000},
  })
});

f:id:ryoutaku_jo:20190228171536g:plain

ということで、再度不正アクセスに成功しました!

Cookieが改竄出来ない(バージョン3.0)

もう一度、ハッキングに成功した事を伝えたところ、またもや改修されました。

HTTPリクエストを見ると、前回まであったFormDataの項目が無くなっています。

f:id:ryoutaku_jo:20190228172149g:plain

つまり、フロントサイドには点数計算のロジックは一切記述せず、
全てサーバーサイドに記述する方式に変更したと考えられます

これ以上、値を改竄する方法が思い付かなかったので、
GitHubからコードをフォークして、対抗策を検討しました。

GitHub - wonder-boooy/eternalpochi

どうやらセッションを使って、合計点数を保持する記述をされていたので、
セッションを保存しているCookieを改竄出来ないか探りました。

ただ、Railsのsessionは、Cookieの暗号化も行っている様で、
どうやっても改竄が出来ません・・・

というわけで、ここで負けを宣言しました!

総括

ハッキングというには、かなりショボい内容ですが、
攻撃方法や防御策を考える過程は非常に楽しく、
セキュリティ関係の分野に強い関心が湧きました!

この分野に関する理解は、更に深めて行きたいと考えています。

《今日の学習進捗》

ハッキングと就活。

学習開始からの期間 :82日
今日までの合計時間:822h
一日あたりの平均学習時間:10.1h
今日までに到達すべき目標時間:749h
目標との解離:73h
「10,000時間」まで、

残り・・・「9178時間!」