MySQL and MariaDB Security Review
MySQL and MariaDB grant access by account and host pattern, and a wildcard host reaches further than one application needs. We review accounts, grants, remote access and file privileges on your database. CREST-certified testers, fixed price from £2,740 for a 2-day single-system scope, quoted within 24 hours.
- Unlimited retesting
- Unlimited pre-retesting
- No hidden fees
“I would highly recommend EJN Labs to any organisation seeking reliable, detailed, and well-managed penetration testing services, particularly for government or enterprise-level projects.”
“There wasn’t another company we could find that could deliver what we needed in the timeframe we needed. The client loved it, and we got instant ROI from the engagement.”
A ‘%’ host or an ALL PRIVILEGES grant can let one MySQL account reach every database on the server, far beyond the one it was created for.
Why MySQL access comes down to the host pattern and the grant
MySQL’s own documentation sets out account name syntax as ‘user_name’@’host_name’, where the host part is optional and an account created with no host at all is equivalent to ‘user_name’@’%’, a wildcard that matches a connection from any host at all. ALL PRIVILEGES is shorthand for every privilege available at the level it is granted, and MySQL’s GRANT reference is explicit that this shorthand covers everything except GRANT OPTION and PROXY, so a single GRANT ALL ON *.* statement reaches every database on the server unless the account is scoped down first. GRANT OPTION compounds this: MySQL’s own privilege-granting guidance warns that two users with different privileges who both hold GRANT OPTION are able to combine privileges, so an account that can grant as well as hold access can end up handing out reach it was never meant to keep.
The FILE privilege gets its own warning in that same guidance, which states plainly that FILE can be abused to read into a database table any file the server can read on the host, including every world-readable file and anything in the server’s data directory, after which the table is read out with an ordinary SELECT. The secure_file_priv variable is meant to contain that risk, and MySQL’s LOAD DATA documentation is direct that leaving the variable empty, which it calls insecure, means a file only has to be readable by the server, with no directory restriction at all. The LOCAL variant of LOAD DATA sidesteps FILE entirely, needing only the server’s local_infile setting and the client’s cooperation, and MySQL’s own security guidance warns that a compromised or malicious server can ask the client to send a different file than the one named in the statement, a risk that matters most where the connecting client is a web application.
Encrypted transport is available but not compulsory unless you turn it on: MySQL’s own configuration guidance confirms that the server permits but does not require encrypted connections by default, and only enabling require_secure_transport forces every client onto an encrypted connection or a local socket. Authentication defaults have moved too, with caching_sha2_password now the default plugin for new MySQL accounts, while MariaDB’s own documentation confirms that its unix_socket plugin is installed and used by ‘root’@’localhost’ by default, matching the connecting operating system user rather than a stored password, a verified difference rather than an assumed one. Where MySQL runs also changes what we can test: on a managed service such as Amazon RDS, Aurora MySQL, Azure Database for MySQL or Google Cloud SQL, the provider controls the host and much of the surrounding configuration, while your accounts, grants and application code remain yours to secure. For estates running several database engines, see our wider database security review.
SCOPE
What we review in a MySQL or MariaDB database
Account and Grant Scope: Host Wildcards and ALL PRIVILEGES
MySQL account names follow the pattern ‘user_name’@’host_name’, and MySQL’s own documentation confirms that creating an account with no host at all is equivalent to ‘user_name’@’%’, a wildcard that matches a connection from any host. ALL PRIVILEGES is shorthand for every privilege available at the level it is granted, except GRANT OPTION and PROXY, so a single GRANT ALL ON *.* statement reaches every database on the server unless the account and its host are scoped down first. We map every account’s host pattern, grants and GRANT OPTION reach against what it is actually used for, flagging a service account left on a ‘%’ host or holding more than its application needs.
Root and Administrative Accounts
The MySQL server creates a ‘root’@’localhost’ superuser account during installation, and MySQL’s own documentation warns that initialising the server with –initialize-insecure rather than –initialize leaves that account with an empty password until someone sets one. On MariaDB the same account authenticates through the unix_socket plugin by default, matching the connecting operating system user rather than a stored password, a difference we have verified against MariaDB’s own documentation. We test which accounts hold superuser or equivalent administrative privileges and whether that access still matches who is meant to administer the server.
Remote Access and bind-address
Which network interfaces MySQL accepts connections on is controlled by the bind_address setting, and since MySQL 8.0.14 the server can also expose a separate administrative connection interface, with its own address and port, alongside the normal client interface. We check what bind_address and any administrative interface are actually set to on every instance in scope, whether a port reachable from outside the intended network was meant to be, and whether the administrative interface is exposed anywhere a normal client connection would not need to reach.
The FILE Privilege and secure_file_priv
MySQL’s own privilege-granting guidance singles out FILE for particular caution, warning that it can be abused to read into a database table any file the server can read on the host, including every world-readable file and anything in the server’s data directory, after which the table is read out with an ordinary SELECT. The secure_file_priv system variable is meant to contain that risk, and MySQL’s documentation is direct that leaving it empty, which it calls insecure, means a file only has to be readable by the server with no directory restriction at all. We test who holds FILE, what secure_file_priv is actually set to, and whether SELECT … INTO OUTFILE or LOAD DATA could reach a file outside the intended directory.
LOAD DATA LOCAL INFILE
A LOAD DATA LOCAL statement needs no FILE privilege at all, working instead whenever the server’s local_infile system variable and the connecting client both allow it, with the file read from the client host rather than the server. MySQL’s own security guidance warns that a compromised or malicious server can ask the client to transfer a different file than the one named in the statement, reading anything the connecting client process has access to, a risk it says matters most where that client is a web application. We test whether local_infile is enabled on the server and in the application’s database driver, and whether an injection point could be used to request an arbitrary local file.
Transport Protection: require_secure_transport and TLS
MySQL’s –ssl option permits but does not require encrypted connections by default, so a client can still connect in plain text unless the server is configured to stop it. Enabling the require_secure_transport system variable closes that gap, since MySQL’s documentation confirms it rejects any connection that is not TCP/IP with SSL, a Unix socket file, or Windows shared memory. We test whether require_secure_transport is enabled, which cipher suites and TLS versions the server accepts, and whether any account is still permitted to authenticate over an unencrypted connection.
Authentication Plugins
caching_sha2_password has been the default authentication plugin for new MySQL accounts since MySQL 8.0, in place of the older mysql_native_password plugin for accounts created without an explicit choice. MariaDB takes a different default for its own superuser account: the unix_socket plugin is installed and used by ‘root’@’localhost’ by default, authenticating the connecting operating system user rather than checking a stored password, a difference we note only because we have verified it against MariaDB’s own documentation. We test which authentication plugin every account actually uses and whether any account still relies on a weaker or deprecated method.
Stored Routines: DEFINER and SQL SECURITY
MySQL grants the EXECUTE and ALTER ROUTINE privileges to a stored routine’s creator automatically, and the default SQL SECURITY characteristic for a routine is DEFINER, which MySQL’s documentation confirms lets any user with access to the routine’s database execute it. A DEFINER routine created by a highly privileged account and left in place after that account should have lost its own access can quietly hand its caller far more than the EXECUTE privilege alone suggests. We review every stored routine’s DEFINER account and SQL SECURITY setting against who is allowed to call it.
Backup Handling, Dump Files and Replication Privileges
mysqldump is MySQL’s own backup utility, and the SQL it writes out reproduces the database’s structure and data as plain statements, so a dump file left on disk or copied off the server carries the same sensitivity as the database itself. A replication account’s access is defined by ordinary GRANT statements, and MySQL’s replication documentation shows a PRIVILEGE_CHECKS_USER account being scoped down to exactly the statements its applier thread needs to run rather than given broad administrative rights. We test where backup and dump files are written and who can read them, and whether replication accounts hold more than the channel they serve requires.
Managed MySQL: RDS, Aurora, Azure and Cloud SQL
On a managed service the provider controls the host: Amazon RDS and Aurora MySQL support IAM database authentication for MariaDB, MySQL and PostgreSQL alike, issuing a short-lived signed token in place of a stored password; Azure Database for MySQL Flexible Server adds a separate Microsoft Entra administrator account alongside the native MySQL one, and can be set to accept Entra sign-in only; and Google Cloud SQL for MySQL automatically grants new built-in-authentication users the cloudsqlsuperuser role, defaulting its SSL enforcement mode to allow unencrypted connections unless you change it. We test the accounts, grants and transport settings you control on whichever of these you run, confirming with you during scoping exactly what the provider manages instead.
OUR PROCESS
MySQL and MariaDB Security Review: From Scope to Attestation
Scope and Access
We agree which MySQL or MariaDB instances, schemas and accounts are in scope, plus a database account for every privilege tier you want tested and, where relevant, an admin or cloud console account for the managed service it runs on.
Account and Privilege Mapping
We map every account’s host pattern, grants and GRANT OPTION reach, plus its authentication plugin and any DEFINER routines it owns, against who should actually hold that access.
Manual Testing
A CREST-certified tester manually tests remote access and transport encryption, the FILE privilege and LOAD DATA LOCAL configuration, and backup and replication access, chaining findings where they compound.
Attestation and Retest
You get a technical report with CVSS scores and reproduction steps, a walkthrough call, a free retest once fixes are deployed, and an attestation letter for auditors.
CREDENTIALS
Verified Accreditations Auditors Accept
Every credential below is independently verifiable. UK procurement teams, FCA supervisors, ISO 27001 / SOC 2 auditors, and cyber insurance underwriters all recognise these standards.
GET YOUR QUOTE
Get a CREST MySQL pen test quote in 24 hours
A fixed-price quote back in one business day, from a named CREST assessor. No sales pipeline, no chasing.
- CREST and IASME accredited. Testing your auditors and clients already recognise.
- Fast-track testing within 24 hours where required. Free retest of every fix included.
- Live findings via your client portal, not a four-week PDF.
- Fixed price from £3,500 for a single-role, single-app scope, agreed up front. Most engagements run £5,000 and up. No day-rate surprises.
Under NDA Further named references available on a scoping call.
- We reply within one business day with a fixed-price quote from a named CREST assessor.
- You approve the scope and we book a start date, usually within 24 hours.
- Live findings land in your client portal as we test, with a free retest of every fix.
Get your fixed pen test quote in 24 hours
Quote request received
We will reply within one business day with your fixed-price quote from a named CREST assessor.
Your data stays with us. No newsletter signup.
or book a 20-min scoping call first
We reply within one business day. Your data stays with us. No newsletter signup.
COMPLIANCE READY
Reports Mapped to Every Framework
Findings are written so your team can reference the report against each framework without translation work.
ISO 27001:2022
Annex A.8.8 management of technical vulnerabilities plus A.5.15-5.18 and A.8.2-8.5 access control validation.
SOC 2 Type I & II
CC6 logical access, CC7 system operations, CC8 change management evidence.
PCI DSS
Requirement 11.4 application penetration testing across cardholder data environments, including ecommerce penetration testing for online retail platforms.
FCA SYSC
SYSC 4.1.1R, 6.1.1R, 13 mapped to each finding for FCA-regulated firms.
UK GDPR
Article 32 effectiveness testing, customer-data security controls, ICO-acceptable evidence.
Cyber Essentials Plus
Direct certification through our IASME body status, single-vendor delivery.
PRICING
Transparent MySQL and MariaDB Security Review Pricing
Pricing depends on the number of roles, integrations and environments in scope. See our pricing page for how we quote.
2 to 3 testing days
Single user role, basic CRUD application, marketing website with auth. Around 5 working days from kickoff to report.
Get a fixed quote3 to 5 testing days
Multi-role SaaS, business application with payment integration. Around 8 to 12 working days from kickoff to report.
Get a fixed quote5 to 8 testing days
Multi-tenant platform, complex authorisation matrix, integration-heavy applications. Around 15 to 20 working days from kickoff to report.
Get a fixed quoteSECTORS
Sectors We Test MySQL For
Sector-specific scoping for regulated UK organisations.
Fintech & FCA-Regulated
FCA SYSC, Open Banking FAPI 1.0, PSD2 SCA, payment-flow scrutiny, KYC/AML testing.
Fintech sector pageSaaS Companies
SOC 2 Type I & II evidence, multi-tenant boundaries, role escalation, customer-tenant isolation.
SaaS sector pageLaw Firms
SRA Cyber Standard, privileged data, conveyancing fraud defence, partner-tier procurement.
Law firm sector pageHealthcare
NHS DTAC, DSP Toolkit v6, UK GDPR Article 32, EHR systems, telehealth platforms.
Healthcare sector pageInsurance
FCA / PRA Operational Resilience, cyber underwriting, claims data, broker portals.
Insurance sector pagePublic Sector
CCS / G-Cloud framework, NCSC-aligned, citizen-facing services, PSN-compliance scrutiny.
Public sector pageWHY EJN LABS
What You Get From MySQL and MariaDB Security Review
Six concrete differentiators competitors don’t all match.
CREST-Certified Testers, Verifiable
Every test by a CREST-certified pen tester (CRT, CCT APP, CCT INF where applicable). Verify our company status at crest-approved.org.
24-Hour Startup, Where Required
From signed scope to active testing in a single business day for incident response, audit deadlines, or regulator-driven timelines.
Live Findings, Not 4-Week PDFs
Critical issues reported during testing through your client portal. Your team remediates while testing continues.
Audit-Ready Reports
Executive summary plus full technical report with CVSS scores and explicit framework mappings (ISO 27001, SOC 2, PCI DSS, FCA SYSC).
Free Retests, Standard
Verify remediation of every finding before close-out. Letter of attestation for audit submission included. Most competitors charge £1,500-£3,000 per retest.
UK-Based CREST Testers
Every engagement performed by vetted, UK-based CREST-certified testers, matched to your needs, security clearance, and compliance scope.
FAQ
Frequently Asked
What access do you need to test our MySQL or MariaDB database?
We need at least one authenticated account for every privilege tier in scope, from an ordinary application account through to one that can query mysql.user, run SHOW GRANTS and list installed plugins for configuration review. If a superuser or cloud console account is available we use it to confirm configuration rather than to run the manual test itself.
Will testing touch live data?
We test the instances and schemas you nominate, working against your actual accounts, grants and configuration rather than a copy, so we agree exclusions such as destructive statements, bulk data changes or production replication targets before testing starts. We do not run destructive tests or export real customer data without that agreement in writing.
How long does a MySQL security review take?
A single MySQL or MariaDB instance with a small number of schemas in scope sits in our 2-day single-system scope, with a report typically landing around 5 working days after kickoff. More schemas, instances, or a mix of self-hosted and managed databases, moves into a larger scope with more testing days.
Do you test self-hosted and managed MySQL the same way?
The testing questions are the same: accounts, grants, remote access, transport encryption and stored routines. What differs is the boundary, since a managed service such as Amazon RDS, Aurora MySQL, Azure Database for MySQL or Google Cloud SQL keeps the host and much of the operational configuration under the provider, so we confirm during scoping exactly what you control on your plan and test to that boundary.
What is out of scope for a single-system MySQL review?
We never test the underlying host, hypervisor or infrastructure of a managed MySQL service, or MySQL’s own source code, and a separate connected system such as a backup platform or an identity provider is scoped and quoted separately. We test the accounts, grants, remote access, transport configuration and stored routines configured on the instance and schemas you nominate.
Do your cloud provider’s rules restrict what you can test?
Yes, where MySQL runs on a managed cloud service. AWS, Microsoft Azure and Google Cloud all allow customers to run security assessments against their own cloud resources without needing prior approval, though each publishes its own rules on activities that need extra sign-off, such as AWS requiring approval for Command and Control testing. We confirm the current version of the relevant provider’s rules during scoping and test to them exactly.
Do you test MariaDB differently from MySQL?
We test the same areas, accounts, grants, remote access, transport and stored routines, but we check each claim against the engine you actually run rather than assume MySQL and MariaDB behave identically. Where we have verified a genuine difference, such as MariaDB’s unix_socket authentication plugin for the root account, we test to that; otherwise we test to documented MySQL behaviour and confirm it against your instance during scoping.
Are your testers CREST certified?
Yes. Every MySQL and MariaDB engagement is carried out by UK-based, CREST-certified testers, and your report and attestation letter are recognised by auditors and insurers accordingly.
20+ CREST-accredited testing services in one place
Web, mobile, API, cloud, AI, infrastructure, red team. Pick the test that fits your environment.
Get a fixed price for your MySQL review
MySQL and MariaDB grant access by account and host pattern, and a wildcard host reaches further than one application needs. We review accounts, grants, remote access and file privileges on your database. CREST-certified testers, fixed price from £2,740 for a 2-day single-system scope, quoted within 24 hours.



