Shikata Ga Nai

Private? There is no such things.

An Interesting Account Takeover!!を訳してみた

Hello there, ('ω')ノ

 

興味深いアカウントの乗っ取りを。

 

脆弱性:

 IDOR

 アカウントの乗っ取り

 弱い暗号化

 パスワードリセットの欠陥

 

記事:

 https://infosecwriteups.com/an-interesting-account-takeover-3a33f42d609d

 

IDORと弱い暗号化により、完全なアカウントの乗っ取りが発生して。

多くのアカウント乗っ取りについて読んでいると。

トークンを盗むために「X-Forwarded-Host」ヘッダを使用していて。

 

今回のバグは「パスワードリセット」機能に存在し。

ユーザからの1回の操作なしで完全なアカウントの乗っ取りを可能にして。

これは、IDOR、少しの暗号化、および多くのディレクトリファジングの組合せで。

仮に「example.com」と呼ぶことに。

まず、通常のパスワードリセットがどのように機能するかを確認することに。

 

1.ユーザは「example.com/php/login_or_password_forgotten」にアクセスし。

 プロファイルIDと名前を入力してパスワードのリセットを要求して。

 

2.プロファイルIDと名前が検証され、「STATE」パラメータが生成されて。

 

STATE=eJxdkN1OwzAMhd8lDzA1XffT9GpMDE2gdmKTuIxM4paILilJJhBo747DfjRxlfhzYp9zGpHPBduaryiXzqN8wdeVhz1%2BOv8utxEiMsHFTxATwcJfWYEoEpgKppxtTZfIOJGSSG%2FQRmkGVgXBC8H4ZDYq8hHnfMSnZaL0r3cKekwFTUUrH%2B7SnXT0YLsDdP9aRxo1E6y96hrAR4ueVY3Iy1v1i81abk7Ny8loIWkjKQcLe1bVNDrPBHuDIHuEYGwnyUf0oCKrXkWWhFPfo3KdNd%2Bob6k0FiOt34cLJTvy4wD9FZANCVp7DCFtO4vfPS%2Fq7WK5Wze13DWP93WyOM4FgxJn7VgrBS2fTzVqzDLFVY4cs2Le6vSuTMmESL5P0RT8bHrjXWt68j0M8sl1xjZ%2BAyFQSHrlfOdidJbyO%2F4CvKKcYg%3D%3D55840ad4a2f32819aa5da2cf48288290

 

3.この後、パスワードリセットリンクがユーザ登録メールに送信されて。

 

https://example.com/php/login_or_password_forgotten?k=789c0dc8610a80200c06d0bbec049bc9d26f870921834192a4ffa2bbd7fbf90a029e810c9adeea98a5753287a844e16555b1016150bfafc3cfbaf94eff2450e494

 

4.これで、ユーザはリンクをクリックした後にダッシュボードに移動して。

 パスワードを変更できて。

 

?k」パラメータは少し疑わしいように見えたので。

すぐにコピーしてCyber​​Chefに貼り付け。

暗号化された文字列かどうかを確認すると。

それは暗号化された+圧縮された文字列で。

 

https://gchq.github.io/CyberChef/

f:id:ThisIsOne:20220323211826p:plain

 

f:id:ThisIsOne:20220323211754p:plain

 

最初にZlibでdeflateされ、次にdeflateされた文字列が16進数を使用して。

暗号化されたので。

 

トークン:    “789c0dc8610a80200c06d0bbec049bc9d26f870921834192a4ffa2bbd7fbf90a029e810c9adeea98a5753287a844e16555b1016150bfafc3cfbaf94eff2450e494a2e640f67ebc89137aade927d25a020ab2535ab4b5c9dc4fd1"

 

復号化:

“a:2:{s:9:”timestamp”;i:1614104013;s:10:”profile_id”;s:8:”40884692";}”

 

復号化された文字列は、2つの重要な変数「profile_id」と「timestamp」で。

構成されて。

すぐに2番目のアカウントのトークンを偽造し。

それを使用してパスワードを変更して。

 

偽造トークン: 789c0dc8510a85201005d0bdcc0ac6f25da6eb62427806034992fe457bb7df93b9f0e9dc28c36be923d726c919107ec0aa40ea0c4a69f775f85976ffcb2746891a610693f44ebe171387

 

しかし、完全に間違っていてリンクが無効で。

それから、元のトークンと偽造されたトークンの長さが異なることに気付くことに。

 

f:id:ThisIsOne:20220323211600p:plain

 

元のトークンと偽造されたトークンには32文字の違いがあって。

サーバがその32文字の代わりにジャンク値を受け入れなかったため。

これは大きな問題で。

両方のトークンが同じ値に復号化されていて。

 

“a:2:{s:9:”timestamp”;i:1614104013;s:10:”profile_id”;s:8:”40884692";}”

 

Zlib圧縮についてもっと検索し始めて。

そして、BC89137Aを取得した後にAdler-32_Checksum()関数を使用すると。

ZlibにADLER32チェックサムが含まれていることがわかって。

このチェックサムが元のトークンに存在することに注意して。

Zlibでは、このチェックサム以降は。

すべて圧縮ストリームの一部ではないため無視されて。

これが、長さが異なっていても両方のトークンが同じ結果をもたらす理由で。

 

そのため、現在の課題は32ビット文字列を見つけることで。

トークン関連の作業はすべてクライアント側で行われていたので。

JSファイルで何かを見つけることができて。

 

JSファイルを調べた後、エンドポイント「/php/user」が見つかって。

ディレクトリをブルートフォース攻撃することにし。

最終的にエンドポイント「https://example.com/php/user/example/」を見つけて。

このエンドポイントには「Transction_Token」という名前の文字列があって。

 

f:id:ThisIsOne:20220323211445p:plain



まとめ:

 ページが更新されるたびに「Transaction _Token」が変更されるため。

 この攻撃は正確である必要があったので。

 全体を自動化するためのPythonスクリプトを作成して。

 2番目のアカウントのトークンを生成し、それを使用してパスワードを変更して。

 

重要なポイント:

 トークンがある場合、それがクラックされる可能性があって。

 JSファイルにはWebアプリの動作に関する非常に重要な情報が含まれているため。

 手動でJSファイルを1回読んで。

 

Best regards, (^^ゞ