Skip to content
KitploitKITPLOIT
उपकरणएक्सप्लॉइटब्लॉग
Log in
जमा करें
उपकरणएक्सप्लॉइटब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

फ़ीडसंपर्कगोपनीयता© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
CVE-2026-19264 — CVE-2026-19264 - Postiz (< 2.22.1) में गंभीर अनप्रमाणित पाथ ट्रैवर्सल से पूर्ण इंस्टेंस टेकओवर। तकनीकी विवरण: डिकोड-ऑर्डर बायपास, JWT_SECRET एस्केलेशन, और अपस्ट्रीम फिक्स का विश्लेषण। | Kitploit
उपकरण/GitHubGitHub/darklycn1976/cve-2026-19264
भेद्यता विश्लेषणकोड विश्लेषणशोषणवेब एप्लिकेशन शोषणवेब सुरक्षालर्निंग और शिक्षा
GitHubdarklycn1976/cve-2026-19264

CVE-2026-19264

CVE-2026-19264 - Postiz (< 2.22.1) में गंभीर अनप्रमाणित पाथ ट्रैवर्सल से पूर्ण इंस्टेंस टेकओवर। तकनीकी विवरण: डिकोड-ऑर्डर बायपास, JWT_SECRET एस्केलेशन, और अपस्ट्रीम फिक्स का विश्लेषण।

रिपॉजिटरी देखें
91 महीना पहलेअभी तक समीक्षित नहीं
वेबसाइट

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

CVE-2026-19264 - Postiz में अनप्रमाणित पाथ ट्रैवर्सल से पूर्ण इंस्टेंस टेकओवर

CVE-2026-19264 - Postiz में अनप्रमाणित पाथ ट्रैवर्सल से पूर्ण इंस्टेंस टेकओवर

लेखक: कृथिक बाबू पी (@DarkLycn1976) प्रकाशित: 2026-08-10 CVE: CVE-2026-19264 गंभीरता: क्रिटिकल - CVSS 4.0 9.3 / CVSS 3.1 9.8 CWE: CWE-22 - प्रतिबंधित निर्देशिका में पाथनाम की अनुचित सीमा प्रभावित: gitroomhq/postiz-app < 2.22.1 सुधारित संस्करण: v2.22.1


TL;DR

Postiz स्थानीय रूप से संग्रहीत मीडिया को एक रूट के माध्यम से सर्व करता था जो URL-आपूर्ति किए गए पाथ सेगमेंट्स को अपलोड निर्देशिका के साथ जोड़ता था और परिणाम को वापस स्ट्रीम करता था - बिना किसी पाथ नॉर्मलाइज़ेशन, बिना किसी कंटेनमेंट जाँच, और बिना किसी प्रमाणीकरण के।

स्पष्ट ट्रैवर्सल पेलोड 404 लौटाता है, क्योंकि Next.js रूटिंग से पहले ../ सेगमेंट्स को समाप्त कर देता है। लेकिन URL-एन्कोडेड सेपरेटर रूट मैचिंग से बच जाते हैं और फ़ाइलसिस्टम कॉल के रास्ते में ठीक एक बार और डीकोड किए जाते हैं, हर जाँच के दूसरी ओर ट्रैवर्सल को पुनर्स्थापित करते हुए।

एक अनप्रमाणित हमलावर एप्लिकेशन प्रोसेस द्वारा पठनीय किसी भी फ़ाइल को पढ़ सकता था - जिसमें उसका अपना एनवायरनमेंट भी शामिल है, जिसमें JWT साइनिंग सीक्रेट होता है। क्योंकि Postiz उस सीक्रेट के साथ सत्र टोकन पर हस्ताक्षर करता है और उन्हें बिना किसी समाप्ति (expiry) क्लेम के जारी करता है, इसे प्राप्त करना एक फ़ाइल-रीड प्रिमिटिव को किसी भी उपयोगकर्ता के रूप में स्थायी, जाली बनाने योग्य सत्र में बदल देता है, जिसमें एक व्यवस्थापक भी शामिल है।

पूर्ण इंस्टेंस टेकओवर के लिए केवल एक अनप्रमाणित GET अनुरोध।


1. पृष्ठभूमि

Postiz एक ओपन-सोर्स सोशल मीडिया शेड्यूलिंग प्लेटफ़ॉर्म है - लिखने के समय लगभग 34,000 GitHub स्टार्स - जो Next.js फ्रंटएंड और NestJS बैकएंड के रूप में बनाया गया है। यह कनेक्टेड सोशल अकाउंट्स, शेड्यूल किए गए कंटेंट और बिलिंग को प्रबंधित करने के लिए एजेंसियों और छोटी टीमों द्वारा व्यापक रूप से सेल्फ-होस्ट किया जाता है।

सेल्फ-होस्टेड डिप्लॉयमेंट अपलोड किए गए मीडिया को ऑब्जेक्ट स्टोरेज के बजाय स्थानीय रूप से संग्रहीत कर सकते हैं। यह व्यवहार एक ही एनवायरनमेंट वेरिएबल द्वारा नियंत्रित होता है:

STORAGE_PROVIDER=local

यही वह मान है जो .env.example में भेजा जाता है, इसलिए जब तक वे जानबूझकर S3 या Cloudflare R2 कॉन्फ़िगर नहीं करते, अधिकांश सेल्फ-होस्टर यही चलाते हैं।

2. हमले की सतह

जब स्थानीय स्टोरेज सक्रिय होता है, next.config.js सार्वजनिक पाथ /uploads/:path* को एक आंतरिक API रूट पर रीराइट करता है:

apps/frontend/src/app/(app)/api/uploads/[[...path]]/route.ts

कोई बग शामिल होने से पहले ही दो गुण इस रूट को दिलचस्प बनाते हैं:

  1. यह अनप्रमाणित है। कोई फ्रंटएंड मिडलवेयर इसे सुरक्षित नहीं करता। सार्वजनिक मीडिया सर्व करना ही उद्देश्य है, इसलिए किसी सत्र की आवश्यकता नहीं है।
  2. यह कैच-ऑल है। [[...path]] वैकल्पिक कैच-ऑल सेगमेंट का अर्थ है कि शेष हर पाथ घटक एक ऐरे के रूप में आता है जिसे हैंडलर अपने अनुसार व्याख्या करने के लिए स्वतंत्र है।

जब STORAGE_PROVIDER local के अलावा कुछ भी होता है, तो रीराइट /404 की ओर इंगित करता है और हैंडलर अगम्य हो जाता है। वह कॉन्फ़िगरेशन गेट ही एकमात्र चीज़ है जो किसी डिप्लॉयमेंट और इस बग के बीच खड़ी है।

3. संवेदनशील कोड

v2.22.1 से पहले का हैंडलर:

export const GET = async (request: NextRequest, context) => {
  const { path } = await context.params;
  const filePath =
    process.env.UPLOAD_DIRECTORY + '/' + (path ?? []).join('/');

  const response  = createReadStream(filePath);
  const fileStats = statSync(filePath);
  // ... stream the file back to the caller
};

चार पंक्तियों में तीन दोष:

  • कोई नॉर्मलाइज़ेशन नहीं। path.normalize(), path.resolve() - इनमें से कोई भी कॉल नहीं किया जाता। जो भी सेगमेंट आते हैं, वे यथावत जोड़ दिए जाते हैं।
  • कोई कंटेनमेंट जाँच नहीं। कोई भी चीज़ सत्यापित नहीं करती कि परिणामी filePath अभी भी UPLOAD_DIRECTORY के अंदर है।
  • स्ट्रिंग कॉन्केटनेशन, पाथ जॉइनिंग नहीं। + '/' + घटकों को टेक्स्ट के रूप में मानता है, न कि अर्थ-सहित पाथ के रूप में।

परिणाम सीधे createReadStream() में जाता है और बाइट्स को फ़ाइलनाम से अनुमानित MIME प्रकार के साथ कॉलर को स्ट्रीम किया जाता है। एक्सटेंशन की कोई अनुमति-सूची (allow-list) नहीं है और कोई कंटेंट फ़िल्टर नहीं है।

4. स्पष्ट पेलोड क्यों विफल होता है

पाठ्यपुस्तकीय (textbook) हमला है:

GET /uploads/../../../etc/passwd

Postiz पर यह 404 लौटाता है, और यही 404 पूरा कारण है कि यह बग मिलने तक जीवित रहा।

Next.js रूटिंग के दौरान अनुरोध पाथ को नॉर्मलाइज़ करता है। रूटर यह तय करने से पहले कि किस हैंडलर को आमंत्रित किया जाए, कच्चे ../ सेगमेंट्स को समाप्त कर दिया जाता है। जब तक अनुरोध कैच-ऑल तक पहुँचता है, ट्रैवर्सल पहले ही समाप्त किया जा चुका होता है - या तो पाथ कहीं ऐसी जगह रिज़ॉल्व होता है जहाँ कोई मेल खाने वाला रूट नहीं होता, या यह डॉट-सेगमेंट्स के बिना वापस /uploads के अंदर रिज़ॉल्व होता है।

जल्दी से परीक्षण करने वाले किसी व्यक्ति के लिए, वह 404 "फ्रेमवर्क इसे संभाल लेता है" जैसा पढ़ा जाता है। यह एक वास्तविक, कार्यशील सुरक्षा है। समस्या यह नहीं है कि यह अनुपस्थित है - समस्या यह है कि यह पाइपलाइन में कहाँ चलता है।

5. बाइपास - एक डीकोडिंग-क्रम बेमेल

रूट मैचिंग और अनुरोध हैंडलर समान संख्या में पर्सेंट-डीकोडिंग पास नहीं करते।

यदि सेपरेटर पर्सेंट-एन्कोडेड हैं, तो अनुक्रम रूट मैचिंग के दौरान पाथ सेपरेटर नहीं होता। %2e%2e%2f केवल एक अपारदर्शी स्ट्रिंग है - निष्क्रिय टेक्स्ट जिसे नॉर्मलाइज़र छूने का कोई कारण नहीं रखता। यह रूटिंग से सुरक्षित गुज़रता है, कैच-ऑल द्वारा मैच किया जाता है, और हैंडलर के params में जाते समय डीकोड हो जाता है, जहाँ यह फिर से ../ बन जाता है।

उस बिंदु पर इसे UPLOAD_DIRECTORY के साथ जोड़ दिया जाता है और createReadStream() को सौंप दिया जाता है - रूटिंग से परे, नॉर्मलाइज़ेशन से परे, हर उस नियंत्रण से परे जो इसे रोक सकता था।

कार्यशील रूप:

GET /uploads/%2e%2e%2fsecretdir%2fsecret.txt        → 200, file outside the upload directory
GET /uploads/..%2f..%2f..%2fetc%2fpasswd            → 200
GET /uploads/%2e%2e%2f%2e%2e%2f...%2fetc%2fpasswd   → 200, returned the real /etc/passwd

डबल-एन्कोडिंग काम नहीं करती - %252e एकल डीकोड पास के माध्यम से शाब्दिक बना रहता है और कभी डॉट नहीं बनता। ठीक एक परत एन्कोडिंग सबसे उपयुक्त है, जो एक उपयोगी अनुस्मारक है कि "और कठिन एन्कोड करो" कोई रणनीति नहीं है।

जिस सिद्धांत (invariant) को धारण करना है:

डीकोडिंग पूर्ण होने से पहले चलने वाला नियंत्रण सिंक (sink) की सुरक्षा नहीं कर रहा है।

6. एस्केलेशन - मनमाने पठन से इंस्टेंस टेकओवर तक

फ़ाइल-रीड प्रिमिटिव अपने आप में High है। इसे Critical बनाने वाली चीज़ है कि यह किस तक पहुँचता है।

चरण 1 - एनवायरनमेंट पढ़ें। Node प्रोसेस का अपना कॉन्फ़िगरेशन डिप्लॉयमेंट रूट में डिस्क पर होता है। .env अन्य चीज़ों के अलावा यह देता है:

  • JWT_SECRET - सत्र टोकन हस्ताक्षर कुंजी
  • DATABASE_URL - पूर्ण Postgres क्रेडेंशियल्स
  • कनेक्टेड प्रोवाइडर के OAuth सीक्रेट्स और बिलिंग कुंजियाँ

चरण 2 - सत्र जाली बनाएँ। Postiz jsonwebtoken के माध्यम से HS256 का उपयोग करके JWT_SECRET के साथ सत्र टोकन पर हस्ताक्षर करता है। महत्वपूर्ण रूप से, टोकन बिना किसी expiresIn के जारी किए जाते हैं, इसलिए एक जाली टोकन अनिश्चित काल तक मान्य रहता है।

चरण 3 - कोई भी बन जाएँ। प्रमाणीकरण मिडलवेयर id क्लेम का उपयोग करके डेटाबेस से उपयोगकर्ता को पुनः-रिज़ॉल्व करता है। यह जानबूझकर टोकन से isSuperAdmin जैसे क्लेम पर भरोसा नहीं करता - अच्छा डिज़ाइन - लेकिन एक बार जब आप किसी भी id पर हस्ताक्षर कर सकते हैं तो वह सख्ती अप्रासंगिक हो जाती है। { id: <victim user id> } पर हस्ताक्षर करने से एक ऐसा सत्र उत्पन्न होता है जो वैध लॉगिन से अप्रभेद्य होता है:

read .env  →  JWT_SECRET  →  sign({ id: victim })  →  authenticated as victim, forever
टूल डाउनलोड करें