# Một số khái niệm
## 1. MIME Types
MIME (Multipurpose Internet Mail Extensions) là giao thức mở rộng thư điện tử Internet đa mục đích cho phép người dùng trao đổi các tệp tin, các dữ liệu. Các dữ liệu này gồm có các loại như video, âm thanh, chương trình ứng dụng hay hình ảnh.
Cấu trúc: Loại MIME phổ biến nhất chỉ bao gồm hai phần: `type` và `subtype` được ngăn cách bằng dấu `/` và không có khoảng trắng ở giữa:
```
type/subtype
```
- `type`: đại diện cho danh mục chung mà dữ liệu rơi vào, ví dụ như video hoặc text.
- `subtype`: xác định chính xác kiểu dữ liệu của `type` đã chỉ định.
- Ví dụ: đối với MIME `text`, subtype có thể là `plain` (plain text), html (mã nguồn HTML), hoặc calendar (đối với iCalendar/`.ics`).
Một tham số tùy chọn có thể được thêm vào để cung cấp thêm chi tiết:
```
type/subtype;parameter=value
```
- Ví dụ: với type `text`, bạn có thể thêm tùy chọn tham số `charset` để chỉ định bộ ký tự được sử dụng cho các ký tự trong dữ liệu. Nếu `charset` không được chỉ định, mặc định là ASCII. Chẳng hạn để chỉ định tệp văn bản UTF-8, loại MIME `text/plain;charset=UTF-8` được sử dụng.
Các loại MIME không phân biệt chữ hoa chữ thường nhưng thường được viết bằng chữ thường. Các giá trị tham số có thể phân biệt chữ hoa chữ thường.
Một số loại MIME quan trọng: `application/octet-stream, text/plain, text/css, text/html, text/javascript, image types (image/apng, image/avif, image/gif, image/jpeg, image/png, image/svg+xml, image/webp)`
MIME header sẽ chứa các phần con khác nhau như:
- MIME-Version: Thư có định dạng MIME với giá trị là 1, 0.
- Content-Type: Tiêu đề mô tả phương tiện bên trong nội dung thư.
- Content-Disposition: Tiêu đề được xác định dưới dạng trình bày email với các vấn đề về tự động hiển thị thông báo (Inline), tệp đính kèm sẽ không hiển thị tự động và RFC 2183 với mục đích chỉ định tiêu đề để bố trí nội dung.
- Content-Transfer-Encoding: Tiêu đề cho thấy loại lược đồ mã hóa nhị phân thành dạng văn bản đã được dùng ngoài mã hóa ban đầu chỉ định trong tiêu đề nội dung hay chưa.
## 2. Header Content-type
Chỉ định loại nội dung chứa trong nội dung thư, chẳng hạn như text/html cho tài liệu HTML. Trong phản hồi, tiêu đề Content-Type cung cấp cho khách hàng loại nội dung thực tế của nội dung được trả về.
Cú pháp:
```
Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
```
Các chỉ thị cho Content-Type là `media type`, `charset`, và `boundary`
- `media-type`: loại MIME của tài nguyên hoặc dữ liệu.
- `charset`: Chuẩn mã hóa ký tự. Không phân biệt chữ hoa chữ thường, ưu tiên sử dụng chữ thường.
- `boundary`: Đối với các thực thể nhiều phần (multipart), boundarylệnh này là bắt buộc. Lệnh này bao gồm từ 1 đến 70 ký tự từ một tập hợp các ký tự (và không kết thúc bằng khoảng trắng). Nó được sử dụng để gói gọn ranh giới của nhiều phần của tin nhắn.
## 3. File Signatures

File Signatures là số nhận dạng duy nhất được nhìn thấy ở đầu tệp. Nó cho bạn biết loại tệp và cung cấp thông tin về dữ liệu chứa trong đó. Máy tính sử dụng nó để xác định cách đọc hoặc sử dụng ứng dụng nào để mở nó. Nếu người dùng lưu file sử dụng sai đuôi mở rộng, máy tính sẽ trả về lỗi không mở được.
Chữ ký tệp cũng đảm bảo dữ liệu gốc được lưu trữ trong tệp vẫn còn nguyên vẹn và không bị sửa đổi. Những điều này làm cho chữ ký tệp trở thành một hình thức xác minh cần thiết, đặc biệt là chống lại vi-rút máy tính mà các chuyên gia pháp y kỹ thuật số thường xác định.
## 4. File Upload Vulnerabilities
### 4.1. File Upload Vulnerabilities
Lỗ hổng upload file là lỗ hổng phát sinh khi máy chủ web cho phép người dùng tải tệp lên mà không xác thực đầy đủ những thứ như tên, loại, nội dung hoặc kích thước của chúng.

Khác với các loại lỗ hổng khác, File Upload được sử dụng tùy thuộc vào mục đích của người sử dụng. Kẻ tấn công có thể sử dụng File Upload để nhúng 1 đoạn mã độc lên trang web, điều này có thể dẫn đến việc đưa 1 trang lừa đảo lên trang web hoặc là đánh sập luôn trang web đó.
### 4.2. Web Shells
Web shell là 1 dạng mã độc có nhiều chức năng để hỗ trợ kẻ tấn công chiếm quyền quản lý hệ thống. Webshell có thể xây dựng bằng nhiều ngôn ngữ lập trình khác nhau và thường được viết bằng chính ngôn ngữ mà website đó đang sử dụng.
Chức năng cơ bản là tải tệp tin lên máy chủ, kết nối đến cơ sở dữ liệu, vượt qua các cơ chế bảo mật, cấu hình, tấn công bruteforce, Get Root, Local Attack...
### 4.3. Exploit
Thông thường, đối với các web site có chức năng upload file chẳng hạn như khi ta đăng 1 file ảnh lên 1 trang web. Chúng ta có thể lợi dụng tính năng này để tải shell lên hệ thống. Tuy nhiên, điều này đã được phòng tránh bằng cách sử dụng một số filters để ngăn chặn khả năng tải lên mã độc. Do đó, để có thể khai thác được lỗ hổng này, chúng ta cần phải vượt qua các filters đó, bao gồm:
- Client side filters
- Content/type Vertification
- The extension Black listing
- The extension White listing
- The content length and malicious script checks
#### a. Client side filters
Client Side Filters là một kiểu xác thực các yêu cầu khi được gửi lên máy chủ.
Để bypass qua client side filter , chúng ta có thể sử dụng các cách như:
- Tắt javascript của trình duyệt thông qua Developer Tools của Chrome, Firefox
- Giả mạo yêu cầu gửi lên (Proxify the application and tamper the request)
- Giả mạo dữ liệu bằng cách sử dụng firefox addon.
#### b. Content/type Vertification
Đây là kiểu xác thực mà nhà phát triển yêu cầu file upload trong trường hợp này bắt buộc phải là kiểu **image** thì mới được chấp thuận.
Tuy nhiên, `Content/type` lại có thể thay đổi trước khi đến server cho nên chúng ta chỉ cần đổi từ type `application/octet-stream` sang `image/`(kiểu định dang ảnh của bạn) ví dụ như là `image/jpeg`:

#### c. The extensions Black listing
Black list tức là 1 danh sách đen các shell bị các nhà phát triển web chặn nhằm chống việc tải shell lên trang web.
- Kẻ tấn công có thể có thể đổi đuôi extension thành `shell.php1`, `shell.php2`, `shell.php3`,... Và thậm chí shell vẫn có thể chạy với các đuôi như `.pl` hoặc `.cgi`
- Có thể check xem bộ lọc có phân biệt chữ hoa chữ thường không : `shell.Php1`, `shell.PHP2`,...
- Nhà phát triển có thể tạo 1 regex kiểm thử `.jpg`, vì vậy chúng ta có thể thử cách chống extension như là `shell.jpg.php`.
- Có thể tải shell lên bằng cách sử dụng file `.htaccess`. Tập tin `.htaccess` (hypertext access) là một file có ở thư mục gốc của các hosting và do apache quản lý, cấp quyền. File `.htaccess` có thể điều khiển, cấu hình được nhiều thứ với đa dạng các thông số, nó có thể thay đổi được các giá trị được set mặc định của apache.
#### d. The extentions White listing
Trái ngược với black list, có một số trang web lại yêu cầu bạn bắt buộc phải sử dụng những extension được liệt kê trong white list như là `.jpg`, `.jpeg`, `.gif`,...
- **Null Byte Injection**: là một kỹ thuật khai thác trong đó sử dụng các ký tự null byte URL-encoded (ví dụ: `00%`, hoặc `0x00` trong hex) được người dùng cung cấp. Một null byte trong các URL được đại diện bởi`00%`, trong ASCII là một `” ”` (giá trị null ) trong quá trình lây nhiễm. Phần sau` %00` sẽ được hiểu là giá trị null, là giá trị kết thúc của chuỗi nên tệp được tải lên với tên là `shell.php`.
```
shell.php%00.jpg
```
- **Bypass using Double Extension**: Trong một số trường hợp, chúng ta có thể sử dụng `shell.php.jpg`, `shell.php;.jpg`, `shell.php:jpg` để thực thi lệnh shell, nhưng lổ hỗng này, thường là do cấu hình của web server hoặc hệ điều hành.
- **Invalid Extension Bypass**: 1 số lỗi từ phía máy chủ như là nếu chúng ta sử dụng extension `.test` thì hệ điều hành sẽ không nhận ra. Cho nên chúng ta có thể tải lên tệp `shell.php.test` và hệ điều hành sẽ bỏ qua `.test` và thực thi shell.
#### e. The Content Length and Malicious script checks
Đối với một số trang web nhất định, chúng ta sẽ phải đối mặt với kiểm tra độ dài của file upload. Với những web như vậy, chúng ta sẽ sử dụng những lệnh shell ngắn để bypass như là:
```
<?system($_GET[0]);
```
### 4.4. Phòng chống
- Xác thực và kiểm soát các tệp được tải lên
- Kết hợp nhiều cơ chế ngăn chặn đảm bảo an toàn đối với các file upload: Có thể kết hợp white list, kiểm tra nội dung file, kiểm tra tên file có đúng định dạng, không chứa ký tự không mong muốn, ...
- Giới hạn dung lượng, quyền của thư mục
- Giới hạn các loại tệp mà bạn cho phép tải lên ở những loại cần thiết cho trải nghiệm người dùng
- Đảm bảo tên tệp không chứa bất kỳ chuỗi con nào có thể được hiểu là một thư mục hoặc một chuỗi truyền tải ( `../`)
- Thường xuyên thực hiện rà soát, tái kiểm tra các tệp tin trong hệ thống.
# Code
Để upload file được thì chúng ta cần phải sử dụng biến `$_FILES` để nhận dữ liệu file gửi lên từ Server.
```php
$_FILES["nameInputFile"]["properties"]
```
Trong đó:
- properties: là tên thuộc tính mà PHP cung cấp cho chúng ta bao gồm 5 thuộc tính:
- name: Tên của file khi upload lên
- type: Kiểu file khi upload (VD: file ảnh loại `.gif, .png, .jpg`,...)
- tmp_name: Đường dẫn tạm của file khi upload
- error: Trạng thái lỗi khi upload.
- size: Dung lượng file khi upload lên được tính bằng đơn vị byte
```php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload File</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" id="txtFile" name="txtFile"><br><br>
<input type="submit" value="Upload" name="isSubmit"><br><br>
</form>
<div id="result">
<?php
if (isset($_POST['isSubmit'])) {
//thiết lập nơi lưu file
$save = './upload_t/';
//lấy đường dẫn đến file đã upload trên server
$target_file = $save . basename($_FILES['txtFile']['name']);
//Hàm basename() dùng để lấy phần đuôi của đường dẫn path
//lấy định dạng loại file uopload. VD: .jpg, .png,...
$img_file_type = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));
//Hàm strtolower(): biến ký tự viết hoa thành ký tự viết thường
//Hàm pathinfo(): lấy thông tin về đường dẫn truyền vào.
$file_name = ""; //biến để lưu tên file
if (isset($_FILES['txtFile'])) {
$file_name = $_FILES['txtFile']['name'];
if ($_FILES['txtFile']['error'] > 0) { //kiểm tra lỗi
echo 'Please select file.';
} else {
if (file_exists($target_file)) { //kiểm tra file đã tồn tại chưa
echo "File has already existed.";
} else if ($_FILES['txtFile']['size'] > 100000000) { // kiểm tra độ lớn của file
echo "<script type='text/javascript'>alert('Your file is too large!');</script>";
} else if (
$img_file_type != 'jpg' && $img_file_type != 'png' &&
$img_file_type != 'jpeg' && $img_file_type != 'gif'
){ //kiểm tra định dạng file
echo "<script type='text/javascript'>alert('Only JPG, PNG, JPEG, GIF files are allowed.');</script>";
} else {
move_uploaded_file($_FILES['txtFile']['tmp_name'], $save . $file_name);
//Hàm move_uploaded_file() dùng để di chuyển tập tin được tải lên vào một nơi được chỉ định
echo "File " . basename($file_name) . " has been uploaded! <br><br>";
echo "<a href = 'http://localhost/phpform/upload_t/" . $file_name . "'>See it here!</a>";
}
}
} else {
echo "There was an error uploading your file!";
}
}
?>
</div>
</body>
</html>
```
**Kết quả**

# Write-up
https://github.com/aQ05/Write-up.training/blob/main/File_upload.md