コース : https://academy.hackthebox.com/course/preview/broken-authentication
-
認証は、RFC 4949 では「システムエンティティまたはシステムリソースが特定の属性値を持つという主張を検証するプロセス」と定義
-
情報セキュリティにおいて、認証とは、エンティティの身元を確認し、そのエンティティが名乗る人物であることを保証するプロセス
-
一方、認可は「システムエンティティがシステムリソースにアクセスすることを許可する承認」
-
知識ベース認証
- パスワードとか
-
所有ベース認証
- ユーザーが所有しているものに依存
- IDカード、セキュリティトークン、スマホなど
-
内在ベース認証
- 生体認証や音声認識、署名など
認証に対する攻撃
- 知識ベース認証
- 比較的攻撃しやすい
- CTFやHTBで扱うのは、知識ベース認証
- サイバー脅威が進化するにつれて、攻撃者はソーシャルエンジニアリングやデータ漏洩など、さまざまな手段を通じて知識ベース認証システムの弱点を悪用することに熟達している
- 所有ベース認証
- フィッシング攻撃やパスワード推測攻撃など、多くの一般的なサイバー脅威に対する耐性がある
- ハードウェアトークンやスマートカードなど、物理的な所有に基づく認証方法は本質的に安全性が高い
- オブジェクトの盗難やクローン作成などの物理的な攻撃、およびそれが使用するアルゴリズムに対する暗号攻撃に対して脆弱になる可能性がある
- 公共交通機関やカフェなどの公共の場所でNFCバッジなどのオブジェクトをクローン作成することは、実行可能な攻撃
- 内在ベース認証
- データ漏洩が発生した場合、元に戻せない形で侵害される可能性がある
- 普通の使用時には安全に見えるが、ハッキングされ、流出したとしても、認証情報を変更することができないというデメリットもある
ブルートフォース
ユーザー列挙した後に、パスワードのブルートフォース攻撃よね
ユーザー列挙
- ユーザー列挙の脆弱性は、Webアプリケーションが認証エンドポイントに対して登録済み/有効な入力と無効な入力で異なる応答を返す場合に発生する
- この脆弱性は、ユーザー名に基づいた機能(ログイン、ユーザー登録、パスワードリセットなど)で頻繁に見られる
- Web開発者は、ユーザー名のような情報は機密ではないと考え、ユーザー列挙の攻撃ベクトルを見落としがち
- ユーザーはWebアプリケーション以外(FTP、RDP、SSHなど)でも同じユーザー名を使い回す傾向がある
理論
- Webアプリケーションが「このユーザー名は存在しません」といった情報を返すことで、正規のユーザーが自分の入力ミスに気づける一方で、攻撃者も有効なユーザー名を特定できてしまう
- 例えば、WordPressのような有名で成熟したアプリケーションでさえ、デフォルトでユーザー列挙が可能
- 無効なユーザー名の場合
- 「不明なユーザー名です。もう一度確認するか、メールアドレスを試してください。」
- 有効なユーザー名 + 無効なパスワードの場合
- 「そのユーザー名 editor に対して入力されたパスワードが間違っています。」
- 無効なユーザー名の場合
- ユーザー列挙はWebアプリケーションが意図的にサービス提供のために受け入れているセキュリティリスクである場合もある
- 例えば、チャットするアプリだったりでユーザー名で相手を検索できる機能を提供しているものとか
攻撃
例えば、無効なユーザーのときは、Unknown user
って出る時は、それ以外が出てきた時に有効なユーザー名ってわかるよね
ffufを使って、ユーザー列挙できるよね
ffuf -w /usr/share/wordlists/seclists/Usernames/xato-net-10-million-usernames.txt \
-u http://172.17.0.2/index.php \
-X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=FUZZ&password=invalid" \
-fr "Unknown user"
あとは、Webアプリケーションの応答内容の違いが最も分かりやすいユーザー列挙手法ですが、それ以外にもサイドチャネルを用いた列挙も可能
- サイドチャネル攻撃は、アプリケーションの直接的な応答ではなく、応答時間などの付随情報を分析する
- 例えば、アプリケーションが有効なユーザー名に対してのみデータベース検索を行っている場合、有効なユーザー名を使用したときだけ応答に時間がかかる、といった挙動の差が現れることがある
- 応答内容が同一でもレスポンスタイミングの差から有効なユーザー名を推測することが可能
パスワード
- 有効なユーザーを特定した後、パスワードベースの認証では、ユーザーの認証手段としてパスワードのみに依存する
- ユーザーは記憶しやすいパスワードを選ぶ傾向があるため、攻撃者がそれを推測したり総当たり攻撃(ブルートフォース)で突破する可能性がある
理論
パスワードの問題点
- パスワードの使い回し
- 同じパスワードを複数のアカウントで使う人が多く、あるアカウントが侵害されると、他のサービスも同じ資格情報で突破されるリスクがあります(パスワードスプレー攻撃)
- 弱いパスワードの使用
- よくあるフレーズ、辞書に載っている単語、単純なパターンに基づくパスワードは、総当たり攻撃(ブルートフォース)で簡単に破られる可能性がある
攻撃
-
ブルートフォース攻撃の成功は、以下の2つに依存する
- 試行回数(何回試せるか)
- 攻撃にかかる時間(どれくらいで終わるか)
- したがって、適切なワードリストの選定が極めて重要
-
サンプルWebアプリケーションのログイン画面とかにパスワード要件とかが書かれてたら、辞書のヒントになるよね
- rockyou.txtから該当するパスワードだけ抽出することで、より短時間で見つけられる
grep ' grep '[[:lower:' | grep '[[:digit:]]' | grep -E '.{10}' > custom_wordlist.txt
snowyowl644@htb[/htb]$ wc -l custom_wordlist.txt
151647 custom_wordlist.txt
まず、burpsuiteなどで、どんなリクエストがきているかを確認してから、ffufとかでブルートフォースできる
ffuf -w ./custom_wordlist.txt -u http://172.17.0.2/index.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin&password=FUZZ" -fr "Invalid username"
パスワードリセットトークン
- 多くのウェブアプリケーションでは、ユーザーがパスワードを忘れた場合にパスワード回復機能が実装されている
- このパスワード回復機能は通常、SMSやEメールなどを介してユーザーに送信されるワンタイムリセットトークンに依存する
- ユーザーはこのトークンを使用して認証を行い、パスワードをリセットしてアカウントにアクセスできる
- 脆弱なパスワードリセットトークンは、攻撃者によってブルートフォースされたり、予測されたりする可能性があり、その結果、被害者のアカウントが乗っ取られる危険がある
脆弱なリセットトークンの特定
- 通常、ターゲットのウェブアプリケーションでアカウントを作成し、パスワードリセットトークンを要求してから、それを分析する必要がある
- この例では、以下のパスワードリセットEメールを受け取ったと仮定する
1. Click on the following link to reset your password: Click 2. If the above link doesn't work, copy and paste the following URL into your web browser: http://weak_reset.htb/reset_password.php?token=7351
4桁のトークンの組み合わせだったら、10000通りしかない
パスワードリセットを要求し、そのトークンをブルートフォースすることで、ユーザーのアカウントを乗っ取ることができる
脆弱なリセットトークンへの攻撃
まず、考えられるトークンのリストを作成する
0-9999までのリストの例
-w
フラグは、すべての数字をゼロで埋めて同じ長さにする
seq -w 0 9999 > tokens.txt
- 現在パスワードをリセット中のユーザーがいると仮定して、すべてのアクティブなリセットトークンをブルートフォースすることができる
- 特定のユーザーをターゲットにする場合は、まずそのユーザーのパスワードリセットを要求してリセットトークンを作成する必要がある
- その後、
ffuf
でワードリストを指定し、すべてのアクティブなリセットトークンをブルートフォースする
ffuf -w ./tokens.txt -u http://weak_reset.htb/reset_password.php?token=FUZZ -fr "The provided token is invalid"
2要素認証へのブルートフォース
- 通常、これは知識ベース認証(パスワード)と所有ベース認証(2FAデバイス)を組み合わせることで実現される
- 2FAは以前に説明した3つの主要な認証カテゴリのいずれか2つを組み合わせることでも実現できる
- 2FAは攻撃者がユーザーの認証情報を入手できたとしても、アカウントにアクセスすることを著しく困難になる
攻撃
- 最も一般的な2FAの実装の1つ
- ユーザーのパスワード
- 認証アプリまたはSMSを介してユーザーのスマートフォンに提供される時間ベースワンタイムパスワード(TOTP)
- これらのTOTPは通常、数字のみで構成されているため、長さが不十分
- ウェブアプリケーションが誤ったTOTPの連続送信に対する対策を実装していない場合、推測される可能性がある
CTFで、admin : admin
でログインできた時に、2要素認証があることに気づいた
- しかし、ウェブアプリケーションのメッセージを見ると、TOTPが4桁のコードであることがわかる
- 可能な組み合わせは10,000通りしかないため、すべての可能なコードを簡単に試すことができる
4桁のセッショントークンのリストを作る
seq -w 0 9999 > tokens.txt
ffufで、エラーメッセージを除外してブルートフォースすることで、セッショントークンがわか離、2要素認証をパスすることができる
- 多くの結果が出てくる場合があるが、正しいTOTPを提供した後、セッションが2FAチェックを正常に通過したため
- なので、一番最初のものが正しいTOTPだとわかる
ffuf -w ./tokens.txt -u http://bf_2fa.htb/2fa.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -b "PHPSESSID=fpfcm5b8dh1ibfa7idg0he7l93" -d "otp=FUZZ" -fr "Invalid 2FA Code"
- 攻撃が成功したら、セッションは完全に認証済みとしてマークされるため、セッションクッキーを使用するすべてのリクエストは
/admin.php
にリダイレクトされて、ログインできる
ブルートフォースの防御のバイパス
レートリミット
- レートリミットは、システムやAPIへの受信リクエストのレートを制御するために、ソフトウェア開発やネットワーク管理で採用されている重要な技術
- DoSシナリオを防ぐために、レートリミットは正規のユーザーではなく、攻撃者に対してのみ適用されるべき
- しかし、攻撃者のIPを見分けるのは難しい
- 一部のレートリミットは、実際の送信元IPアドレスを取得するために
X-Forwarded-For
などのHTTPヘッダーに依存している
しかし、X-Forwarded-For
などのHTTPヘッダーは、攻撃者が任意のHTTPヘッダーを設定できるため、レートリミットを完全にバイパスすることもできる
- これにより、攻撃者はレートリミットを回避するために各HTTPリクエストで
X-Forwarded-For
ヘッダーをランダム化することでブルートフォース攻撃を実行できる- 例 : CVE-2020-35590
CAPTCHA
- Completely Automated Public Turing test to tell Computers and Humans Apart (CAPTCHA)
- ボットがリクエストを送信するのを防ぐためのセキュリティ対策
- こんな風に、正答がHTMLに書いてるCAPTCHAはだめ
パスワードアタック
デフォルト認証情報
-
多くのウェブアプリケーションは、インストール後にアクセスできるようにデフォルトの認証情報が設定されている
-
以下のリンクらで、デフォルトの認証情報探せるって
-
https://github.com/danielmiessler/SecLists/tree/master/Passwords/Default-Credentials
-
https://github.com/scadastrangelove/SCADAPASS/blob/master/scadapass.csv
あと、google検索でもこのように調べれば出てくる
bookstack default credentials
脆弱なパスワードリセット
ウェブアプリケーションがレートリミットやCAPTCHAを利用している場合でも、「パスワードリセット機能内のビジネスロジックのバグ」などで 他のユーザーのアカウントを乗っ取ることが可能になる場合がある
推測可能なパスワードリセットの質問
- 多くの場合、ウェブアプリケーションは、パスワードを忘れたユーザーに1つまたは複数のセキュリティの質問に答えることを要求して認証する
- 登録時、ユーザーは事前に定義された一般的なセキュリティの質問に回答を提供し、カスタムの質問を入力することはできない
- 同じウェブアプリケーション内では、すべてのユーザーのセキュリティの質問は同じになり、攻撃者がそれを悪用できるようになる
ターゲットのウェブサイトでそのような機能を見つけた場合、認証をバイパスするためにそれを悪用しようとすべき
多くの場合、質問ベースのパスワードリセット機能の脆弱なリンクは回答の予測ができる
- 「母親の旧姓は何ですか?」
- 「生まれた都市はどこですか?」
これらの質問は個々のユーザーに結びついているように見える
- しかし、多くの場合、OSINTを通じて取得されたり、十分な試行回数(つまり、ブルートフォース保護の欠如)があれば推測されたりする可能性がある
たとえば、ウェブアプリケーションが「生まれた都市はどこですか?」のようなセキュリティの質問を使用していると仮定
- 世界には大都市のワードリストが複数存在
- https://github.com/datasets/world-cities/blob/main/data/world-cities.csv
- ブルートフォースできる
- 何かわかっていれば絞り込んでブルートフォースすることもできる
例
- 回答をブルートフォースするための対応する
ffuf
コマンドをセットアップできる - ユーザー名「admin」とリクエストを関連付けるために、セッションクッキーを指定する必要がある
- burpsuiteなどで取得
上のワードリストから、都市名のみを取得
- burpsuiteなどで取得
cat world-cities.csv | cut -d ',' -f1 > city_wordlist.txt
ffufでブルートフォース
ffuf -w ./city_wordlist.txt -u http://pwreset.htb/security_question.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -b "PHPSESSID=39b54j201u3rhu4tab1pvdb4pv" -d "security_response=FUZZ" -fr "Incorrect response."
リセットリクエストのロジック面での脆弱性
- 欠陥のあるパスワードリセットロジックの別の例は、ユーザーが潜在的に隠されたパラメータを操作して、別のアカウントのパスワードをリセットできる場合に発生
htb-stdntとして、reset_password.phpを行うが、リクエストの中にusername
が入っている
POST /reset.php HTTP/1.1
Host: pwreset.htb
Content-Length: 18
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=39b54j201u3rhu4tab1pvdb4pv
username=htb-stdnt
POST /security_question.php HTTP/1.1
Host: pwreset.htb
Content-Length: 43
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=39b54j201u3rhu4tab1pvdb4pv
security_response=London&username=htb-stdnt
POST /reset_password.php HTTP/1.1
Host: pwreset.htb
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=39b54j201u3rhu4tab1pvdb4pv
password=P@$w0rd&username=htb-stdnt
なので、このように、adminのパスワードを変更できてしまうという脆弱性を突ける
POST /reset_password.php HTTP/1.1
Host: pwreset.htb
Content-Length: 32
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=39b54j201u3rhu4tab1pvdb4pv
password=P@$w0rd&username=admin
認証バイパス
ダイレクトアタック
- 認証チェックをバイパスする最も直接的な方法は認証されていないコンテキストから保護されたリソースを直接要求すること
- ウェブアプリケーションがリクエストが認証されていることを適切に検証しない場合、認証されていない攻撃者は保護された情報にアクセスできる
- 例
- ウェブアプリケーションがユーザーの認証成功後に
/admin.php
エンドポイントにリダイレクトし、認証されたユーザーにのみ保護された情報を提供するロジックだとする - この時に認証も何もしていない状況で、直接
/admin.php
にアクセスすること
- ウェブアプリケーションがユーザーの認証成功後に
- 例
- ウェブアプリケーションがユーザーの認証をログインページのみに依存している時に起こる
攻撃
- webブラウザで、
/admin.php
にアクセスする - Burpsuitdeで傍受→Repeater
この時、 Repeaterのレスポンスを見ると、302になってるけど、admin.phpのHTMLが含まれているのがわかる
含まれているのがわかる
Proxyに戻って、右クリック→Do interceptを押す(ここでは画面に変化なし)
Forward押す
レスポンスが、Proxyに出てくる
HTTP レスポンスステータスコードが302 Foundになっているので、それを200 OKに書き換える
Forwardを押すと、ブラウザで、ダイレクトアタックした結果を見ることができる
パラメータ変更による認証バイパス
- 認証実装は、HTTPパラメータの存在または値に依存している場合に欠陥がある可能性があり、認証の脆弱性を引き起こす
- セクションと同様に、このような脆弱性は認証および認可のバイパスにつながり、権限昇格を許してしまうことがある
- このタイプの脆弱性は、Insecure Direct Object Reference (IDOR) の脆弱性など、認可に関する問題と密接に関連しており、これらは「Web攻撃」モジュールでより詳細に扱われている
ログインした後に/admin.php?user_id=183
って感じで、webページが出たら、このuser_idの数字をファジングすることでIDORで、権限昇格できることあるよねって話
SQLインジェクションとかもあるよねって話
user_idの数字のリストの作成
```sh
seq 1 200 > user_ids.txt
ffufの実行
```sh
ffuf -w user_ids.txt -u "http://94.237.51.163:50066/admin.php?user_id=FUZZ" -b "PHPSESSID=vu4badta7ib21h8wefwefwfwe" -mc 200,302
セッショントークンへの攻撃
- ウェブアプリケーション認証の欠陥のある実装の悪用に焦点を当ててきた
- しかし、認証に関連する脆弱性は、認証自体の実装だけでなく、セッショントークンの取り扱いからも発生する可能性がある
- セッショントークンとは、ウェブアプリケーションがユーザーを識別するために使用する一意の識別子
- セッショントークンはユーザーのセッションに結びついている
- 攻撃者が別のユーザーの有効なセッショントークンを入手できれば、そのユーザーになりすましてウェブアプリケーションにアクセスし、セッションを乗っ取ることができる
十分にランダムでない場合、セッションを乗っ取ることができてしまう
十分にランダムではないトークン
- ウェブアプリケーションによって割り当てられた次のセッショントークンを考えてみる
2c0c58b27c71a2ec5bf2b4b6e892b9f9
セッショントークンは32文字長なので、他のユーザーの有効なセッションを列挙することは不可能に思える
しかし、ログインリクエストを複数回送信し、ウェブアプリケーションによって割り当てられたセッショントークンに注目してみる
その結果、以下のセッショントークンが得られる
2c0c58b27c71a2ec5bf2b4b6e892b9f9
2c0c58b27c71a2ec5bf2b4546092b9f9
2c0c58b27c71a2ec5bf2b497f592b9f9
2c0c58b27c71a2ec5bf2b48bcf92b9f9
2c0c58b27c71a2ec5bf2b4735e92b9f9
ご覧の通り、すべてのセッショントークンは非常に似ている
実際、32文字のうち28文字は、キャプチャされた5つのセッションすべてで同じ
- セッショントークンは、静的な文字列
2c0c58b27c71a2ec5bf2b4
に4つのランダムな文字が続き、静的な文字列92b9f9
が続く構成になっている - これにより、セッショントークンの実質的なランダム性が低下している
- 32文字のうち28文字が静的であるため、既存のアクティブなセッションをブルートフォースするために列挙する必要があるのはわずか4文字であり、すべてのアクティブなセッションを乗っ取ることが可能になる
インクリメントするトークン
- もう1つの脆弱な例は、インクリメントするセッショントークン
- たとえば、連続するセッショントークンの以下のキャプチャを考えてみる
141233
141234
141237
141238
141240
- したがって、複数のセッショントークンをキャプチャして分析し、セッショントークンがそれらに対するブルートフォース攻撃を許さない十分なランダム性を提供していることを確認することが重要
攻撃
- より現実的なシナリオでは、セッショントークンは表面上は十分なランダム性を提供しているように見える
- しかし、セッショントークンの生成は真にランダムではなく、セッショントークン生成ロジックを理解している攻撃者によって予測される可能性がある
セッショントークンは、ただのbase64エンコードされたデータの時とか
- これはCTFでガチであった
- このサイト最高
- 16進エンコードまたはURLエンコードされたデータにも注意を払うべき
echo -n dXNlcj1odGItc3RkbnQ7cm9sZT11c2Vy | base64 -d
user=htb-stdnt;role=user
- ご覧の通り、クッキーにはユーザーとセッションに結びついたロールに関する情報が含まれている
- しかし、データを改ざんすることを防ぐセキュリティ対策はない
- データを操作し、期待される形式に一致するようにbase64エンコードすることで、独自のセッショントークンを偽造できる
- これにより、管理者のクッキーを偽造することができて、ログインすることができる
echo -n 'user=htb-stdnt;role=admin' | base64
dXNlcj1odGItc3RkbnQ7cm9sZT1hZG1pbg==
セッショントークンの別のバリアントには、データシーケンスの暗号化の結果が含まれている
- 弱い暗号化アルゴリズムは、単純なエンコードと同様に、権限昇格や認証バイパスにつながる可能性がある
- 暗号化アルゴリズムの不適切な処理や、ユーザー提供データの暗号化関数の入力への挿入は、セッショントークン生成の脆弱性につながる可能性がある
セッション固定攻撃
- セッション固定攻撃 (Session Fixation) は、攻撃者が被害者の有効なセッションを取得できるようにする攻撃
- セッション固定攻撃に脆弱なウェブアプリケーションは、認証成功後に新しいセッショントークンを割り当てない
- もし攻撃者が被害者を、攻撃者によって選ばれたセッショントークンを使用するように誘導できれば、セッション固定攻撃によって攻撃者は被害者のセッションを盗み、そのアカウントにアクセスできるようになる
- たとえば、セッション固定攻撃に脆弱なウェブアプリケーションがHTTPクッキーの
session
にセッショントークンを使用していると仮定
セッション固定攻撃の流れ
- 攻撃者は、ウェブアプリケーションに認証することで有効なセッショントークンを取得する
- たとえば、セッショントークンが
a1b2c3d4e5f6
であると仮定する - その後、攻撃者はログアウトして自身のセッションを無効にする
- たとえば、セッショントークンが
- 攻撃者は、以下のリンクを送信して、既知のセッショントークンを使用するように被害者を誘導する
http://vulnerable.htb/?sid=a1b2c3d4e5f6
- 被害者がこのリンクをクリックすると、ウェブアプリケーションは
session
クッキーに提供された値を設定する
- 被害者は脆弱なウェブアプリケーションに認証する
- 被害者のブラウザはすでに攻撃者が提供したセッションクッキーを保存しているため、ログインリクエストと共にそれが送信される
- ウェブアプリケーションは新しいセッショントークンを割り当てないため、被害者は攻撃者が提供したセッショントークンを使用することになる
- 攻撃者は被害者のセッショントークン
a1b2c3d4e5f6
を知っているので、被害者のセッションを乗っ取ることができる