自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MySQL安全攻防實(shí)戰(zhàn)指南之體系結(jié)構(gòu)篇

原創(chuàng)
安全 數(shù)據(jù)安全
本文將為讀者詳細(xì)介紹MySQL數(shù)據(jù)庫(kù)在體系結(jié)構(gòu)方面的安全問(wèn)題以及相應(yīng)的攻擊方法,在后續(xù)的文章中我們將介紹相應(yīng)的防御措施。

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

一、MySQL支持的機(jī)器體系結(jié)構(gòu)

MySQL自稱是當(dāng)今世界上最流行的開(kāi)源數(shù)據(jù)庫(kù),并且是免費(fèi)發(fā)行,同時(shí)還能運(yùn)行在各種平臺(tái)之上——這也正是黑客們對(duì)它趨之若鶩的原因。與其它大型數(shù)據(jù)庫(kù)相比較而言,它的配置工作要容易、簡(jiǎn)單得多,并且性能也說(shuō)的過(guò)去。盡管它的用法相對(duì)來(lái)說(shuō)簡(jiǎn)單一些,但是在安全配置方面還是有大量的工作要做的,這也是許多數(shù)據(jù)庫(kù)存在安全隱患的原因之一。

一般情況下,人們都是通過(guò)二進(jìn)制文件程序包來(lái)安裝MySQL數(shù)據(jù)庫(kù)服務(wù)器,這時(shí)它可以安裝到如下所示的系統(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)行安裝的話,那么它能支持的平臺(tái)還要多。

#p#

二、MySQL的部署

由于MySQL服務(wù)器是如此流行,以至于在網(wǎng)絡(luò)中的任何角落幾乎都能找到它的身影,實(shí)際上,它不僅安裝到專用服務(wù)器中,就連桌面機(jī)器中也常見(jiàn)它的蹤跡。

在一般的配置中,客戶端會(huì)通過(guò)TCP 3306端口連接到MySQL。對(duì)于Windows平臺(tái)而言,還可以通過(guò)有名管道使用MySQL,不過(guò)一般不推薦這樣配置。默認(rèn)情況下,以有名管道模式運(yùn)行的MySQL會(huì)同時(shí)偵聽(tīng)TCP 3306端口和一個(gè)名為MySQL的有名管道。與諸如Oracle之類的數(shù)據(jù)庫(kù)系統(tǒng)相比,MySQL使用的網(wǎng)絡(luò)協(xié)議就比較簡(jiǎn)單了,并且默認(rèn)情況下是使用明文通信,當(dāng)然也可以使用SSL來(lái)保護(hù)通信。啟用SSL協(xié)議后,數(shù)據(jù)庫(kù)仍然是一TCP 3306端口。

您可以很輕松地檢測(cè)一臺(tái)主機(jī)上運(yùn)行的MySQL的版本,因?yàn)橹灰B接該機(jī)器,它就會(huì)返回?cái)?shù)據(jù)庫(kù)的主要版本號(hào)和次要版本號(hào),某些版本還會(huì)提供操作系統(tǒng)的提示信息。任何能夠抓取旗標(biāo)的TCP端口掃描器都能夠返回MySQL版本。

MySQL最普遍的應(yīng)用是為動(dòng)態(tài)web應(yīng)用程序提供后端支持,當(dāng)我們掃描網(wǎng)絡(luò)時(shí)見(jiàn)到的MySQL通常出現(xiàn)在Apache/PHP應(yīng)用程序的后端,甚至有時(shí)候它竟跟web服務(wù)器運(yùn)行在同一臺(tái)主機(jī)上。在一些大型組織中,它常用作日志記錄服務(wù)器,用于存放入侵檢測(cè)系統(tǒng)日志、web日志或者其他審計(jì)任務(wù)。有些情況下,特別是在開(kāi)發(fā)環(huán)境中,MySQL經(jīng)常被安裝到一臺(tái)桌面機(jī)器上,所以在PC上掃描到它也就不足為奇了。

由于MySQL通信協(xié)議是明文通信,因此人們喜歡在MySQL服務(wù)器所在主機(jī)上同時(shí)安裝一個(gè)SSH服務(wù)器,并使用端口轉(zhuǎn)發(fā)技術(shù)通過(guò)加密隧道連接至3306端口。這種方法有幾種好處:數(shù)據(jù)在運(yùn)輸中是加密的,并強(qiáng)迫執(zhí)行一個(gè)額外的認(rèn)證步驟,同時(shí)還給該數(shù)據(jù)庫(kù)的連接提供了額外的審計(jì)記錄。
 
此外,有人認(rèn)為MySQL服務(wù)器應(yīng)該與web服務(wù)器安裝到同一臺(tái)機(jī)器上,因?yàn)檫@樣可以避免遠(yuǎn)程連接,但是這種配置本身就是不安全的。之所以這樣說(shuō),是因?yàn)镸ySQL的數(shù)據(jù)表是以文件的形式存儲(chǔ)的,并且通常沒(méi)有鎖定,那么一旦Web應(yīng)用程序出現(xiàn)文件泄露漏洞,這就使得攻擊者能夠下載數(shù)據(jù)庫(kù)的所有內(nèi)容。從另一方面來(lái)說(shuō),Web應(yīng)用程序中的SQL注入漏洞也可能導(dǎo)致攻擊者得以修改web服務(wù)器上的腳本內(nèi)容。恰當(dāng)?shù)奈募?quán)限可以防止此類問(wèn)題,但是除此之外,將web服務(wù)器和數(shù)據(jù)庫(kù)服務(wù)器置于同一臺(tái)機(jī)器上還為攻擊者敞開(kāi)了許多其它的方便之門。

#p#

三、WinMySQLAdmin簡(jiǎn)介

當(dāng)MySQL安裝到Windows平臺(tái)的時(shí)候,通常會(huì)提供WinMySQLAdmin工具。當(dāng)這個(gè)工具第一次運(yùn)行時(shí),它會(huì)將自身添加到運(yùn)行它的用戶所在的啟動(dòng)組。當(dāng)它運(yùn)行時(shí),WinMySQLAdmin會(huì)自動(dòng)地啟動(dòng)MySQL,這會(huì)導(dǎo)致運(yùn)行于Windows主機(jī)的MySQL的實(shí)例在無(wú)意間被運(yùn)行。

此外,當(dāng)WinMySQLAdmin運(yùn)行于沒(méi)有默認(rèn)MySQL用戶帳戶的主機(jī)時(shí),它會(huì)要求用戶創(chuàng)建一個(gè)用戶名和口令對(duì),并將這些憑證以明文形式存儲(chǔ)在系統(tǒng)根目錄(例如,c:\winnt)下的my.ini文件中。這個(gè)文件通常對(duì)該主機(jī)上的任何用戶來(lái)說(shuō)都是可讀的。

#p#

四、缺省用戶名和口令

MySQL的默認(rèn)配置隨平臺(tái)、部署模式、發(fā)行版本(源代碼或者二進(jìn)制文件)和初始配置的不同而異,在有些情況下MySQL服務(wù)器一經(jīng)安裝就可能被遠(yuǎn)程攻擊者所攻陷——如果缺省配置有問(wèn)題的話。舉例來(lái)說(shuō),MySQL 4.0.20的一些默認(rèn)配置下,表mysql.user中有四條缺省記錄,有兩條用于root帳戶,另兩條用于匿名帳戶。并且,有一個(gè)帶有root權(quán)限的遠(yuǎn)程表項(xiàng)是給主機(jī)build上的根用戶的。這些表中的表項(xiàng)的具體含義,我們會(huì)在后面加以詳解,現(xiàn)在我們只需知道的是:

如果您位于本地主機(jī),那么您可以作為密碼為空的root根用戶通過(guò)身份驗(yàn)證,并獲得數(shù)據(jù)庫(kù)的完全控制權(quán)。如果您位于本地主機(jī),您可以使用任何用戶名通過(guò)身份驗(yàn)證,并獲得對(duì)該數(shù)據(jù)庫(kù)的來(lái)賓訪問(wèn)權(quán)限。如果您位于一個(gè)遠(yuǎn)程主機(jī)上,同時(shí)能夠控制服務(wù)器的名稱解析,這樣的話就可以使你的主機(jī)名看起來(lái)是“build”,所以您就可以作為密碼為空的root用戶通過(guò)身份驗(yàn)證,從而獲得數(shù)據(jù)庫(kù)的完全控制權(quán)。如果您位于一臺(tái)名為build的遠(yuǎn)程主機(jī)上,那么您就可以使用任何用戶名來(lái)通過(guò)身份驗(yàn)證,并獲得數(shù)據(jù)庫(kù)的來(lái)賓訪問(wèn)權(quán)限。

在Windows主機(jī)上,根帳戶的存在會(huì)導(dǎo)致任何本地用戶都能將自身權(quán)限提升為本地系統(tǒng)級(jí)訪問(wèn)權(quán)限;而在默認(rèn)情形下,MySQL就是運(yùn)行在系統(tǒng)權(quán)限級(jí)別的。糟糕的是,攻擊者只需簡(jiǎn)單將其機(jī)器命名為build,那么他就輕而易舉地獲得了對(duì)運(yùn)行MySQL服務(wù)的機(jī)器的遠(yuǎn)程系統(tǒng)級(jí)訪問(wèn)權(quán)限。當(dāng)然,攻擊者必須位于目標(biāo)所在的同一個(gè)NetBIOS名字域中,或者能夠偽造一個(gè)DNS響應(yīng)。針對(duì)這一問(wèn)題的防御方法是:

  • 安裝MySQL時(shí)禁用網(wǎng)絡(luò)連接。
  • 安裝之后立即刪除mysql.user表中除本地主機(jī)root帳戶之外的全部帳戶。
  • 為本地主機(jī)root帳戶設(shè)置一個(gè)復(fù)雜的密碼。

#p#

五、身份驗(yàn)證協(xié)議中的安全漏洞

MySQL使用一個(gè)專有協(xié)議進(jìn)行身份驗(yàn)證和發(fā)送接收數(shù)據(jù)。這個(gè)協(xié)議比較簡(jiǎn)單,所以可以為MySQL輕松編寫(xiě)一個(gè)定制的客戶端。換句話說(shuō),MySQL身份驗(yàn)證協(xié)議的各版本中的嚴(yán)重漏洞可能會(huì)導(dǎo)致服務(wù)器立即被攻陷。下面我們介紹之前發(fā)現(xiàn)的一些漏洞,以及針對(duì)這些漏洞的攻擊方法。

描述這些攻擊方法之前,我們先來(lái)大致介紹涉及身份驗(yàn)證協(xié)議的包格式和加密機(jī)制。當(dāng)客戶端連接服務(wù)器時(shí),服務(wù)器問(wèn)候數(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ù)包的其余部分)

就身份驗(yàn)證協(xié)議而言,有關(guān)的內(nèi)容是Protocol Version和Challenge域,但是Server Version String域則對(duì)確定服務(wù)器容易受到哪些身份驗(yàn)證漏洞的攻擊非常有幫助。客戶端然后會(huì)發(fā)送一個(gè)身份驗(yàn)證數(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é)尾)

下面我們對(duì)身份驗(yàn)證協(xié)議中的安全漏洞進(jìn)行介紹。MySQL身份驗(yàn)證協(xié)議中已經(jīng)發(fā)現(xiàn)過(guò)許多安全漏洞,我們這里略舉一二。

#p#

身份驗(yàn)證協(xié)議4.1版本之前的基本密碼弱點(diǎn)

4.1版本之前的MySQL,無(wú)需知道密碼,只要知道密碼的hash值(包含在mysql.user表中)就能通過(guò)身份驗(yàn)證——這意味著,攻擊者根本無(wú)需編寫(xiě)密碼雜湊值的破解程序,因?yàn)樾薷臉?biāo)準(zhǔn)MySQL客戶端讓它接受密碼雜湊而非密碼要容易多了。當(dāng)然,用戶傾向于多處使用同一個(gè)密碼,尤其是root密碼,所以破解任何一個(gè)密碼的雜湊值,就極有可能在多個(gè)地方派上用場(chǎng)。

3.23.11版本之前的身份驗(yàn)證算法

3.23.11版本之前的MySQL的身份驗(yàn)證機(jī)制中有一個(gè)嚴(yán)重的缺陷,即攻擊者僅僅使用雜湊后的密碼的單個(gè)字符就能通過(guò)身份驗(yàn)證。其實(shí)雜湊后的字符串由32個(gè)字符中的某些字符構(gòu)成的,所以攻擊者只需進(jìn)行少量猜測(cè)就能登錄。

3.23.54版本之前的CHANGE_USER

對(duì)于3.23.54版本之前的MySQL來(lái)說(shuō),如果用戶可以進(jìn)行身份驗(yàn)證,它就有機(jī)會(huì)提交一個(gè)超長(zhǎng)字符串(來(lái)觸發(fā)緩沖區(qū)溢出)或者單字節(jié)字符串的CHANGE_USER命令來(lái)提權(quán)。

4.1.1、4.1.2和5.0.0版本中的身份驗(yàn)證算法

通過(guò)提交一個(gè)精心制作的身份驗(yàn)證數(shù)據(jù)分組,對(duì)于攻擊者而言,就有可能繞過(guò)在4.1.0到4.1.2以及5.0早期構(gòu)建版的MySQL中的密碼身份驗(yàn)證機(jī)制。下面的代碼取自sql_parse.cpp文件的check_connection代碼:

  /*

    舊版本的客戶端發(fā)送以null結(jié)束的字符串作為密碼;新客戶端使用尺寸(1字節(jié))+字符串(并非以null作為終止符)作為密碼。 因此如果是空密碼的話,兩者都會(huì)發(fā)送'\0'。

  */

  uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
    *passwd++ : strlen(passwd);

0x8000是在客戶端的能力標(biāo)志中規(guī)定的,用戶可以指定所選的passwd_len字段。對(duì)于該攻擊,我們選擇0x14 (20),這是我們預(yù)期的SHA1雜湊長(zhǎng)度。

現(xiàn)在要執(zhí)行多道檢測(cè)以保證用戶是從授權(quán)連接的主機(jī)上進(jìn)行身份驗(yàn)證。通過(guò)這些檢測(cè)后,我們到達(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;                                 /* 密碼錯(cuò)誤 */
  }
  return 0;
}

現(xiàn)在,用戶已經(jīng)規(guī)定了一個(gè)他想要的雜湊字符串,本例為一個(gè)零長(zhǎng)度的字符串。最后的循環(huán)對(duì)雜湊字符串與MySQL已知正確響應(yīng)字符串進(jìn)行逐字符比較,直到雜湊字符串中的所有字符都比較完為止。由于在雜湊字符串中根本沒(méi)有要比對(duì)的字符,所以函數(shù)會(huì)立即返回0,即允許用戶使用零長(zhǎng)度字符串通過(guò)身份驗(yàn)證。

這個(gè)缺陷的利用方法相當(dāng)簡(jiǎn)單,但是我們還是必須要編寫(xiě)一個(gè)定制的MySQL客戶端才行。除了使用零長(zhǎng)度字符串繞過(guò)身份驗(yàn)證外,還可以使用長(zhǎng)雜湊字符串來(lái)溢出基于堆棧的緩沖區(qū)。我們可以使用偽隨機(jī)數(shù)發(fā)生器my_rnd()函數(shù)輸出的字符來(lái)溢出該緩沖區(qū)。字符的范圍介于0x40到0x5f之間。對(duì)于一些平臺(tái)來(lái)說(shuō),執(zhí)行任意代碼是可能的,但是該漏洞利用非常復(fù)雜,并且需要進(jìn)行暴力破解,或者知道一個(gè)密碼雜湊值。

為了進(jìn)行這些攻擊,攻擊者必須知道或者能猜出用戶的名稱,所以重命名MySQL的root帳戶不失為一個(gè)有效的預(yù)防措施。此外,有關(guān)賬戶還必須能夠從攻擊者的主機(jī)進(jìn)行訪問(wèn),所以應(yīng)用基于IP地址的登錄限制也能減輕這些漏洞所帶來(lái)的危害。

#p#

六、利用體系結(jié)構(gòu)設(shè)計(jì)缺陷

下面,我們將介紹設(shè)計(jì)缺陷有哪些?如何利用這些缺陷?以及如何識(shí)別和抵御這些攻擊。

對(duì)于MySQL,歷史上曾經(jīng)出現(xiàn)過(guò)多個(gè)設(shè)計(jì)缺陷,它們主要影響身份驗(yàn)證協(xié)議,這些我們?cè)谏衔闹幸呀?jīng)介紹過(guò)了。下面,我們將從更通用的、體系結(jié)構(gòu)的角度來(lái)考察在MySQL中的各種安全弱點(diǎn)。

認(rèn)證機(jī)制中的各種漏洞允許遠(yuǎn)程用戶無(wú)需任何憑證就可以通過(guò)身份認(rèn)證,這些應(yīng)該屬于體系結(jié)構(gòu)漏洞中最嚴(yán)重的一類。

我們知道,凡事都有其兩面性,MySQL的簡(jiǎn)單性雖然給我們帶來(lái)了便利,但是它同時(shí)也成為了其最大的弱點(diǎn)。舉例來(lái)說(shuō),Microsoft SQL Server的一個(gè)極其有用的特性就是能夠在遠(yuǎn)程數(shù)據(jù)庫(kù)服務(wù)器上執(zhí)行查詢,比如我們可向服務(wù)器發(fā)送一個(gè)如下所示的查詢:

 

SQL Server中的OpenRowset語(yǔ)句允許您在SQL Server查詢過(guò)程中向另一個(gè)(運(yùn)行不同的數(shù)據(jù)庫(kù)管理系統(tǒng)的)服務(wù)器提交查詢。但是這個(gè)特性很容易被濫用。據(jù)我們所知,最常用的濫用方式之一是可以通過(guò)它來(lái)掃描該SQL Server所在網(wǎng)絡(luò)的端口,因?yàn)樗梢岳貌煌L(zhǎng)度的響應(yīng)時(shí)間來(lái)確定遠(yuǎn)程主機(jī)是否存在,是否為SQL Server。

而對(duì)于MySQL來(lái)說(shuō),由于沒(méi)有對(duì)應(yīng)的OpenRowset語(yǔ)句,因此MySQL也就不會(huì)遭受此類攻擊了??蓡?wèn)題是,如果軟件的行為太簡(jiǎn)單,那么就可能缺少針對(duì)濫用的保護(hù)措施。

#p#

七、利用用戶定義的函數(shù)

幾乎每個(gè)數(shù)據(jù)庫(kù)管理系統(tǒng)都提供了調(diào)用定制的本機(jī)代碼的機(jī)制,例如SQL Server有擴(kuò)展存儲(chǔ)過(guò)程的概念,Oracle有外部存儲(chǔ)過(guò)錯(cuò)的概念,等等。雖然這些機(jī)制的名稱不同,但是基本原理是一致的,那就是用戶創(chuàng)建一個(gè)可動(dòng)態(tài)裝載程序庫(kù)(在windows上為.dll;在linux中為共享對(duì)象.so),然后數(shù)據(jù)庫(kù)可以通過(guò)SQL語(yǔ)句來(lái)調(diào)用這個(gè)庫(kù)。

由于大多數(shù)數(shù)據(jù)庫(kù)運(yùn)行在管理權(quán)限上,或者至少能控制他們自己代碼和數(shù)據(jù),因此這就會(huì)招致一個(gè)嚴(yán)重的安全問(wèn)題。如果一個(gè)MySQL用戶可以創(chuàng)建和執(zhí)行一個(gè)惡意UDF,那么整個(gè)數(shù)據(jù)庫(kù)服務(wù)器的安全性就會(huì)岌岌可危。

觸發(fā)添加和使用UDF的過(guò)程的內(nèi)容,我們前面已經(jīng)講過(guò)一些了,這里將深入探討更多的細(xì)節(jié),因?yàn)橐坏㎝ySQL本身被攻陷,那么也會(huì)殃及MySQL所在的主機(jī),而有時(shí)候利用惡意UDF攻陷MySQL是件非常簡(jiǎn)單的事情。

MySQL提供了一個(gè)機(jī)制,通過(guò)該機(jī)制可以擴(kuò)展默認(rèn)函數(shù)集,方法是編寫(xiě)定制的包含用戶定義的函數(shù)或者UDFs的動(dòng)態(tài)庫(kù)。這個(gè)機(jī)制可以通過(guò)CREATE FUNCTION語(yǔ)句加以訪問(wèn),而MySQL.func表中的表項(xiàng)則可以手動(dòng)添加。包含函數(shù)的程序庫(kù)必須能夠從MySQL裝入動(dòng)態(tài)庫(kù)時(shí)所用的路徑加以訪問(wèn)。

#p#

攻擊者濫用這個(gè)機(jī)制的通常方式是,創(chuàng)建一個(gè)惡意程序庫(kù),然后使用SELECT . . . INTO OUTFILE將其放到一個(gè)適當(dāng)?shù)哪夸浿?。該程序?kù)就位之后,攻擊者需要更新或者插入mysql.func表,以便配置MySQL使其加載該程序庫(kù)并執(zhí)行該函數(shù)。一個(gè)UDF程序庫(kù)示例源代碼如下所示:

#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ù)的長(zhǎng)度 */
 char *maybe_null;                     /* 對(duì)于所有的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ù)無(wú)關(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ù)可以通過(guò)如下所示的命令來(lái)添加至MySQL:

 

然后,mysql.func表看上去會(huì)是這樣的(您還可以通過(guò)手動(dòng)方式更新):

 

于是,我們就可以像下面這樣來(lái)調(diào)用函數(shù)了:

 

即使攻擊者受文件權(quán)限的制約無(wú)法在目標(biāo)系統(tǒng)上創(chuàng)建自己所有的程序庫(kù),但是他仍然可以通過(guò)一個(gè)現(xiàn)有的函數(shù)來(lái)達(dá)到不可告人的目的。攻擊者的難點(diǎn)在于大多數(shù)函數(shù)的參數(shù)表不可能匹配MySQL UDF的原型:

int xxx( UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)

當(dāng)然,機(jī)智的攻擊者可能會(huì)通過(guò)調(diào)用一個(gè)當(dāng)解釋傳給MySQL的參數(shù)時(shí)會(huì)出現(xiàn)某種可控故障的程序庫(kù)來(lái)設(shè)法執(zhí)行任意的代碼。然而,現(xiàn)有的系統(tǒng)程序庫(kù)中的函數(shù)仍然可能會(huì)做壞事——舉例來(lái)說(shuō),在Windows系統(tǒng)中將ExitProcess作為MySQL UDF進(jìn)行調(diào)用,這會(huì)導(dǎo)致MySQL立即退出——即使發(fā)起調(diào)用的用戶不具備Shutdown_priv權(quán)限:

 

您還可以鎖住當(dāng)前登錄用戶的工作站,只要使用下列命令,其效果跟按下CTRL-ALT-DEL一樣:

 

然后工作站就會(huì)被鎖定。

總之,在MySQL中的UDF機(jī)制對(duì)于開(kāi)發(fā)人員來(lái)說(shuō)是極其靈活和有用的,但是也給攻擊者帶來(lái)了莫大的幫助。所以,防御此類攻擊的最好措施就是,仔細(xì)分配MySQL權(quán)限(特別是MySQL數(shù)據(jù)庫(kù)和mysql.func表有關(guān)的權(quán)限)、文件權(quán)限以及限制使用SELECT . . . INTO OUTFILE。

#p#

八、利用訪問(wèn)控制系統(tǒng)中的漏洞

由于4.1.x版本之前版本沒(méi)有實(shí)現(xiàn)視圖,因此也就沒(méi)有記錄級(jí)別的安全機(jī)制。對(duì)于某些用戶來(lái)說(shuō),這可能是一個(gè)問(wèn)題,并且在有些情況下缺少可用的安全配置,所以它們最好選擇更高版本。舉例來(lái)說(shuō),假設(shè)一個(gè)數(shù)據(jù)倉(cāng)儲(chǔ)系統(tǒng)使用MySQL用戶來(lái)確定哪些用戶可以執(zhí)行哪些動(dòng)作,該用戶通常想要做的事情之一就是更改他們的口令,所以該軟件使用了一個(gè)表單查詢實(shí)現(xiàn)了該功能:

 

現(xiàn)在假設(shè)入庫(kù)腳本存在被可以替換參數(shù)中的用戶名的用戶的攻擊的弱點(diǎn),對(duì)于帶有記錄級(jí)別安全控制機(jī)制的系統(tǒng)來(lái)說(shuō),攻擊者仍然無(wú)法改變另一個(gè)用戶的密碼,因?yàn)樗挥懈伦约簲?shù)據(jù)的權(quán)限。由于4.1.x版本及其之前版本的MySQL數(shù)據(jù)庫(kù)管理系統(tǒng)沒(méi)有實(shí)現(xiàn)記錄級(jí)別的安全機(jī)制,因此每一用戶毫無(wú)疑問(wèn)都能更新所有其他用戶的密碼,這將導(dǎo)致非常嚴(yán)重的安全問(wèn)題。

#p#

九、利用缺乏的安全特性

MySQL沒(méi)有內(nèi)置訪問(wèn)違例審計(jì)機(jī)制,但是它支持所有連接和查詢的完整日志記錄。 這對(duì)于安全性的影響是顯而易見(jiàn)的,在一些情況下,缺乏本地審計(jì)時(shí)一個(gè)非常大的安全問(wèn)題。然而,由于提供了對(duì)調(diào)試日志記錄的支持,使得MySQL能夠通過(guò)--log選項(xiàng)記錄每一連接和語(yǔ)句到日志文件。

前面提到的MySQL存儲(chǔ)引擎大部分都不支持引用完整性或者事務(wù)。雖然這些特性是可用的,但是默認(rèn)的存儲(chǔ)引擎MyISAM卻沒(méi)有實(shí)現(xiàn)這些特性。 因此,下面的討論只是針對(duì)MySQL的默認(rèn)行為的,當(dāng)然,我們這里討論的某些問(wèn)題也可能出現(xiàn)在那些功能不是很豐富的數(shù)據(jù)庫(kù)管理系統(tǒng)中。

在一些缺乏引用完整性的應(yīng)用程序中,可能會(huì)出現(xiàn)競(jìng)態(tài)條件從而引起安全問(wèn)題,舉例來(lái)說(shuō),假設(shè)我們的應(yīng)用程序通過(guò)一個(gè)用戶表來(lái)執(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)訪問(wèn)一些資源,并使用編號(hào)進(jìn)行標(biāo)識(shí):

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 );

這些資源的訪問(wèn)權(quán)限是通過(guò)一個(gè)訪問(wèn)控制表來(lái)實(shí)現(xiàn)的,表中的記錄決定用戶是否可以訪問(wèn)各個(gè)資源:

create table accesscontrol( userid int, resourceid int, allowed int );
# Admin可以訪問(wèn)下面三種資源:
insert into accesscontrol values ( 0, 1, 1 );
insert into accesscontrol values ( 0, 2, 1 );
insert into accesscontrol values ( 0, 3, 1 );
# Fred可以訪問(wèn)文件系統(tǒng)和網(wǎng)絡(luò):
insert into accesscontrol values ( 1, 2, 1 );
insert into accesscontrol values ( 1, 3, 1 );
#Joe只能訪問(wèn)打印機(jī)
insert into accesscontrol values ( 2, 1, 1 );

#p#

假設(shè)我們沒(méi)有強(qiáng)制執(zhí)行引用完整性,如果我們利用id 2刪除用戶joe,如下所示:

 

表accesscontrol中與joe有關(guān)的的所有記錄仍然在那里。如果我們借助下一個(gè)可用的id(即2)添加另一個(gè)用戶的話,那么這個(gè)用戶就會(huì)繼承joe在accesscontrol表中的記錄。

對(duì)于提供引用完整性的數(shù)據(jù)庫(kù)來(lái)說(shuō),我們就可以規(guī)定該用戶標(biāo)識(shí)為accesscontrol表中的外鍵,這樣,當(dāng)該用戶的記錄刪除時(shí),那么在accesscontrol中對(duì)應(yīng)的所有記錄也會(huì)自動(dòng)刪除。

然而,在默認(rèn)情形下缺乏事務(wù)支持也可能會(huì)導(dǎo)致安全隱患。舉例來(lái)說(shuō),假設(shè)實(shí)現(xiàn)前面的系統(tǒng)的公司具有審計(jì)每次密碼改變的要求, 同時(shí)假定使用了如下所示的查詢:

 

假定這兩次查詢之間的服務(wù)器連接失敗。用戶的密碼將已經(jīng)更改,但是系統(tǒng)尚未進(jìn)行審計(jì)。如果我們正在使用非默認(rèn)的、支持事務(wù)的MySQL存儲(chǔ)引擎,那么我們就可以在第一個(gè)語(yǔ)句之前開(kāi)始事務(wù),然后在第二個(gè)語(yǔ)句之后提交事務(wù),那么密碼改變就不會(huì)漏掉審計(jì)了。

在4.0版本之前,MySQL并不支持UNION語(yǔ)句。由于SQL注入是最常見(jiàn)的數(shù)據(jù)庫(kù)攻擊形式之一,而UNION又是攻擊者的指令表中的關(guān)鍵部分,因此在防御SQL注入攻擊方面,通常認(rèn)為4.0版之前的MySQL要比其他數(shù)據(jù)庫(kù)系統(tǒng)更加安全。然而,應(yīng)用開(kāi)發(fā)人員卻對(duì)這一局限性頗為不滿;此外,如果您運(yùn)行版本較老的MySQL的話,那就會(huì)受到目前已經(jīng)修復(fù)的安全漏洞的威脅。所以,如果有一個(gè)功能受限同時(shí)又補(bǔ)丁齊全的MySQL就好了,但是看起來(lái)這是不可能的。如果讀者有志于此的話,抽時(shí)間您可以親自動(dòng)手試試。

此外,4.1版本之前的MySQL并不支持子查詢,下面是一個(gè)子查詢的例子:

 

由于進(jìn)行SQL注入攻擊時(shí),攻擊者通常能控制查詢字符串的部分字符,所以如果缺乏子查詢的話,那么從安全的角度來(lái)說(shuō)倒是一個(gè)優(yōu)點(diǎn)。然而,現(xiàn)實(shí)中如果缺乏某些特性的話,MySQL是很難推薦給管理層的,更別說(shuō)開(kāi)發(fā)團(tuán)隊(duì)了?!叭狈δ堋庇袝r(shí)候也是有好處的,例如Oracle沒(méi)有十分詳細(xì)的錯(cuò)誤信息,但是對(duì)于SQL Server 來(lái)說(shuō),這可能從錯(cuò)誤信息文本中檢索數(shù)據(jù),不過(guò)還好MySQL并沒(méi)有效仿這一點(diǎn)。

#p#

 

十、小結(jié)

在本文中,我們?yōu)樽x者詳細(xì)介紹了MySQL數(shù)據(jù)庫(kù)在體系結(jié)構(gòu)方面的安全問(wèn)題以及相應(yīng)的攻擊方法,在后續(xù)的文章中我們將介紹相應(yīng)的防御措施。

【編輯推薦】

  1. SHA也難逃我手:巧用Cain破解MYSQL數(shù)據(jù)庫(kù)密碼
  2. MySQL數(shù)據(jù)庫(kù)中的重要數(shù)據(jù)應(yīng)當(dāng)如何保護(hù)
  3. MySQL數(shù)據(jù)庫(kù)敏感數(shù)據(jù)安全保護(hù)六大措施
責(zé)任編輯:Oo小孩兒 來(lái)源: 51CTO.com
相關(guān)推薦

2021-04-27 10:00:27

網(wǎng)絡(luò)安全WebURL

2012-02-06 17:22:44

MySQL

2021-06-16 09:40:44

網(wǎng)絡(luò)安全物聯(lián)網(wǎng)代碼

2021-05-07 14:12:50

網(wǎng)絡(luò)安全Web安全CSRF

2021-05-13 20:38:30

2021-04-30 19:38:42

網(wǎng)絡(luò)安全WebHTTP

2021-05-08 15:22:31

網(wǎng)絡(luò)安全Web安全SQL

2021-04-01 10:40:22

網(wǎng)絡(luò)安全軟件

2010-10-20 17:26:26

SQLServer線程

2021-04-25 21:45:25

網(wǎng)絡(luò)安全網(wǎng)絡(luò)安全攻防ZigBee安全

2021-03-15 13:50:24

網(wǎng)絡(luò)安全Android安全機(jī)制

2021-03-22 10:52:58

網(wǎng)絡(luò)安全Android數(shù)據(jù)安全

2021-04-23 13:35:41

網(wǎng)絡(luò)安全藍(lán)牙Wi-Fi

2010-06-18 16:15:59

UML用戶指南

2021-03-24 09:46:46

網(wǎng)絡(luò)安全軟件反匯編

2009-06-26 15:58:28

EJB

2009-09-11 10:38:03

LINQ體系結(jié)構(gòu)

2018-04-23 09:25:24

MySQL結(jié)構(gòu)存儲(chǔ)

2009-07-15 13:46:26

Swing體系結(jié)構(gòu)

2014-07-23 09:33:52

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)