DNSLOG平台搭建从0到1 – 作者:dadadadudu

作者:saltor

1 前言

       DNSLOG是一种回显机制,常用于在某些漏洞无法回显但可以发起DNS请求的情况下,利用此方式外带数据,以解决某些漏洞由于无回显而难以利用的问题。主要利用场景有SQL盲注、无回显的命令执行、无回显的SSRF。本文介绍一种搭建DNSLOG平台的方法,旨在为渗透测试提供一些帮助。

2 前期准备

       一个域名,一台vps

       本文使用的是:阿里云购买的域名和云服务器ECS

       域名:example.icu

       vps ip:100.100.100.100

3 实验过程

3.1 添加DNS解析

       在云解析DNS处添加一条A记录和一条NS记录,如图所示:

1.png

3.2 对外开放53端口

       在云服务器ECS安全组规则里添加对外开发53端口的规则,协议是udp。

2.jpg

3.3 DNSLOG代码

       dnslog.py

       运行在python2下,无需安装依赖包。

 

       #!/usr/bin/env python

       # -*- coding: utf-8 -*-

 

       import SocketServer

       import struct

       import socket as socketlib

 

       # DNS Query

       class SinDNSQuery:

           def __init__(self, data):

               i = 1

               self.name = ”

               while True:

                   d = ord(data[i])

                  if d == 0:

                      break;

                  if d < 32:

                       self.name =self.name + ‘.’

                   else:

                      self.name =self.name + chr(d)

                  i = i + 1

               self.querybytes =data[0:i + 1]

               (self.type,self.classify) = struct.unpack(‘>HH’, data[i + 1:i + 5])

               self.len = i + 5

           def getbytes(self):

               return self.querybytes+ struct.pack(‘>HH’, self.type, self.classify)

 

       # DNS Answer RRS

       class SinDNSAnswer:

           def __init__(self, ip):

              self.name = 49164

               self.type = 1

               self.classify = 1

               self.timetolive = 190

              self.datalength = 4

               self.ip = ip

           def getbytes(self):

               res =struct.pack(‘>HHHLH’, self.name, self.type, self.classify, self.timetolive,self.datalength)

               s = self.ip.split(‘.’)

               res = res +struct.pack(‘BBBB’, int(s[0]), int(s[1]), int(s[2]), int(s[3]))

               return res

 

       # DNS frame

       class SinDNSFrame:

           def __init__(self, data):

               (self.id, self.flags,self.quests, self.answers, self.author, self.addition) =struct.unpack(‘>HHHHHH’, data[0:12])

               self.query =SinDNSQuery(data[12:])

           def getname(self):

               return self.query.name

           def setip(self, ip):

               self.answer =SinDNSAnswer(ip)

               self.answers = 1

               self.flags = 33152

           def getbytes(self):

               res =struct.pack(‘>HHHHHH’, self.id, self.flags, self.quests, self.answers,self.author, self.addition)

               res = res +self.query.getbytes()

               if self.answers != 0:

                   res = res +self.answer.getbytes()

               return res

 

       # A UDPHandler to handle DNS query

       class SinDNSUDPHandler(SocketServer.BaseRequestHandler):

           def handle(self):

              data =self.request[0].strip()

               dns =SinDNSFrame(data)

               socket =self.request[1]

               namemap =SinDNSServer.namemap

               if(dns.query.type==1):

                  # If this is query a A record, thenresponse it        

                  name =dns.getname();

                   toip =namemap[‘*’]

                   dns.setip(toip)

                   print ‘%s:%s–>%s’%(self.client_address[0], name, toip)

                   socket.sendto(dns.getbytes(),self.client_address)

               else:

                   # If this is notquery a A record, ignore it

                  socket.sendto(data, self.client_address)

       # DNS Server

       class SinDNSServer:

           def __init__(self,port=53):

               SinDNSServer.namemap ={}

               self.port = port

           def addname(self, name,ip):

               SinDNSServer.namemap[name] = ip

           def start(self):

               HOST, PORT =”0.0.0.0″, self.port

               server =SocketServer.UDPServer((HOST, PORT), SinDNSUDPHandler)

               server.serve_forever()

 

       if __name__ == “__main__”:

           sev = SinDNSServer()

           sev.addname(‘*’,’127.0.0.1′) # default address

           sev.start() # start DNSserver

 

       在vps上直接运行dnslog.py,一个简易的DNSLOG平台就搭起来了。

       运行效果如下图: 3.png        回显的ip地址可通过sev.addname(‘*’, ‘127.0.0.1’)自定义。

4 WEB界面

       使用tornado框架写一个web界面。

       项目已上传至github:https://github.com/sa1tor/dnslog

 

       pip安装tornado之后直接运行server.py即可,当然也可以使用Nginx+Tornado+Supervisor来进行部署。

 

       pip install tornado

       python server.py

 

       默认在8000端口,浏览器访问http://ip:8000/ 即可看到web界面

       我指定了6002端口,python server.py –port=6002

4.jpg 

       界面比较简单,只有3个按钮,getsubdomain按钮用来获取随机子域名,refresh按钮用来刷新页面,delete all按钮用来删除所有记录。

 

5 后记

       网上的相关实验大多数都是使用两个域名来实现的,一个域名修改DNS服务器,另一个域名修改NS记录。不过其实只用一个域名也是可以的。

       修改DNS服务器如下图:

5.jpg

 

 

来源:freebuf.com 2020-05-26 15:21:24 by: dadadadudu

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论