Our VPS is set up in such a way that all databases are accessible from any domain via localhost and the username/password/dbname.
Is this the usual set up, or should there be some way of 'jailing' each user so they cannot access other databases on localhost?
Thanks, Mark
As Caleb mentions, when setting up MySQL, it's best, as with other systems, to operate a system of least-required-privileges - unless the different applications are related, then there is little reason for them to have access to each others' databases. If some are related, then they should be granted specific, limited privileges on the tables they need access to in the other database but not more.
I am assuming that when you say
you mean that you're running a multi-domain Apache installation (or similar), that means that all your applications are running on the same machine, and thus, from MySQL's point of view every user is a
'username'@'localhost'
user, so you're restricted to specifying users by username.It's important to note that because of the way MySQL permissions work, in a situation where you have remote users that
'user1'@'abc.example.com'
is actually a completely different user to'user1'@'xyz.example.com'
or'user1'@'localhost'
despite sharing a username which does significantly increase your flexibility in setting permissions (or makes things very confusing, depending on your perspective). It's a point in favour of running your database server on a different VM if you're able - not a must-have of course though.The common, easy to use (and insecure) method for adding database users tends to be something along the lines of:
which simply gives that user
GLOBAL
privileges to do anything on any database.This is bad for some obvious, and other not-so-obvious reasons.
*.*
includes themysql
database itself - that lets you do anything you like with other users, settings etc, and should be avoided. TheALL
part of the statement grants all privileges available at theGLOBAL
scope - this means they can do things likeSHOW PROCESSLIST
andKILL <query-id>
. It might seem fine ("why would they do that anyway?") but again, as Caleb notes - if the application is compromised, the database user it connects with is the user the attacker "uses" against you.A simple improvement to the above is to assign privileges using a statement like this, for each database:
This grants all
DATABASE
level privileges touser1
onuser1_database
- this is important as it excludes all the powerfulGLOBAL
privileges listed above, so now the user can, at worst, drop its own database.A further improvement to this method is to create at least two users per application. One with a
GRANT ALL
on the database (for administration), and another to be used by the web application itself that has only the privileges it needs, and only on the objects it needs access to. This is obviously quite a bit of extra work when you make changes, and extra testing, but done well it can significantly reduce the damage possible if the system is compromised.I often have a standard user, and another with a
_www
suffix for a web application.You can simplify some of this using MySQL's wildcard privileges, and have users that are able to create their own databases (matching a certain pattern) and
Example
The way the admin user is created in the example is a common method in a shared environment - it allows users to create databases, without assigning any
GLOBAL
privileges so that they can't see other users' databases.You should use finer grained privileges using the MySQL privileges table so that each application (or even component of an application) only has access to the databases or tables that are required for it's function. This will reduce potential problems with privacy violations, reduce damages in the event of a security breach, and even help reveal bugs in your software during testing.
As @simon and @caleb mention, it is common for global permissions to be given but that doesn't make it good practice, I use this 'macro' (which I cobbled together based on another post on serverfault or SO, can't remember which one tho') for privileges:
removing the 'revoke', 'drop' and 'create' lines and changing the table name and privileges as required. It allows, as @caleb suggests, the creation of fine grained privileges with the minimum of hassle.