随着网络的普及,基于网络的应用也越来越多。网络数据库就是其中之一。通过一台或几台服务器可以为很多客户提供服务,这种方式给人们带来了很多方便,但也给不法分子造成了可乘之机。由于数据都是通过网络传输的,这就可以在传输的过程中被截获,或者通过非常手段进入数据库。由于以上原因,数据库安全就显得十分重要。因此,本文就以上问题讨论了MySQL数据库在网络安全方面的一些功能。" R6 h- w6 N, y) p" A1 w( C8 }
帐户安全; h P8 L: C |* h* j
帐户是MySQL最简单的安全措施。每一帐户都由用户名、密码以及位置(一般由服务器名、IP或通配符)组成。如用户john从server1进行登录可能和john从server2登录的权限不同。
9 J* q% b/ `5 y" J' EMySQL的用户结构是用户名/密码/位置。这其中并不包括数据库名。下面的两条命令为database1和database2设置了SELECT用户权限。
- Y( ?2 c5 m' p& K+ \, y1 B) MGRANT SELECT ON database1.* to ‘abc’@‘server1’ IDENTIFIED BY ‘password1’;
5 c: \* x4 S1 j3 oGRANT SELECT ON database2.* to ‘abc’@‘server1’ IDENTIFIED BY ‘password2’;
# z9 R9 s# t4 ]5 e第一条命令设置了用户abc在连接数据库database1时使用password1。第二条命令设置了用户abc在连接数据库database2时使用password2。因此,用户abc在连接数据库database1和database2的密码是不一样的。
3 I8 |" c! O. |8 ^. d) f2 C4 x& _上面的设置是非常有用的。如果你只想让用户对一个数据库进行有限的访问,而对其它数据库不能访问,这样可以对同一个用户设置不同的密码。如果不这样做,当用户发现这个用户名可以访问其它数据库时,那将会造成麻烦。
6 I/ Z* i- X/ a; k4 p; ~. P$ UMySQL使用了很多授权表来跟踪用户和这些用户的不同权限。这些表就是在mysql数据库中的MyISAM表。将这些安全信息保存在MySQL中是非常有意义的。因此,我们可以使用标准的SQL来设置不同的权限。
" c* K# u1 c( x一般在MySQL数据库中可以使用3种不同类型的安全检查:
' ], J, K: s R·登录验证" |7 m: j+ u' ?) b7 v
也就是最常用的用户名和密码验证。一但你输入了正确的用户名和密码,这个验证就可通过。) v1 `2 r4 T& J9 b b$ |
·授权
: a! N6 q' s- k3 p0 k8 S r在登录成功后,就要求对这个用户设置它的具体权限。如是否可以删除数据库中的表等。
- M1 {% \+ B: f2 A: Y·访问控制
- e8 s* ? R* l& b8 E这个安全类型更具体。它涉及到这个用户可以对数据表进行什么样的操作,如是否可以编辑数据库,是否可以查询数据等等。" v7 P9 r* q# u' h4 O
访问控制由一些特权组成,这些特权涉及到所何使用和操作MySQL中的数据。它们都是布尔型,即要么允许,要么不允许。下面是这些特权的列表:
" Q0 a% w' Y6 f- i·SELECT
) w3 V2 \% Y/ R7 x6 ~SELECT是设定用户是否可以使用SELECT来查询数据。如果用户没有这个特权,那么就只能执行一些简单的SELECT命令,如计算表达式(SELECT 1+2),或是日期转换(SELECT Unix_TIMESTAMP(NOW( )))等。+ l; }4 v- o$ h" K2 f5 F9 W
·INSERT7 q# R% s% K) c6 K6 f4 t6 _+ `+ c9 D
·UPDATE
. Q! P) p0 B9 q# I. [+ \·INDEX
- Y8 |5 k- U+ \INDEX决定用户是否可以对表的索引进行设置。如果用户没有这个权限,那么将无法设置表中的索引。 |- o. S- C' w+ _, g; k+ p
·ALTER
4 R4 m3 {0 }* E- B4 I% t·CREATE
9 P# B+ [ q% R9 v·GRANT
8 u7 o+ y4 i1 h/ t+ ]$ j: [9 h如果一个用户拥有这个GRANT权限,那么他就可以将自己的权限授给别的用户。也就是说,这个用户可以和其它用户共享自己的权限。; E5 F) S8 O2 \
·REFERENCES
7 S! o' @+ G0 m. |0 ?8 }有了REFERENCES权限,用户就可以将其它表的一个字段作为某一个表的外键约束。
2 k# {4 e" o- Y5 u) f除了以上的权限外,MySQL还有一些权限可以对整个MySQL进行操作。
; c, b7 B( S" F- _3 ?, `; \·Reload2 W+ R0 w; U4 R# c: ^8 B& m% V* L
这个权限可以使用户有权执行各种FLUSH命令,如FLUSH TABLES, FLUSH STATUS等。
& G [( `6 i/ g$ M9 @5 {8 }·Shutdown# K3 c" G% C4 w( m
这个权限允许用户关闭MySQL3 s1 Z) `$ C8 g" F1 s2 Y
·Process
1 z$ B7 V, g- q2 t, {% z) W通过这个权限,用户可以执行SHOW PROCESSLIST和KILL命令。这些命令可以查看MySQL的处理进程,可以通过这种方式查看SQL执行的细节。
+ ^) ?2 e6 p9 T$ w- c2 J6 Z·File& d1 S( ?, r, k6 r1 [0 E
这个权限决定用户是否可以执行LOAD DATA INFILE命令。给用户这个权限要慎重,因为有这个权限的用户可以将任意的文件装载到表中,这样对MySQL是十分危险的。3 z. T* X" y6 k; [
·Super
0 a. [, Z% F$ q这个权限允许用户终止任何查询(这些查询可能并不是这个用户执行的)。
% c0 [# w( I& v% \- |) q/ Q1 z3 m以上几种权限是非常危险的,在给用户授权限时要非常谨慎。
1 f% x' w9 p0 M+ Q1 i[NextPage] k5 y i- q" r
MySQL中的SSL
9 T4 J+ _" `) \& o6 A以上的帐户安全只是以普通的Socket进行数据传输的,这样非常不安全。因此,MySQL在4.1版以后提供了对SSL(Secure Scokets Layer)的支持。MySQL使用的是免费的OpenSSL库。
2 q1 u2 B9 @0 @/ t7 n m由于MySQL的Linux版本一般都是随Linux本身一起发布,因此,它们默认时都不使用SSL进行传输数据。如果要打开SSL功能,需要对hava_openssl变量进行设置:7 x3 U: L: K s' j6 Z/ s
MySQL的Windows版本已经将OpenSSL加入了。也面的命令是查看你的MySQL是否打开了SSL功能。
+ u& E' I, C% N2 |SHOW VARIABLES LIKE ‘have_openssl’;
: `- w8 \% q, d0 J# O2 Q/ Q+---------------+-------+
8 ^8 y' v4 {4 g' [& b( N6 L| Variable_name | Value |$ x! W5 H/ Q* v2 e( H4 u! u
+---------------+-------+
0 }# e9 D# V$ k& B! O( n| have_openssl | NO |
2 G& X8 J5 D' e/ G+---------------+-------+1 O! U0 g2 r! O+ W3 l1 n
1 row in set (0.00 sec)6 b5 o; z$ ~1 d6 Q2 i6 \( e" A
如果返回的是NO,那么说明你需要将OpenSSL编译进自己的MySQL& }; o+ n$ g1 X) A
在有时你可能需要将用户名和密码进行加密传输。在这时可以使用下面GRANT命令:
$ @! Q- d P: K& _2 S; JGRANT ALL PRIVILEGES ON ssl_only_db.* to ‘abc’@‘%’ IDENTIFIED BY “password!” REQUIRE SSL;
& n8 J+ @5 J. y# g9 s2 x! A还可以通过 REQUIRE x509 选项进行SSL传输:5 j* d7 |" j4 ?" i5 K
GRANT ALL PRIVILEGES ON ssl_only_db.* to ‘abc’@‘%’ IDENTIFIED BY “password!” REQUIRE x509;! \3 i, D8 L6 j2 j' O
你还可以使用REQUIRE SUBJECT来指定一个特定的客户端证书来访问数据库。# q& M$ U& R) ]# E6 e( x
GRANT ALL PRIVILEGES ON ssl_only_db.* to ‘abc’@‘%’$ ]: l: C q% n( P& x9 l
IDENTIFIED BY “password!”# S; L, O0 ~: G
REQUIRE SUBJECT “/C=US/ST=New York/L=Albany/O=Widgets Inc./CN=client-ray.
/ b$ {" B0 }' w5 ^example.com/emailAddress=raymond@example.com”;# t( ~+ e }- y2 _) I: k/ l
也许你并不关心使用的是什么客户许可,而仅仅关心的是你的证书。那么你可以使用REQUIRE ISSUER来实现:
+ i3 b* Z8 T6 s3 U4 N7 S1 {. u* LGRANT ALL PRIVILEGES ON ssl_only_db.* to ‘abc’@‘%’ IDENTIFIED BY “password!”2 Y3 W! O6 K, X- M+ f% t
REQUIRE ISSUER “/C=US/ST=New+20York/L=Albany/O=Widgets Inc./CN=cacert.example.$ p8 k+ y+ a# W# Q g# A+ Y: P
com/emailAddress=admin@example.com”;
$ f3 O. q/ f8 {& r N& G( f* s- V0 c9 rSSL还可以直接通过密码进行加密。可以使用REQUIRE CIPHER设置密码。. m: {' b1 q- `9 U
GRANT ALL PRIVILEGES ON ssl_only_db.* to ‘abc’@‘%’ IDENTIFIED BY “password!”" |) S- O: U: @( [4 I8 n
REQUIRE CIPHER “EDH-RSA-DES-CBC3-SHA”;4 k1 F7 { l. c" \. b
上面使用了GRANT命令对用户权限进行设置。而这些信息都是保存在授权表中,这些表是安全系统的心脏。在这些表中保存了每一个用户和客户机所具有的权限。如果正确地操作这些表,将会对数据库的安全起到积极的作用,而如果使用不慎,将是非常危险的。
$ v# c7 a4 x2 X, [下面让我们来看看MySQL中的最要的5个授权表。7 O) _2 d$ _* e
user$ B" N" ?7 o9 j" S
用户表保存了用户的权限和被加密的密码。这个表负责确定哪些用户和客户机可以连接到服务器上。
; p3 p# E7 Y) |+ bhost/ {# w: P0 o' C
这个表为每一个客户机分配权限,它并不考虑用户的权限。MySQL在确定是否接收还是拒绝一个连接时,首先考虑的是user表。而使用GRANT或REVOKE命令并不影响host表,我们可以通过手工方式修改这个表中的内容。' |6 f) E/ k. v+ r7 ]' w
db6 Q- {' @! G- o- E' j
db表保存了数据库层的权限信息。% Z( A% H$ }; f* T r0 N! W9 i
tables_priv
0 O* y2 K w* a, v这个表存储了表的权限信息。- n6 O9 O# w& D" c! R1 n- `
columns_priv
6 w5 @( _9 M( J4 o这个表保存了单独列的权限信息。通过这个表,可以将操作某一列的权限授予一个用户。
0 ^3 X) O1 r4 k+ ~[NextPage]
3 w* t3 M3 g5 {6 ]- E哈希加密' ^+ i1 G, o3 f1 |9 w
如果数据库保存了敏感的数据,如银行卡密码,客户信息等,你可能想将这些数据以加密的形式保存在数据库中。这样即使有人进入了你的数据库,并看到了这些数据,也很难获得其中的真实信息。
. @/ y/ o# A) B3 S. @在应用程序的大量信息中,也许你只想交很小的一部分进行加密,如用户的密码等。这些密码不应该以明文的形式保存,它们应该以加密的形式保存在数据库中。一般情况下,大多数系统,这其中包括MySQL本身都是使用哈希算法对敏感数据进行加密的。1 }; u$ y) A: z5 [$ d R
哈希加密是单向加密,也就是说,被加密的字符串是无法得到原字符串的。这种方法使用很有限,一般只使用在密码验证或其它需要验证的地方。在比较时并不是将加密字符串进行解密,而是将输入的字符串也使用同样的方法进行加密,再和数据库中的加密字符串进行比较。这样即使知道了算法并得到了加密字符串,也无法还原最初的字符串。银行卡密码就是采用的这种方式进行加密。
! f1 a& G/ C9 L+ X2 m" ` lMySQL提供了4个函数用于哈希加密:PASSWORD, ENCRYPT, SHA1和MD5。下面让我们试一试这4个函数,看看会得到什么结果。我们以加密字符串“pa55word”为例进行说明:
x" h9 F; d. ~! ~/ g; i6 i! i让我们先来看看MD5函数$ h3 a! K1 n! F- `2 Q
SELECT MD5(‘pa55word’);
. g. E6 \& I2 c x* w, O- ~2 Y+----------------------------------+6 z- y( j3 B9 t3 {5 N) Z7 J
| MD5(‘pa55word’) |1 Q9 A: T/ a1 l/ }. n4 E0 ]; ?
+----------------------------------+
0 P) v( p2 s- y, B| a17a41337551d6542fd005e18b43afd4 |
( [6 `0 u* q" c$ g
- J9 q9 y' N; o0 n+----------------------------------+
, Y( z/ d J; k; {3 d1 row in set (0.13 sec)
7 x1 w( L% B& i) t6 N1 k下面是PASSWORD函数
& N8 Q% S3 c$ @6 ], l' GSELECT PASSWORD(‘pa55word’);4 W$ J2 f7 p3 O
+----------------------+% W0 D) u1 u- e8 r7 v# k8 Q# z0 W
| PASSWORD(‘pa55word’) |
5 j; @$ ]; m' \3 S" }. I+----------------------+8 E7 O& P& U' L' v, o6 F
| 1d35c6556b8cab45 |3 \: P* j, E( a# w' E0 P
+----------------------+
+ U) u% x& v0 u" Z- m' K1 ?9 r1 row in set (0.00 sec)- s+ d+ A5 p/ |; j3 B
下面是ENCRYPT函数. H/ b* M, r! l, |: s0 m
SELECT ENCRYPT(‘pa55word’);- u: M7 L2 Y: [8 D' y
+---------------------+' H. [- F% W" L! M# p! s
| ENCRYPT(‘pa55word’) |/ i! e9 k! O: @5 \& f! r- _
+---------------------+
$ e% [$ E6 {8 {+ p) }8 C* x4 l| up2Ecb0Hdj25A |
" s" x6 [2 i3 g! _) c5 i+---------------------+
3 u* R# q- P* F' f1 row in set (0.17 sec)
]0 W9 \2 L, o* A! j# a- A上面的每个函数都返回了一个加密后的字符串。为了区分加密字符串的大小写,最好在使用ENCRYPT生成加密字符串时,将这个字段定义成CHAR BINARY类型。
) a; Y) h- y& ]* c- ]; R+ D; |( @ Q上面列举了3种加密的方法,但我认为使用MD5加密是最好的。这是因为这样做可以将明文密码显示在处理列表中或是查询日志中,这样便于跟踪。如下面的INSERT语句使用插入了一条记录,其中的密码使用了MD5进行加密:
5 G' E6 Q5 R2 F& u! HINSERT INTO table1 (user, pw) VALUE (‘user1’, MD5(‘password1’))
+ ^& m' u4 x3 w' g2 o* E1 E可以通过如下的语句进行密码验证:- a3 A/ o% Y' a$ m
SELECT * FROM table1 WHERE user = ‘user1’ AND pw = MD5(‘password1’)
# d2 Y- t& [! R$ N/ {哈希加密方法可以很好地对密码进行加密,使用了这种方法加密,密码将无法 恢复成明文。
. t6 k! n3 X. m! b
3 d; J) c0 R, V5 {5 J" m* w |
|