Tuesday, April 7, 2015

Copying files out of a VM guest machine

A nice benefit of using a guest VM is that the host machine is protected from any malware that infects the guest (barring security vulnerabilities in the VM software itself). I've been using VMs fairly frequently over the past five years, first with VMWare, and now with VirtualBox.

If the guest machine is possibily affected by malware, how then can one transfer data from the guest to the host? Sending through e-mail divulges password information, and uploading to some type of file transfer site is slow and inconvenient. Running a ftp server or web server on the host takes time and introduces another attack surface. Using VirtualBox's shared clipboard works for text files and I was able to use it for binary files after escaping characters, but is also inconvenient and less sure to be safe. VirtualBox's default way of transfering files, emulating a SMB network drive, is not safe, as malware can propagate across a network drive.

I'll describe the approach I came up with. I do use bridged networking so that the guest can ping the host, but I disable all of VirtualBox's shared folders/network drives/USB connectivity. I then make sure that no shared folders on the host are publically writable. I install Python on the guest and use scripts to transfer files over a socket by ip address. (To see the guest's ip, in Windows ipconfig, in Linux ifconfig).

First run this script on the host, which I put together from some stack overflow answers,
import socket

f = open('output_file', 'wb')
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
portnumber = 8206
conn.bind(('', portnumber))
conn.listen(5)
channel, details = conn.accept()
  
print 'connected'
while True:
  received_data = channel.recv(4096)
  if not received_data:
    break
  f.write(received_data)
  
f.close()
print "transfer complete!"
channel.close()


Run this script on the guest, after changing the file name and ip address; I haven't found a need for the script to support files that won't fit into memory.
import socket

file_to_send = './filename'
ip_of_recipient = '192.168.10.105'
portnumber = 8206
f = open(file_to_send, 'rb')
all_file_contents =  f.read()

conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((ip_of_recipient, portnumber))
conn.sendall(all_file_contents)
conn.shutdown(socket.SHUT_RDWR)
conn.close()



To ensure that the data is intact, I can use a quick checksum with SHA512,
import hashlib

f1=open(r'./filename','rb')
hash = hashlib.sha512()
while True:
  # update the hash 256k at a time
  buf = f1.read(1024 * 256)
  if not buf: break
  hash.update (buf)

print hash.hexdigest()


The chances of malware are now much lower. Only one file can come through a port that is quickly closed. I don't use this to transfer executable files, though, as they can have been modified, but in general it seems to be a safer way to copy files from a VM.

No comments: