[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Anyone using MySQL on a computer connected to the Internet should read this section to avoid the most common security mistakes.
In discussing security, we emphasize the necessity of fully protecting the entire server host (not just the MySQL server) against all types of applicable attacks: eavesdropping, altering, playback, and denial of service. We do not cover all aspects of availability and fault tolerance here.
MySQL uses security based on Access Control Lists (ACLs) for all connections, queries, and other operations that users may attempt to perform. There is also some support for SSL-encrypted connections between MySQL clients and servers. Many of the concepts discussed here are not specific to MySQL at all; the same general ideas apply to almost all applications.
When running MySQL, follow these guidelines whenever possible:
root
accounts) access to the
user
table in the mysql
database! This is critical.
The encrypted password is the real password in MySQL.
Anyone who knows the password which is listed in the user
table
and has access to the host listed for the account can easily log
in as that user.
GRANT
and
REVOKE
statements are used for controlling access to MySQL. Do
not grant any more privileges than necessary. Never grant privileges to all
hosts.
Checklist:
mysql -u root
. If you are able to connect successfully to the
server without being asked for a password, you have problems. Anyone
can connect to your MySQL server as the MySQL
root
user with full privileges!
Review the MySQL installation instructions, paying particular
attention to the item about setting a root
password.
SHOW GRANTS
statement and check to see who has access to
what. Then use the REVOKE
statement to remove those privileges that
are not necessary.
MD5()
, SHA1()
or
some other one-way hashing function.
Checklist:
nmap
. MySQL uses port 3306 by default. This port should
not be accessible from untrusted hosts. Another simple way to check whether
or not your MySQL port is open is to try the following command
from some remote machine, where server_host
is the host where
your MySQL server runs:
shell> telnet server_host 3306 |
If you get a connection and some garbage characters, the port is
open, and should be closed on your firewall or router, unless you really
have a good reason to keep it open. If telnet
just hangs or the
connection is refused, everything is OK; the port is blocked.
; DROP
DATABASE mysql;
". This is an extreme example, but large security leaks
and data loss may occur as a result of hackers using similar techniques,
if you do not prepare for them.
A common mistake is to protect only string data values. Remember to check
numeric data as well. If an application generates a query such as
SELECT * FROM table WHERE ID=234
when a user enters the value
234
, the user can enter the value 234 OR 1=1
to cause the
application to generate the query SELECT * FROM table WHERE ID=234 OR
1=1
. As a result, the server retrieves every record in the table. This
exposes every record and causes excessive server load. The simplest way to
protect from this type of attack is to use apostrophes around the numeric
constants: SELECT * FROM table WHERE ID='234'
. If the user enters
extra information, it all becomes part of the string. In numeric context,
MySQL automatically converts this string to a number and strips any trailing
non-numeric characters from it.
Sometimes people think that if a database contains only publicly available data, it need not be protected. This is incorrect. Even if it is allowable to display any record in the database, you should still protect against denial of service attacks (for example, those that are based on the technique in the preceding paragraph that causes the server to waste resources). Otherwise, your server becomes unresponsive to legitimate users.
Checklist:
%22
(`"'), %23
(`#'), and %27
(`'') in the URL.
mysql_escape_string()
function, which
is based on the function of the same name in the MySQL C API.
Prior to PHP 4.0.3, use addslashes()
instead.
mysql_real_escape_string()
API call.
escape
and quote
modifiers for query streams.
quote()
method or use placeholders.
PreparedStatement
object and placeholders.
Other programming interfaces may have similar capabilities.
tcpdump
and strings
utilities. For most cases,
you can check whether MySQL data streams are unencrypted
by issuing a command like the following:
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings |
(This works under Linux and should work with small modifications under other systems.) Warning: If you do not see plaintext data, this doesn't always mean that the information actually is encrypted. If you need high security, you should consult with a security expert.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |