数年前に発見された巧妙なウェブサイトの脆弱性の暴露
複数の脆弱性が重なって引き起こされたウェブサイトのセキュリティ問題

Photo by Tarik Haiga
はじめに
数年前、まだウェブ開発のサポートをしていた頃、社内のエンジニアチーム向けにCTF競技を開催する任務を任されました。最初は会社の製品ごとにチームを分けて攻防戦を行う予定でしたが、主催者としてまずは参加者のレベルを把握するために、会社の各製品に対して自分で侵入テストを実施しました。どれだけの脆弱性を見つけられるか確認し、イベントの進行に問題がないかを確かめるためです。
しかし最終的に大会の時間が限られており、エンジニアリング分野の違いが大きかったため、共通の基礎知識と面白い方向性で問題を出題しました。興味のある方は、以前の記事「面白いエンジニアリングCTF大会の作り方」をご参照ください。中には斬新な問題がたくさんあります!
発見された脆弱性
合計で3つの製品に4つの脆弱性を発見しました。本文で取り上げる問題のほかに、以下の3つの一般的なウェブサイトの脆弱性も見つかりました:
-
Never Trust The Client!
問題は基本的なもので、フロントエンドがIDを直接バックエンドに送信し、バックエンドもそれをそのまま受け入れている点です。ここはTokenで認証するように変更すべきです。 -
パスワードリセットの設計欠陥
正確には忘れましたが、プログラム設計に欠陥があり、パスワードリセットの手順でメール認証を回避できてしまいました。 -
XSSの問題
-
本記事で紹介する脆弱性
検索方法はすべてブラックボックステストで行い、XSSの問題が見つかった製品のみ私がプログラム開発に関わっており、それ以外は関与しておらずコードも見ていません。
脆弱性の現状
ホワイトハッカーとして、発見した問題はすべて速やかにエンジニアチームに報告し修正しました。現在、2年が経過し、公表しても良い時期だと考えています。ただし、前職の立場を考慮し、本記事ではどの製品で発生した脆弱性かは触れません。この脆弱性の発見経緯と原因のみ参考にしてください。
脆弱性の影響
この脆弱性により、侵入者は対象ユーザーのパスワードを自由に変更でき、新しいパスワードで対象ユーザーのアカウントにログインし、個人情報を盗んだり、不正行為を行ったりすることが可能になります。
脆弱性の主な原因
タイトルの通り、この脆弱性は複数の要因が組み合わさって発生しています。以下の要素を含みます:
-
アカウントログインは二段階認証やデバイス紐付けに対応していません
-
パスワードリセットの認証にシリアル番号を使用しています
-
サイトのデータ暗号化機能に復号の脆弱性があります
-
暗号化機能が乱用されています
-
認証トークンの設計に誤りがあります
-
バックエンドでフィールドの二重検証が行われていません
-
プラットフォーム上のユーザーのメールアドレスは公開情報です
脆弱性の再現方法

プラットフォーム上でユーザーのメールアドレスが公開情報であるため、まずプラットフォーム上でターゲットのアカウントを閲覧し、メールアドレスを確認してからパスワードリセットページにアクセスします。
-
まず自分のメールアドレスを入力してパスワードリセットを行います。
-
侵入したいアカウントのメールアドレスを再度入力し、同様にパスワードリセット操作を行います。
以上の2つの操作はどちらもパスワードリセットの確認メールを送信します。

自分のメールボックスに入り、自分宛のパスワードリセット確認メールを受信する。
パスワード変更リンクは以下のURL形式にしてください:
https://zhgchg.li/resetPassword.php?auth=PvrrbQWBGDQ3LeSBByd
PvrrbQWBGDQ3LeSBByd は今回のパスワードリセット操作の認証トークンです。
しかし、サイトの認証コード画像を観察していると、認証コード画像のリンク形式も以下のように類似していることがわかりました:
https://zhgchg.li/captchaImage.php?auth=6EqfSZLqDc

6EqfSZLqDc は 5136 を表示します。
それでは、私たちのパスワードリセットトークンを入れたらどうなる?気にしないで! 入れてみよう!

ビンゴ!
しかし、認証コードの画像が小さすぎて、完全な情報を得ることができません。
私たちは引き続き利用可能なポイントを探します…
ちょうどサイトはクローラーの侵入を防ぐために、ユーザーの公開個人情報のメールアドレスを画像で表示しています。キーワード:画像で表示!画像で表示!画像で表示!
すぐに開いて確認してください:

個人情報ページ

ウェブページのソースコード部分
私たちも同様のURL形式の結果を得ました:
https://zhgchg.li/mailImage.php?mail=V3sDblZgDGdUOOBlBjpRblMTDGwMbwFmUT10bFN6DDlVbAVt
V3sDblZgDGdUOOBlBjpRblMTDGwMbwFmUT10bFN6DDlVbAVt は [email protected] を表示します。
同じく気にせず!詰め込め!

ビンゴ!🥳🥳🥳
PvrrbQWBGDQ3LeSBByd=2395656
パスワードリセットトークンを逆解析した結果、数字であることが判明した後
シリアル番号だったりして。。。
そこで再度メールアドレスを入力してパスワードリセットをリクエストし、新しく届いたメールのトークンを解読すると、2395657 が出てきた…なんてこった…本当にそうだった。
連番であることが分かれば対処は簡単なので、最初の操作は自分のアカウントのパスワードリセットメールをリクエストし、その後に侵入したいターゲットのリクエストを行います。次にリクエストされるパスワードリセットのIDを予測できるためです。
次に、
2395657をトークンに戻す方法を考えるだけです!
たまたままた問題を発見しました
サイトの編集時のメールアドレス形式の検証はフロントエンドのみで、バックエンドでの二重検証は行われていません…
フロントエンドの検証を回避した後、メールアドレスを次のターゲットに変更する


穴に火をつけろ!
私たちは以下を得ました:
https://zhgchg.li/mailImage.php?mail=UTVRZwZuDjMNPLZhBGI
この時点でこのパスワードリセットトークンを持って、パスワードリセットページに戻ります:

侵入成功!認証を回避して他人のパスワードをリセット!
最終的に二段階認証やデバイスバインディング機能がなかったため、パスワードが上書きされた後はそのまま不正ログインが可能になりました。
事の発端
全体の流れを整理します。
-
最初にパスワードをリセットしようとしましたが、リセット用トークンが実際には連番で、本当の一意のトークンではないことが判明しました。
-
サイトは暗号化・復号化機能を乱用しており、機能ごとの区別がなく、ほぼ全サイトで同じ鍵を使用しています。
-
ウェブサイトにオンラインで任意の暗号化・復号化機能が存在しており(=鍵が無効化されています)
-
バックエンドでユーザー入力の二重検証が行われていません
-
二段階認証保護やデバイス紐付け機能がありません
修正方法
-
最も基本的なことは、パスワードリセットのトークンはランダムに生成された一意の識別トークンであるべきです。
-
サイトの暗号化・復号部分は、機能ごとに異なる鍵を使い分けるべきです。
-
外部から自由にデータの暗号化・復号化を操作できないようにする
-
バックエンドはユーザーの入力を検証する必要があります
-
念のため、二段階認証とデバイス認証機能を追加する
まとめ
全体の脆弱性発見の過程は驚きでした。多くは基本的な設計上の問題だからです。機能だけを見ると動作は可能で、小さな穴があってもまあ安全と思えます。しかし、複数の穴が組み合わさると大きな穴になり、開発では本当に慎重さが求められます。
関連記事
Post は ZMediumToMarkdown によって Medium から変換されました。



コメント