Rogue MySQL Server Attacks

A rogue MySQL server attack turns the client–server trust relationship of the MySQL protocol against an application: the attacker coaxes a target application into connecting to a MySQL server they control, and the malicious server then abuses protocol features — above all LOAD DATA LOCAL INFILE — to read arbitrary files from the application’s host or feed it poisoned data. Any application whose database connection parameters (host, port, credentials, dbname) are attacker-influenceable is a candidate target.

Mechanism: the server requests the file

LOAD DATA INFILE loads a file’s contents into a table. With the LOCAL modifier, the file is read from the client (the application server), not the database host. The critical, non-obvious protocol detail: the transfer is initiated by a server-to-client request packet — and a malicious server can send that request in response to any query, naming any file path, regardless of what the client actually asked for. The client library, if LOCAL INFILE is enabled, dutifully reads the named file and ships its contents to the server.

So the attacker needs only:

  1. A MySQL server they control (trivial with Docker — any host running mysqld on a reachable port).
  2. A way to make the application connect to it.
  3. A client with local-infile enabled — for PHP’s mysqli, mysqli.allow_local_infile=On in php.ini.

The rogue server answers the application’s first query with a LOCAL INFILE request for /etc/passwd, TLS keys, application configs, backups — anything the PHP/DB process can read.

The OpenEMR case (CVE-2023-22974)

SonarSource’s 2022 research into OpenEMR (< 7.0.0) is the canonical worked example. OpenEMR’s installer (setup.php) is not deleted after installation, and its step-wise $state parameter lets an unauthenticated user re-invoke setup steps with attacker-controlled Installer properties — including server, port, login, pass, and dbname. One step calls getCurrentTheme(), which opens a database connection using those attacker-supplied values and runs SELECT gl_value FROM globals WHERE gl_name LIKE '%css_header%' — a query to a database the attacker now controls.

Because OpenEMR legitimately uses LOAD DATA to import clinical definitions, a correctly configured deployment has mysqli.allow_local_infile=On — exactly the precondition the rogue server needs. The attack chain is therefore: unauthenticated POST to setup.php?state=7 with attacker DB credentials → application connects to the rogue MySQL server → rogue server issues LOCAL INFILE requests → arbitrary unauthenticated file read of certificates, passwords, tokens, and backups. SonarSource additionally chained a reflected XSS with an authenticated LFI (path traversal into *.plugin.php) to reach full unauthenticated RCE.

The fix (OpenEMR 7.0.0): session + CSRF checks through setup, ordered steps, refusal to run when a config already exists, and a longer-term plan to eliminate the allow_local_infile requirement.

Where the pattern applies

  • Any application with a web-driven “configure your database” flow (installers, setup wizards, admin DB-settings pages) that doesn’t verify the target DB is trustworthy.
  • MySQL client libraries generally, not just PHP — the LOCAL INFILE server-initiated read is a protocol feature; clients that enable it (or that a rogue server can trick into enabling it) are exposed. This is why modern client defaults disable it.
  • Data-poisoning variants: even without file read, a rogue server fully controls query results, so it can forge application state — fake themes pointing at attacker templates, spoofed admin flags, poisoned cache rows.

Defense

  • Delete or lock down installers after deployment; refuse to run setup when a valid config exists; gate every setup step behind authentication, sessions, and CSRF tokens.
  • Never let request parameters reach database connection constructors; treat DB host/credentials as deployment-time configuration only.
  • Keep allow_local_infile / LOCAL INFILE off in client libraries unless strictly required, and require TLS with server-certificate verification on DB connections so the client can’t be silently rerouted.
  • Run the application DB user with least filesystem privilege to bound what a file read can reach.

Sources

Related: sql-injection-attacks, mysql-into-outfile-webshell, local-file-inclusion-attacks, xss-attacks