Oracle 学习
基础知识
端口号:1521下载地址:
http://download.oracle.com/otn/nt/oracle11g/112010/win32_11gR2_database_1of2.zip
http://download.oracle.com/otn/nt/oracle11g/112010/win32_11gR2_database_2of2.zip
https://www.oracle.com/tools/downloads/sqldev-downloads.html
sqldeveloper 工具连接

Oracle 权限
ORACLE 系统提供三种权限:
Object 对象级、System 系统级、Role 角色级
如果授予一个权限给特殊用户
Public(用户 public 是 oracle 预定义的,每个用户享有这个用户享有的权限),那么就意味作将该权限授予了该数据库的所有用户权限被大体分为两类:
系统权限:系统规定用户使用数据库的权限(系统权限是对用户而言)
系统权限就是我们常见的
CREATE SESSION、ALTER SESSION等权限,这些权限通常通过角色来进行分配oracle 中有几个常见的预定义角色:
DBA: 拥有全部特权,是系统最高权限,只有DBA才可以创建数据库结构RESOURCE: 拥有 Resource 权限的用户只可以创建实体,不可以创建数据库结构CONNECT: 拥有 Connect 权限的用户只可以登录 Oracle,不可以创建实体,不可以创建数据库结构
一般普通用户拥有
connect、resource角色,而管理员拥有connect、resource、dba角色
实体权限:某种权限用户对其它用户的表或视图的存取权限(是针对表或视图而言的)
简单说就是用户对表、视图、存储过程等有什么权限
表权限:
SELECT、DELETE、UPDATE、INSERT、ALTER视图权限:
SELECT、DELTE、INSERT、UPDATE过程、函数、程序包权限:
EXECUTE、DEBUG
权限查询
-- 查看所有角色 select * from dba_roles; -- 查看当前用户被激活的全部角色 select * from session_roles; -- 查看当前用户被授予的角色 select * from user_role_privs; -- 查看当前用户是否为DBA select t.DEFAULT_ROLE from user_role_privs t where t.granted_role='DBA'; -- 查看当前用户所拥有的全部权限 select * from session_privs; -- 查看当前用户的系统权限 select * from user_sys_privs; -- 查看当前用户的表级权限 select * from user_tab_privs; -- 查看某个用户所拥有的系统权限 select * from dba_sys_privs; -- 查看角色(只能查看登陆用户拥有的角色)所包含的权限 select * from role_sys_privs; -- 查看用户的java权限(用户名必须大写) select * from user_java_policy where grantee_name='SCOTT'; -- 设置输出列宽,优化 sqlplus 交互式命令行的输出 COL TYPE_NAME FOR A30; COL NAME FOR A30; COL ACTION FOR A10; select TYPE_NAME, NAME, ACTION from user_java_policy where grantee_name = 'TEST4';权限更改
可以通过 GRANT 和 REVOKE 命令来对账户进行权限的授予和撤回,一般这些操作会由 DBA 用户(SYS 用户和 SYSTEM 用户)来执行
而权限的赋予通常也是通过角色(Role)这个“桥梁”来做的(当然也可以直接赋给 user),举个例子,创建一个用户,并给该用户赋予
create session和create procedure
-- 进入交互式命令行 sqlplus -- 创建一个的用户 create user <用户名> identified by <密码>; -- 创建一个 role create role <角色名>; -- 将 connect 和 create procedure 赋给 testrole grant connect,create procedure to <角色名>; -- 将testrole这个角色给用户test grant <角色名> to <用户名>; -- 这样我们可以将 testrole 给多个用户,修改权限时只需要添加/删除角色的权限即可,方便批量管理,类似Active Directory中的组 -- 使用 revoke 收回某个权限 revoke create procedure from <角色名>; -- 修改用户密码 alter user <用户名> identified by <密码>; -- 删除用户和角色 drop user <用户名> cascade; drop role <角色名>;
PL/SQL注入
PL/SQL 是 Oracle 公司在标准 SQL语言 的基础上进行扩展,可以在数据库上进行设计编程的一种过程化的语言,类似程序语言 JAVA 一样可以实现逻辑判断、条件循环、异常处理等细节操作,可以处理复杂性问题
如果 PL/SQL 使用
AUTHID CURRENT_USER关键词创建,它执行时会以调用者(invoker)的权限来执行如果没有
AUTHID CURRENT_USER这个关键词,它执行时会以它的定义者(definer)的权限来执行注:Oracle不支持堆叠注入(多语句执行)
Cursor注入
下面这个 procedure 由 DBA(SYS) 创建,并赋予 public 执行权限,数据库能所有用户都可以调用这个 procedure
由于没有声明 AUTHID CURRENT_USER,所以该存储进程执行时的权限是其定义者(definer),也就是SYS
很明显 P_OBJNM 是存在 SQL 注入的,但由于 Oracle 不支持堆叠查询,我们只能够使用联合查询来注出一些数据,但仅仅查数据肯定不能满足我们的需求
创建一个执行其他命令的函数(需要 CREATE PROCEDURE 权限),并且加上 AUTHID CURRENT_USER,然后用 || 将函数注入到 SQL 语句中,当 SQL 语句以 SYS 权限执行时,这个被注入的函数作为 SQL 语句的一部分也会被执行
在这里的GET_DBA这种函数被称为辅助注入函数,如果我们没有办法自己创建辅助注入函数的话,就要寻找oracle上已经存在的、可以辅助注入的函数。其它的可以看这里:
https://www.t00ls.net/articles-23609.html
http://www.davidlitchfield.com/HackingAurora.pdf
Lateral SQL注入
主要针对以下两种情况:
Procedure 不接收用户输入的参数(参数不可控)
Procedure 中 SQL 语句拼接的参数被定义为 NUMBER 或 DATA 类型
下面这个存储过程接收一个日期类型的参数,并将参数动态拼接入 SQL 语句
下面这个存储进程不接收任何参数,拼接入 SQL 语句中的参数从 sysdate 中获取
权限提升
SET_OUTPUT_TO_JAVA
权限要求:
CREATE SESSION测试环境:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit原理:该函数可以利用前面提到的
Lateral SQL Injection来进行注入,进而获取 DBA 权限这个函数允许用户在另一个新的虚拟 session 中重定向 java 输出写入到 System.out 和 System.err,最后两个参数的 SQL 语句将在这个新 session 中执行
如果攻击者可以得到一个属于 SYS 的使用 java 的 package 并将它写入 System.out 和 System.err,那么这个新会话的所属者就是 SYS,进而所执行的 SQL 语句也将以 SYS 权限执行
而
DBMS_CDC_ISUBSCRIBE正是一个符合条件 package,它可被 public 执行,属于 SYS 并且是 definer 权限执行,通过将无效的订阅名传递给这个包的e INT_PURGE_WINDOW过程,则可以将错误强制写入 System.err,随后将以SYS权限执行前一个请求的参数中提供的SQL语句
利用
GET_DOMAIN_INDEX_TABLES
影响版本:
Oracle Database <= 10g R2 (未打补丁的情况下)测试环境:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit权限要求:
CREATE SESSION原理:
SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES函数的定义可以看到当
GET_TABLES != 1时,TYPE_NAME和TYPE_SCHEMA被直接动态拼接进 PL/SQL 语句中并执行,由于这个函数是以 definer 权限来执行的,所以我们注入的语句也会以 SYS 权限来执行因此我们构造语句,传入参数TYPE_NAME
本地用 pl/sql 手动打印
LT.FINDRICSET
测试环境:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit权限要求:
CREATE SESSIONCREATE PROCEDURE原理:该方法利用
SYS.LT.FINDRICSET这个函数的注入漏洞来实现权限的提升函数定义
这个函数又调用了
SYS.LTRIC.FINDRICSET,定义如下IN_TABLE_OWNER和IN_TABLE_NAME直接动态拼接到 SQL 语句中,是可以注入的点创建一个赋权的存储进程,然后闭合 SQL 语句,在参数处调用存储进程
利用:
注入环境中可使用
dbms_xmlquery.newcontext来执行
SDO_DROP_USER_BEFORE
测试环境:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit权限要求:
CREATE SESSION这个是一个触发器(trigger)漏洞,触发器在数据库里以独立的对象存储,它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行
原理:
SDO_DROP_USER_BEFORE触发器的的定义可以看出这个触发器是在 drop 用户时会执行对应的命令,而
dictionary_obj_name被动态拼接到 PL/SQL 中,存在注入但
SDO_DROP_USER_BEFORE这个触发器属于 MDSYS,而且是以definer的权限来执行的,MDSYS 在oracle 9i中是 DBA 权限,后来在10g R2上被降权了,因此无法直接通过注入来获取DBA权限但是也不是毫无办法,MDSYS 拥有
create any trigger,也就是说我们可以利用这个注入来任意创建触发器那么我们完全可以在 SYSTEM 下创建一个触发器来执行我们想要的命令,然后触发这个新创建触发器,从而以 system 来执行我们的命令
直接看 POC,使用游标创建一个 procedure(当然也可以不使用游标),该过程在 system 下创建一个触发器,当向
system.OL$中插入数据时(默认 public 可向该表中插入数据),就会触发执行grant dba to public之后将注入该procedure的payload放到drop的用户名中,触发SDO_DROP_USER_BEFORE执行,再向system.OL$中插入数据即可
利用
命令执行
DBMS_XMLQUERY
测试环境:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bitOracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit
权限要求:
CREATE SESSIONCREATE PROCEDURE创建用户
创建
java source创建函数
通过查询
OBJECT_ID来判断函数是否创建成功赋予需要的三个 java 权限:当前用户为 DBA 时,通常只需要为该用户赋予第一个执行权限即可
执行命令
创建存储进程执行命令
测试环境:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bitOracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit
权限要求:
CREATE SESSIONCREATE PROCEDURE有时执行命令也会碰到这种报错,此时需要为用户赋予 java 的对应权限,最好执行前先执行一次
dbms_xmlquery中赋予那三个权限的命令,如果你已经创建完 javae 函数在执行命令时发现了这个报错,那么要再执行一次 2.sql,然后再执行 javae 函数将下面文件分别保存为:
1.sql
2.sql
放在 sqlplus 同级目录下,然后分别执行
执行命令
DBMS_JAVA.RUNJAVA
测试环境:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bitOracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit
权限要求:
CREATE SESSION先给当前用户赋予
java.io.FilePermission执行命令
Web层面的利用
前面提到过 Oracle 并不支持堆叠注入,但是前面介绍的
dbms_xmlquery.newcontext是可以执行 PL/SQL 语句的,因此当我们遇到 Oracle 的 SQL 注入点时,就可以构造执行dbms_xmlquery.newcontext的语句来进行命令执行总结
一般 PL/SQL 注入利用的条件:存在注入的 PL/SQL 属于高权限用户(一般关注SYS),且以 definer 权限执行
对用户权限的要求:如果用户没有
CREATE PROCEDURE权限,则需要寻找数据库已有的辅助注入函数,如果用户有CREATE PROCEDURE权限,则可以自己创建辅助注入函数如果没有辅助注入函数
如果注入点是在
execute immediate后的 PL/SQL 语句中,那么可以考虑直接注入匿名 PL/SQL 语句块如果存在注入的是
insert、delete、update这三种类型的语句,那么我们就可以利用现有的语句进行增删改操作,特别是 insert 情况下可以通过将当前用户插入到 SYS.SYSAUTH$ 表中,同样可获得 DBA 权限如果存在注入的是 select 这种类型的语句,那么我们就只能对数据库进行查询操作,如
UNION SELECT PASSWORD FROM SYS.USER$,当然前提是它有输出
当遇到 Web 层面的 SQL 注入时,需要构造
dbms_xmlquery.newcontext执行 PL/SQL 的语句来进行命令执行即可
Last updated