
MySQL client allows MySQL server to request any local file - cnst
https://gwillem.gitlab.io/2019/01/20/sites-hacked-via-mysql-protocal-flaw/
======
sehrope
The intended usage is that the client tells the server, " _I want to load data
from a file /path/to/data.txt on my local filesystem_" in a SQL command. As
part of the protocol for executing the query the server sends a message to the
client to request the contents of /path/to/data.txt. Unfortunately client's
don't validate the file request and will send _any_ file (ex:
/path/to/secrets.txt) even if there was no legit data request in their
command.

This has been an issue with MySQL client drivers for years. I found and fixed
the same issue in MariaDB Connector/J (JDBC driver (wire compatible with MySQL
databases) in 2015. It rejects LOCAL DATA requests from the server unless the
client app preregistered an InputStream (Java interface for generic stream of
bytes) as data for the command being executing.

This is one of the many _many_ reasons I love open source database drivers. I
was able to find and fix this issue only because I could see the source code.
Similar "features" in proprietary databases could go unnoticed for years and
even when discovered may not have feature flags to disable them.

~~~
bufferoverflow
It's strange to blame the client, while it's actually the fault of the server.
A DB server should not be able to pipe an arbitrary file to the client.

~~~
hamiltont
You've got it backwards - the DB server can pipe an arbitrary file _from_ the
client. So it is considered the fault of the client - it should not allow
that. Since the mysql client is the one receiving the request and it should
apply standard security practices by not blindly trusting an incoming request
and instead validating that the path is equal to an earlier client load
request sent to the server. (Although a better approach IMO would be to modify
the wire protocol so the server "request" does not use the file name, but
instead uses an ID from the earlier client request)

------
lqet
Am I understanding this correctly: LOAD DATA LOCAL is used to bulk load
datasets (like CSV files) into a MySQL database from the client. Why is the
file transfer initiated by the server, and not by the client? Is it because
they wanted to cover cases where the server processes / simplifies the query,
and after processing, it becomes evident that the file is not needed at all?
If so, why isn't there an additional check on the client that the file
requested by the server matches a file that was previously used in a LOAD DATA
LOCAL query? Is it because there is no query processing / parsing on the
client side at all (in case of string SQL queries)?

~~~
beagle3
The client does not parse the SQL prior to sending it to the server. The name
of the file may actually be a computation result that depends on data in
tables IIRC.

~~~
adrianmonk
The docs say that it must be a literal:

> _The file name must be given as a literal string._

(From [https://dev.mysql.com/doc/refman/8.0/en/load-
data.html](https://dev.mysql.com/doc/refman/8.0/en/load-data.html) )

However, you raise an interesting point about parsing. It is reasonable to
want the server to do the parsing. You could, for example, tweak the grammar
to add a new feature and do it entirely in an server update without needing to
deploy a new client binary to every user. But then that makes it a bit harder
to fix bugs like this.

There are surely some commands parsed and implemented by the client, though.
Like connect, quit, and source for example. So another way to have designed
this would be to make a local command to designate a file that the server will
be allowed to access. You could define the path name on the client side and
pass a symbolic reference to the server. Then the client could parse that
command without taking on the burden of parsing SQL, and the client could
still own opening files rather than taking orders from the server.

------
billsmithaustin
But only with a modified MySQL server.

~~~
ryebit
Yeah, i definitely think common workflow rarely involves connecting to
untrusted servers. But... If server gets hacked, connecting in to see why your
site is down could steal files before you know what happened. Even better if
hack isn't visibly causing problems. Though that seems really indirect and
unproductive an attack vector.

But sounds great for a honeypot. Put up an easy-to-hack WordPress server, and
when attacker connects to mysql, start downloading all the PII files you can
think of from the client.

~~~
zAy0LfpBZLC8mAC
What is it with this concept of "(un)trusted servers" that people throw around
here all the time that seems to build on the assumption that the world
consists only of entities that are to be distrusted and those that should have
full access to and control over all your information and resources?

No, just because I don't expect my client to kill me, does not mean that
therefore there is no reason to be concerned about a rogue employee of theirs
being able to gain access to any other of my clients' servers that I have
access to by patching an exploit into their MySQL server.

Nor is it reasonable to assume that everyone is on top of their IT security
and their infrastructure is only under their own control, and that includes
your own organization once it grows beyond one or two people.

If that is the kind of mental model you are working with, your IT security
probably is shit. Even the slightest external vulnerability anywhere in your
systems or the systems of people whose systems you access/(co-)manage is going
to grant an attacker total control over your organization if that is how you
manage security.

------
lefred
by default, LOAD DATA LOCAL INFILE in libmysql is disabled by default to avoid
such problem

------
ams6110
This is an issue that something like openbsd's pledge can prevent. No reason
for the MySQL client to be able to read arbitrary files on the system.

[https://man.openbsd.org/pledge](https://man.openbsd.org/pledge)

~~~
giornogiovanna
This is incredibly off-topic, but can I use pledge as a sandbox by pledging
and then execve-ing?

~~~
throwawaypled
if you pass the `execpromises` parameter, and make sure that the flags DO NOT
include the ability to further execve() (the `exec` flag), then yes, but
openbsd pledge flags are not implicitly inherited like linux seccomp filters.

