# 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)