def test_findNotificationTmClientProfile(self): client = upnp(None, None, None) data = "NOTIFY * HTTP/1.1\r\nCache-control: max-age=1800\r\nHost: 239.255.255.250:1900\r\nUsn: uuid:547af669-7984-6c6a-0000-00000bcfbcb2::urn:schemas-upnp-org:service:TmClientProfile:1\r\n" data += "Location: http://192.168.1.101:53712/dev/547af669-7984-6c6a-0000-00000bcfbcb2/desc.xml\r\nNt: urn:schemas-upnp-org:service:TmClientProfile:1\r\n" data += " Nts: ssdp:alive\r\nServer: Linux/2.6.35.10-gd2564fb UPnP/1.0 4thLine-Cling/1.1\r\n" self.assertTrue(client.findRequest(data, "service", "TmClientProfile"))
def test_findRequestMsearch(self): client = upnp(None, None, None) data = "M-SEARCH * HTTP/1.1\r\nHost:239.255.255.250:1900\r\nCache-Control:max-age=60\r\n" data += "Location:http://192.168.1.1:80/upnp/service/descrip.xml\r\nNT:urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n" data += "NTS:ssdp:alive\r\nServer:NT/5.0 UPnP/1.0\r\nUSN:uuid:upnp-WANConnectionDevice-1_0-001ee58cab66::urn:schemas-upnp-org:device:WANConnectionDevice:1" self.assertFalse(client.findRequest(data, "device", "WANConnectionDevice"))
def main(): client = upnp() print "Entering main" myip = '' #should be localhost myport = 0 #Have to create a new socket since replies will be sent directly to our IP, not the multicast IP server = client.createNewListener(myip, myport) if server == False: print 'Failed to bind port %d' % myport return server.settimeout(2) type = 0 types = ["ssdp:all", "upnp:rootdevice"] request= \ "M-SEARCH * HTTP/1.1\r\n"\ "HOST: %s:%s\r\n"\ "MAN: \"ssdp:discover\"\r\n"\ "MX: 1\r\n"\ "ST: %s\r\n"\ "\r\n" % (client.DEFAULT_IP,client.DEFAULT_PORT,types[type]) print "\"" + request + "\"" client.send(request, server) print "Discovery sent" while True: data = client.listen_from(1024, server) # data = client.listen(1024,server) if data is None: break print("\n\r" + str(data[1]) + "\n\r" + str(data[0]))
def test_findRequestNotifyRequest(self): client = upnp(None, None, None) data = "NOTIFY * HTTP/1.1\r\nHost:239.255.255.250:1900\r\nCache-Control:max-age=60\r\n" data += "Location:http://192.168.1.1:80/upnp/service/descrip.xml\r\nNT:urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n" data += "NTS:ssdp:alive\r\nServer:NT/5.0 UPnP/1.0\r\nUSN:uuid:upnp-WANConnectionDevice-1_0-001ee58cab66::urn:schemas-upnp-org:device:WANConnectionDevice:1" client.findRequest(data, "device", "WANConnectionDevice") self.assertEqual(client.upnpRequest['location'], "http://192.168.1.1:80/upnp/service/descrip.xml") self.assertEqual(client.upnpRequest['host'], '239.255.255.250:1900' ) self.assertEqual(client.upnpRequest['server'], 'NT/5.0 UPnP/1.0')
def test_buildMsearchRequest(self): client = upnp(None, None, None) MsearchRequest = "M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nST:urn:schemas-upnp-org:device:test:1" self.assertTrue(client.buildMsearchRequest("device", "test").startswith(MsearchRequest))
def test_findRequestMsearch(self): client = upnp(None, None, None) data = "M-SEARCH * HTTP/1.1\r\nHost:239.255.255.250:1900\r\n" self.assertFalse(client.findRequest(data, None, None))
def test_getTypeAndName(self): client = upnp(None, None, None) self.assertEqual(client.getTypeAndName("urn:schemas-upnp-org:device:WANConnectionDevice:1"), ("device", "WANConnectionDevice") )
def build_ssdp(st): request = 'M-SEARCH * HTTP/1.1\r\n'\ 'HOST: 239.255.255.250:1900\r\n'\ 'ST: %s\r\n'\ 'MAN "ssdp:discover"\r\n'\ 'MX: 2' % (st) return request def fuzz_msearch(): server = hp.createNewListener('', False) if server == False: print 'Failed to bind port %d' % lport return fuzz_data = get_fuzz_data() fuzz_data.append('"ssdp:discover"') fuzz_data.append('upnp:rootdevice') #print fuzz_data try: while True: request = build_ssdp(get_random_str(fuzz_data)) hp.send(request,server) print hp.recv(1024,server) except KeyboardInterrupt: print '' sys.exit(0) if __name__ == '__main__': hp = upnp(False, False, None, None) fuzz_msearch()
def fuzz(): init() hp = upnp(False, False, None, None) ''' first we send a request to 239.255.255.250:1900 to discover upnp servers. all information about the upnp server will be saved in the structure of ENUM_HOSTS ''' msearch(None, None, hp) ''' fisrt, we get the description xml. then by the desc-xml, we get a service's SCPDURL location which describes the service of upnp server, including a service's actions and its arguments. And we must get a service's control-url which we will send our actions to it. ''' #List UPnP servers command = ['host', 'list'] host(len(command), command, hp) #Sending request to get the desc-xml scount = len(hp.ENUM_HOSTS) for i in range(0, scount): command = ['host', 'get', i] host(len(command), command, hp) if debug: for i in range(0, scount): command = ['host', 'summary', i] #host(len(command), command, hp) host_ip = None ''' after getting the infomation we need, we constuct some packages sending to the control url. ''' fuzz_times = 1 state = False fuzz_data = get_fuzz_data() #A large loop print "\n\n[+] Fuzzing......" print '[+] Stage 1 fuzzing start.......' for i in range(0, scount): devices = get_devices(hp, i) #print devices for device in devices: services, services_ctrurls = get_services_and_control_urls( hp, i, device) for service in services: actions = get_actions(hp, i, device, service) for action in actions: argList, args = get_args(hp, i, device, service, action) if len(args) == 0 or len(argList) == 0: continue #print args control_url = services_ctrurls[service] for data in fuzz_data: sendArgs = {} for argName, argVals in args.iteritems(): #print '.....' #print argVals actionStateVar = argVals['relatedStateVariable'] stateVar = hp.ENUM_HOSTS[i]['deviceList'][device][ 'services'][service]['serviceStateVariables'][ actionStateVar] if argVals['direction'] == 'in': ''' there is a problem that if the data type is bin.base64, before sending our requests, we must encode the data(or argument) ''' if stateVar['dataType'] == 'bin.base64': data = base64.encodestring(str(data)) sendArgs[argName] = (data, stateVar['dataType']) #print sendArgs #print len(sendArgs) if len(sendArgs) > 0: service_fullName = get_fullName_by_service( hp, i, device, service) fuzz_case = Fuzz_case(service_fullName, control_url, action, sendArgs) fuzz_times += 1 state = do_fuzz(hp, i, fuzz_case, False) ''' #get host ip address host_ip = hp.ENUM_HOSTS[i]['name'].split(':')[0] host_port = hp.ENUM_HOSTS[i]['name'].split(':')[1] #print host_ip state = check_service(host_ip, int(host_port)) ''' if state == False: print "[-] Can't receive data. Server crashed?" #sys.exit() #We must save the data to analyse. with open('crash/data_crash', 'a+') as f: f.write('[+] ') f.write('host: ' + hp.ENUM_HOSTS[i]['name']) f.write('\tdevice: ' + device) f.write('\tservice: ' + service) f.write('\taction: ' + action) f.write('\targs: ' + str(sendArgs)) f.write('\n') fuzz_http_xml() print '\n[+] Fuzzing finished! Just check the crash directory!'