<style>
h2 {
border-bottom: 1px solid #ddd;
}
h3 {
border-bottom: 1px solid #eee;
}
section {
margin-bottom: 2rem;
padding: 0em 1em;
padding-bottom: 1em;
border-radius: 4px;
background-color: #f7f7f7;
border: 1px solid #ccc;
}
center {
text-align: center;
}
summary {
font-weight: bolder;
}
summary:hover {
text-decoration: underline;
}
.alert details {
background-color: transparent !important;
}
code {
background-color: rgb(244,244,245) !important;
color: #ff0000;
}
.alert-warning {
background-color: #fcf8e3 !important;
color: #8a6d3b !important;
}
.alert-success {
background-color: #dff0d8 !important;
color: #3c763d !important;
}
</style>
**[« Back to the main CSCI1660 website](https://brown-csci1660.github.io)**
# Flag project setup guide
This guide is designed to help you get started with setting up the environment you'll use for the Flag project.
The primary component of the project is the "Flag portal," a *very* insecure website that you will attack in order to give you practice discovering some real vulnerabilities and proposing fixes. In order to let you conduct attacks in a safe, repeatable way, we provide the website to you as a container image--you will run this container on your computer, which will host a version of the Flag portal for you to attack.
This guide will provide instructions on how to set up the flag container environment and how to work with it for the project.
## Before you start: updates to your Docker setup
**New to docker?** Before you can start download the Flag container environment, you'll need Docker installed on your system. If you do not have Docker installed from the last project, you can do so using [this guide](https://hackmd.io/@cs1660/container-setup).
Before continuing, now is a good time to check in and make sure your container setup is performing optimally. If your container ran slowly or had issues during Project 1, take a look at the following notes and recommendations:
:::warning
<details markdown="1"><summary markdown="span"><b><u>MacOS users: if you had slow filesystem performance</u></b></summary>
If you experienced exceptionally slow filesystem performance on MacOS, see [here](https://hackmd.io/@cs1660/container-setup#Filesystem-Performance-on-Macs) for instructions on how to update your docker settings for a fix.
If you still encounter poor filesystem performance, or you have issues after the fix, please let us know!
</details>
:::
:::warning
<details markdown="1"><summary markdown="span"><b><u>Windows users: Important instructions for making Docker more usable</u></b></summary>
It seems that recent versions of Docker and WSL have issues with memory usage.
See [these instructions](https://hackmd.io/@cs1660/container-setup#Windows-performance-and-stability-issues) for a full writeup of the problem and a list of workarounds that we think will help. If you encountered issues with Docker during project 1, we strongly recommend that you do the following steps from this guide now:
1. Update Docker to the latest version (if you installed it from a previous class)
2. [Set a memory limit on WSL](https://hackmd.io/@cs1660/container-setup#Workaround-1-Limit-WSL%E2%80%99s-memory-usage) (and thus your docker containers)
The instructions also list some workarounds you can use at times to help reduce Docker/WSL's memory usage when they start to get problematic--skim these over and then keep them in mind in case you run into issues!
</details>
:::
<!--
### Updating your development container
For project 1, we asked you to download a container with a development environment you could use for the project. From now on, we'll call this the *"development container"*--this container is a good baseline Linux system that you can use for general development. In Project 2, you won't use this container as much since you won't be writing as much code, but you may find it useful to run commands from a Linux system.
We've made some updates to the development container to make it compatible with project 2, and we added some optimizations to reduce disk space (4GB => 2GB!). To update your environment with the new changes, you should do the following:
1. Open a terminal to where you cloned the container environment repo (ie, where your `run-container` script lives)
2. Update the container scripts to the latest version by running the following:
```
$ git pull origin main
```
This loads a new version of the `run-container` script and updated, optimized Dockerfiles!
:::info
**Git errors?** If you changed any of the container scripts due to debugging and get git errors due to local changes, you can reset them to their original state using `git checkout HEAD <name of file>`. Alternatively, run `git reset --hard HEAD` to revert all tracked files to their original state.
:::
3. Run the following commands to update your container image:
```
$ ./run-container clean-image # Remove your old container image
$ ./run-container setup # Update to the latest container image
```
:::info
**Windows users**: If you receive errors about newlines, you may need to run `dos2unix` again--see [this section](https://hackmd.io/@cs1660/container-setup#Windows-line-endings-%E2%80%9Cunexpected-end-of-file%E2%80%9D) for details.
:::
You should now have the latest version of the development container, yay! To try it out, run `run-container`:
```
$ ./run-container
cs1660-user@9899143429a2:~$ # you're inside the container!
```
As part of the updates, we've added a bunch of options to `cs1660-run-docker` to handle common container operations. You won't need these now, but run `./cs1660-run-docker help` to take a look!
-->
## Flag container setup
To get started, we can download the flag container and start working with the project! We'll be using more features of Docker containers in this project, so first it's important to understand some background on how containers work.
<!--
For the bulk of the project, you'll be interacting with a new container that we'll call the *Flag container*--this new container hosts the Flag portal website you'll be attacking! In general, you'll end up running two containers at the same time: the flag container hosts the website, while the development container will be useful for testing.
If CS1620/CS2660 students will download one additional container for the Bob's router portion. -->
### Super important container terminology
As you attack the flag website, you will inevitably make changes to the website's state (like the server's filesystem, database, etc.) in ways that will break it. This is okay--and, in fact, encouraged! This is how you'll learn about the system and how it's vulnerable.[^1]
[^1]: Breaking things isn't the *only* way to test the security of a system. It's possible to study a system in a stealthy manner, but this is much more difficult and beyond the scope of this course.
What this means is that we need an easy way to make changes to the flag webserver and then revert it to a clean state, which is exactly the kind of workflow that containers were designed to do.
Up to this point, we've abstracted away some of the details of how containers work--now that we'll be using them for their primary purpose, here's some important terminology we'll use as we work with the flag container:
- When we download or set up or a container, we create a **container image** (often just called an "image"): This is a self-contained, read-only collection of files and settings that tell Docker how to run the software--think of it like a "template" for how the software runs
- To actually run the code inside the image, docker creates a **container instance** (often just called a "container"), which is a specific *instance* of a container image. Unlike images, container instances are read-write. <u>Here's the crucial bit: as the code inside the container runs, only the instance changes--the original image is unaffected!</u>
After testing, Docker makes it easy to discard the container instance and start over from the image, which is what we'll use in the project!
### Our container infrastructure
While working on this project, you'll have at least two containers on your system:
- The **flag portal container**: A new container for this project, which hosts the portal website
- The **"development container"**: This is the container you used in project 1 (and just updated in the previous section). For this project, you can think of this container as just a generic Linux system you can use to edit code or run exploits.
- **Bob's router (CS1620/CS2660 only)**: This container contains extra components for the CS1620/CS2660 portion of the project (more on this later)
We've provided scripts for managing each container--you'll gain some practice with them in this guide.
#### Recommended filesystem layout (and cloning the stencil repo)
To make development easier, we recommend cloning your stencil code for this project so you can access files in it from your development container. To do this, we recommend cloning the stencil in your `DEV-ENVIRONMENT/home` directory, where `DEV-ENVIRONMENT` is the name of the folder you used when you cloned the development container.
Here's an example of what your filesystem might look like (based on what you might have from project 1):
```
- ...
|--DEV-ENVIRONMENT
| |--docker/
| |--home/
| | |--pr01-cryptography-yourname/
| | |--pr02-flag-yourname/ # <----------- Clone your stencil here!
| |--run-container
| |-- ...
...
```
### Downloading the flag container image
In the stencil repository, we've provided another script called `run-container`, which automates downloading the flag container image and starting an instance of the webserver.
:::info
**Note**: the flag container runs separately from the "development container" container you used in the previous project, though you'll interact with it in a similar way. Both containers have a `run-container` script--these scripts essentially do the same things, but they operate on different containers. For example:
- The script `DEV-ENVIRONMENT/run-container` controls your development container
- The script in your flag repo `pr02-flag/run-container` controls the flag container
Since the `run-container` scripts need to interface with Docker, always make sure that you run `./run-container` from a terminal on your **host system** (or a WSL terminal, for Windows).
The rest of this guide will demonstrate how to work with everything, but keep the differences in mind as you read the instructions!
:::
To download the flag container image, do the following:
1. If you have not done so already, clone the stencil repository for the project (link in the handout)
2. Open a new terminal on your **host machine** (or, on Windows, a **WSL terminal**).
3. `cd` to the flag project stencil directory and run the following:
```shell
# Download the container image
$ ./run-container setup
```
:::warning
**Windows users**: If you get errors running this script the first time, you may need to run `dos2unix` on the script. See [here](https://hackmd.io/@cs1660/container-setup#Windows-line-endings-%E2%80%9Cunexpected-end-of-file%E2%80%9D) for more info.
:::
This will download the latest version of the container image from our repository, which may take a few minutes. If we push updates to the image while the project is out, you can run this command again to pull the latest version (we'll post an announcement on Ed if this happens).
### Running the container
Now that the image is setup, we can launch an instance of the container, which starts up the flag portal webserver.
In a terminal on your host machine (or a WSL terminal on Windows), run the command `./run-container`. This should produce output that looks like this:
```shell
$ ./run-container # Start an instance of the flag webserver container!
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Found network net-cs1660, skipping creation
***************************************************************************************
Container version: flag-webserver cs1660-flag-dev-d66e411-2023-02-24T20:13:22-05:00
Starting webserver at http://localhost:8888
Note: any warnings you see after this are safe to ignore if the URL
works--if not, include this log when posting about errors
*** Container network info ***
This container's internal IP: 172.19.0.2
This container's internal hostname: flag-webserver
***************************************************************************************
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.19.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.19.0.2. Set the 'ServerName' directive globally to suppress this message
[Sun Feb 26 18:46:38.172735 2023] [mpm_prefork:notice] [pid 23] AH00163: Apache/2.4.54 (Debian) PHP/8.2.3 configured -- resuming normal operations
[Sun Feb 26 18:46:38.172818 2023] [core:notice] [pid 23] AH00094: Command line: 'apache2 -D FOREGROUND'
```
Running `./run-container` with no arguments starts up an instance of flag container, which runs a webserver that hosts the portal. Once started, the container prints out some information about how to connect to it, as well as a log of the webserver's operation. As you work on the project, you may find this information useful.
:::success
**What to expect**: After starting the container, your terminal should look like the example above and appear to hang--this indicates the webserver is running normally and waiting for you to connect to it, which we'll do in the next step.
Unlike your container for project 1, **this container does not launch a shell**: the point of this project is to attack the flag portal by exploiting vulnerabilities *in the flag portal website*, so you won't have access to a terminal unless you exploit a web vulnerability to acquire one!
:::
If you receive an error when launching the container, or the container otherwise quits and returns you to your terminal, please post on Ed and include this log output so we can help you debug.
:::warning
<details markdown="1"><summary markdown="span"><b><u>If you get an error "could not bind to port 8888"</u></b></summary>
This issue might occur if another program on your system is using port 8888, the default port used by the webserver. If this occurs, do the following:
1. Stop your flag container by pressing `Ctrl+C` in the terminal.
2. Run the command `./run-container clean; ./run-container` and try again.
3. If the issue persists, open up the `run-container` script and find the line `webserver_port=8888` near the top. Change the port number (8888) to another number, like 8889--it should look like this:
```shell
maindir=""
container_name=flag-webserver
network_name=net-cs1660
webserver_port=8889 # <---- Change this to a number not 8888 (in the range 1024-65535)
```
4. Save the script and try running `./run-container` again. If there is no error, connect to the webserver using `http://localhost:<NEW PORT>`, where `<NEW PORT>` is the new number you picked. **Note**: When the webserver starts, it will still tell you to connect on port 8888--this is a known issue (the value is hard-coded in the startup info)--you should connect with your new port anyway.
5. If the issue still persists, please check Ed for any similar issues, or feel free to make a new post.
</details>
:::
<section>
#### Stopping/Restarting the flag webserver
*(Don't do this now, but take note for later)* You can stop the webserver by pressing `Ctrl+C` in this terminal. By default, any changes made to the server's database or filesystem are preserved--for instructions on how to reset the webserver to clean state, see [here](#Resetting-the-webserver).
If you lose the terminal where you ran `./run-container` for some reason, you can also stop it by running `./run-container stop` from another terminal. Once stopped, you can restart the webserver again by running `./run-container`.
</section>
### Connecting to the flag portal
Now we can connect to the flag portal website! To do this:
1. Make sure your flag container is running (your terminal should look like the previous step)
2. Open a browser on your host machine and go to [http://localhost:8888](http://localhost:8888). You should be presented with the Flag portal, which should look like this:
<!-- :::info
NOTE: we recommend using Firefox for this assignment when connecting to http://localhost:8888.
::: -->
![](https://hackmd.io/_uploads/r1mQNEKAi.png)
If you are unable to connect to the site, make sure your webserver is running from the previous step and has not exited. As a quick fix, try restarting it with `./run-container --clean`. If the issue persists, please check or post Ed to let us know!
## Working with the flag portal
Once you can connect to the flag portal, you can begin to poke around and start attacking the site! This guide will demonstrate the most important mechanics you should know as you work on discovering vulnerabilities.
### What you know
The Flag portal is part of a fictional grading system at Blue University (think like Gradescope, but more insecure). You've managed to obtain the login credentials for one student (or maybe you are the student? you decide...):
```
Username: qmei
Password: iamqmei
```
Given this information, your job is to explore the flag portal website and see what vulnerabilities you can find. For more information on the types of vulnerabilities we expect you to find, and specific requirements for the project and grading, please see the handout and the [wiki](https://brown-csci1660.github.io/flag-wiki/).
:::danger
**Remember**: for this project, your goal is to find vulnerabilities in the flag portal website itself, **any attacks on the container infrastructure itself are out of scope and will receive no credit.**
<details markdown="1"><summary markdown="span"><b>What does this mean?</b></summary>
The point of this project is to help you lean about web vulnerabilities, meaning we want you to behave as if you are a remote attacker who can only access the portal website. Since the container runs on your own computer, you can *easily* use `docker` commands or other methods to "break in" and get a root shell, view files, etc.--these are outside the capabilities of the attacker we want to guard against (called the "threat model") and thus are NOT considered vulnerabilities.
Remember that you are being graded based on the web vulnerabilities you find (and your explanations of them)--attacks out of this scope will not receive credit, and are not in your best interest for learning about web vulnerabilities. (We'll learn about more OS vulnerabilities in the next project--and *maybe* Nick will talk about attacks on containers.)
</details>
:::
### Tutorial: Resetting the container
As you attack the flag website, you will inevitably make changes to the website's state (like the server's filesystem, database, etc.) in ways that will break it--this is okay, and encouraged!
During this process, you'll find it useful to reset your website to its default configuration to test out attacks once you've figured out a procedure, and to conduct different attacks that may conflict with each other.
#### Making a change to the website
To try this out, let's alter the website to demonstrate how this works:
1. Log into the website using the credentials in the previous section
2. Go to the profile page and add a comment, then, like the figure below.
![](https://hackmd.io/_uploads/BJFhkrt0j.png)
3. Press the **Comment** button. This alters the website's database--if you were to change pages or restart the webserver, this comment would persist.
#### Resetting the container
Now let's see how to reset the webserver and erase this change to show you how it works. To do this:
1. **Stop your flag webserver container** by pressing `Ctrl+C` in the terminal. Alternatively, you can run `./run-container stop` from another terminal
2. Run **`./run-container --clean`**. This will delete your container instance and start a new container from a fresh copy of the image.
3. Refresh your tab with the portal website, or go to http://localhost:8888. You'll be prompted to log in again--your profile should be the same as before!
### Final notes
This guide has provided an overview of the most important mechanics you need to work with the container for this project. As you work on the project, keep in mind our [Useful tools and resources]()
)
If you have questions, please feel free to come to hours or post on Ed. Have fun, and happy hacking!
**If you are doing the CS1620/CS2660 part, Bob's router**, see the next section for more guides and instructions for using the extra tools required for this component.
:::success
**Now that you are done, please [fill out this form](https://forms.gle/EwvjY7k13W6uzbAE9)** to let us know you can access the webserver! This will help us make sure everyone can access these critical tools.
:::
## Bob's router setup guide
Bob's router uses an additional container, which is provided as part of your stencil repo. This extra container (which we'll call the "Bob container") performs all tasks ascribed to "Bob" in the handout. You don't know everything that Bob is doing, but here are the most important parts:
- The Bob container runs a script that fetches the main page of the flag portal (equivalent to when you visit http://localhost:8888) every 10 seconds from a browser that runs inside the container. You don't get to see this browser, but you'll see its requests in the log for the flag container
- The Bob container also hosts a website that mimics "Bob's router"--**you can't access this website directly**. Instead, the goal is to perform a CSRF attack on Bob in order to attack the router!
### How to run the Bob container
The Bob container has a separate `run-container` script in the `bob-router` directory of your stencil repo. You can use this `run-container` script the same way you use the flag container (ie, downloading the image, starting/resetting the container, etc). This guide describes the most important parts.
#### First-time setup
First, we need to download the container image for the Bob container. To do this:
2. Open a new terminal on your **host machine** (or, on Windows, a **WSL terminal**).
3. `cd` to the `bob-router` directory of the stencil repository
```shell
# Download the container image
user@host-or-wsl:../flag-stencil/bob-router$ ./run-container setup
```
:::warning
**Windows users**: If you get errors running this script the first time, you may need to run `dos2unix` on the script. See [here](https://hackmd.io/@cs1660/container-setup#Windows-line-endings-unexpected-end-of-file) for more info.
:::
This should download the container image, similar to how you set up the flag container.
#### Starting the Bob container (and what to expect)
Now we can start up Bob. To do this:
1. If you have not done so already, start up the Flag webserver container and make sure you can access the portal. **Leave this container running.**
2. Open a new terminal on your host machine (or a WSL terminal on Windows) and `cd` to the `bob-router` directory of your stencil repo
3. Run `./run-container`. This should produce output that looks like this:
```shell
user@host-or-wsl:../flag-stencil/bob-router$ ./run-container # Start an instance of the Bob container!
*************************************************************************
Container version: bob-router cs1660-bob-0f23b83-2023-02-28T19:
Bob starting ...
In your flag container's main terminal, you should see log entries
this container's internal IP showing that Bob is fetching the w
every 10 seconds.
If not, restart this container (possibly with --clean) to reset
*** Container network info ***
This container's internal IP: 172.19.0.3
This container's internal hostname: bob-router
*************************************************************************
Starting Bob's "router"
Starting Bob's auto-refresh script
Xvfb: no process found
AH00558: apache2: Could not reliably determine the server's fullmain name, using 172.19.0.3. Set the 'ServerName' directive globss this message
AH00558: apache2: Could not reliably determine the server's fullmain name, using 172.19.0.3. Set the 'ServerName' directive globss this message
<br />
<b>Deprecated</b>: Directive 'allow_url_include' is deprecated /b> on line <b>0</b><br />
[Sun Mar 05 17:52:20.145075 2023] [mpm_prefork:notice] [pid 26] e/2.4.54 (Debian) PHP/8.2.3 configured -- resuming normal operat
[Sun Mar 05 17:52:20.145147 2023] [core:notice] [pid 26] AH00094: 'apache2 -D FOREGROUND'
BOB: Started firefox
```
:::success
**What to expect**: Bob takes several seconds to start. Once you see `BOB: Started firefox`, Bob should be running successfully! Like the flag container, note that **this container does not start a shell**--there is no terminal for you to access. After Bob has started, you won't see any further output in this terminal until you've accessed the router. For more info on how to tell if Bob is running, see the next section.
:::
### How to tell if Bob is running
While working with the Bob container, you should have terminals open to **both** the flag webserver and the Bob container---both of these containers need to be running for Bob to work.
Normally, Bob's container doesn't print anything. However, you can check that Bob is fetching the flag portal regularly by looking at the log in your main **flag webserver container**--you should see requests for `GET /` from the IP address of Bob's container every 10 seconds. Here's an example of what this should look like:
![](https://hackmd.io/_uploads/HJHAo8Myn.png)
If your terminals look like this, Bob is running normally, yay! To begin attacking Bob's router, see the handout for a high-level description of the attack you'll be trying to perform. For more details, see the Gearup slides and recording. If you're ever concerned the Bob container isn't running normally, see [Resetting Bob](#Resetting-Bob).
:::info
**"What does Bob's container print?"** Just like the flag webserver container shows a log of requests made to the flag portal's webserver, the Bob container shows a log of requests for **the router's webserver**. You can't access this webserver normally, but if the CSRF phase of your attack is successful, you'll see output here once Bob successfully fetches the router's webpage!
(This is more information than you'd actually have while performing this kind of attack, but it's available to you for debugging purposes.)
:::
#### Resetting Bob
**If you stop seeing regular requests from Bob**, it's likely Bob is broken. To reset Bob:
1. Press `Ctrl+C` in the Bob container terminal to shut down the container
2. In this same terminal (or a new terminal on your host system), run `./run-container --clean`. This should reset the Bob container to its original state and restart it.
## Useful tools and tips
There are three extra tools within the container environment you may find useful with this project, most especially for Bob's router:
- [Listening on a port (webhook)](#Listening-on-a-port-with-Webhook.site): an easy way to **receive** and display incoming HTTP requests
- [Listening on a port (netcat)](#Listening-on-a-port-with-netcat): an alternate method to receive arbitrary HTTP requests (GET, POST, etc.), or to listen for connections from a reverse shell
- [Serving files with a simple webserver](#Simple-webserver-Hosting-arbitrary-files): use to **host** arbitrary files or scripts that you want another container to download (eg. to get another system to load your exploit code)
- [Using a reverse shell](#PHP-reverse-shell)
These aren't the only ways to accomplish these tasks. However, we'll describe methods you can use that work within the container environment, meaning that they don't require access to other web hosting services or platforms.
### Listening on a port (with `webhook.site`)
Sometimes, you may want to have your exploit code make a web request to some location that you control. This is useful when you want to *exfiltrate* some information from a user's browser, like stealing a cookie or revealing some other information about their browser or location.
This is particularly useful in scenarios where you are unable to directly view the HTTP response, but have the capability to redirect the response to a different endpoint.
To do this, we need a URL for your exploit to connect to--this is a common way for web applications to communicate. While we *could* do this by setting up a custom webserver to receive and process requests in a certain way, for this project we really just need a way to print out a list of who connects and any data they send. An easy tool for this is [webhook.site](https://webhook.site), which creates unique URLs we can use for this. To use it:
1. Go to [webhook.site](https://webhook.site).
2. Upon visiting the site, a unique URL is generated for you. This is your endpoint URL.
3. In your exploit, use your endpoint URL where you want the exploit to send data
4. Make request to your URL. The webhook page will automatically refresh with all the details of incoming HTTP requests.
### Listening on a port (with `netcat`)
To receive web requests or other connections, we can use a program called `netcat` to "listen" for connections on a particular port and print out the result. This allows us to read the content (headers, body, URL) of a web request and see the results. To do this:
1. Open a terminal in your **development container** (ie, with `run-container`)
2. When you start the container, you should see some lines printed about networking info, like this:
![](https://hackmd.io/_uploads/r1prl9Gyn.png)
This information gives the name and IP address of this container, which we'll need to connect later.
:::warning
#### How to get the dev container's IP
**Warning**: We're observing a known bug where the dev container's internal IP doesn't show up for all users like in this picture. If you don't see this info an need it later, you can run:
```
cs1660-user@661ad4fcfe8e:~$ hostname --ip-address
```
from the dev container to print its IP address. The container's internal hostname is always `cs1660-dev`--this should always work too.
:::
3. In your terminal, run the following:
```
cs1660-user@661ad4fcfe8e:~$ nc -l -p 7169
```
This tells the netcat (`nc`) command to listen for connections on port 7169.[^2] **After running the command, your terminal will hang--this is okay**, it means that netcat is waiting for something to connect to it!
[^2]: While we can technically pick any port number 1025--65536 here, we choose 7169 because it's pre-configured with a forwarding rule so we can access it outside the container. This isn't relevant unless we want to connect to this port from our host system.
4. Your dev container is now set up to listen for connections! To have a browser or script connect to this port, you would use a URL of the form `http://SERVER-ADDRESS:7169`. Due to come quirks with how containers interact with the network, the value for `SERVER-ADDRESS` depends on how you're connecting to it:
- If you want to receive a connection from **another container** (ie, Bob, the flag webserver, your dev container), use the value for "`This container's internal hostname`" or "`This container's internal IP`" from the network info you printed in Step 2. (For example, `http://cs1660-dev:7169/`)
- If you want to receive a connection from **your host system** (ie, your own browser) use **`localhost`**, ie `http://localhost:7169`. If this doesn't work, something may have gone wrong with the container's port forwarding--see [this section](#How-to-check-if-a-container-port-is-forwarded-to-the-host) for how to debug it.
Once something has connected to your port, you should see `netcat` print some output like this:
```
GET / HTTP/1.1
Host: localhost:7169
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Sec-GPC: 1
```
This example shows a browser attempting to fetch `http://localhost:7169/` with `GET /`, as well as any headers sent during the request.
**To close netcat, or try again**, press `Ctrl+C`. This will drop you back to a shell so you can try again!
### Simple webserver: Hosting arbitrary files
You may find it useful to host a file at a URL so you can use it in an exploit. That is, you want to redirect an attacker to `http://your-site.com/do-some-thing`, you need to control `your-site.com`. To do this within the container environment on our systems, we don't need a `.com` domain, we just need another place to run a webserver!
We've packaged a tiny container that will run a webserver for you (called the [simple webserver](https://github.com/brown-csci1660/simple-webserver)) for this purpose. The next sections will show you how to set it up and use it.
:::info
**Note**: This webserver only hosts files--it does not run PHP or any other server-side code, which should not be necessary for the project. If you want to try out stuff with PHP, try out the [web demo code](https://github.com/brown-csci1660/web-lecture-demos) from lecture.
:::
#### Setting up the simple webserver
To set up the simple webserver container image:
1. Clone the simple webserver repository to your host system. For easy editing, we recommend storing it in the same place as your flag project stencil repo--see [here](#Recommended-filesystem-layout-and-cloning-the-stencil-repo) for details. You can clone the repo as follows (in whatever terminal you use for git):
```
$ git clone https://github.com/brown-csci1660/simple-webserver.git
```
2. If you have not done so already, open a new terminal on your **host system** (or a WSL terminal on Windows) and `cd` to the `simple-webserver` directory
3. Run `./run-container setup` to build the image for this container
:::info
**Windows users**: If you receive errors about newlines, you may need to run `dos2unix` again--see [this section](https://hackmd.io/@cs1660/container-setup#Windows-line-endings-%E2%80%9Cunexpected-end-of-file%E2%80%9D) for details.
:::
4. Start the container with `./run-container`. You should see the same sort of webserver startup info you've seen for the flag webserver container, like the image below. As it starts, take note of the "container network info" section (highlighted in red below), which you'll need later.
![](https://hackmd.io/_uploads/H1G4Ksfy2.png)
:::success
**What to expect**: Just like the flag webserver container, **this container does not run a shell**--instead, it shows a log of all requests to the webserver. To stop it, just press `Ctrl+C`.
:::
5. Your webserver is now running! See the next section for instructions on how to connect to it.
#### Connecting to the simple webserver
Due to come quirks with how containers interact with the network, the URL you'll use to connect to the webserver will differ depending on what system will be connecting:
- If you want **another container** (ie, Bob, the flag webserver, your dev container) to connect, use the value for "`This container's internal hostname`" or "`This container's internal IP`" from the network info you printed in Step 2. (For example, `http://simple-webserver/index.html`)
- If you want to connect from **the browser on your host system** use **http://localhost:9090**. If this doesn't work, something may have gone wrong with the container's port forwarding--see [this section](#How-to-check-if-a-container-port-is-forwarded-to-the-host) for how to debug it.
If you're able to connect successfully, you should be able to view any page in the `webroot` directory of the webserver.
Here's an example when connecting from the browser on a host system:
![](https://hackmd.io/_uploads/r1T1qizkn.png)
...and from another container (in this case, from the development container, using `curl`):
![](https://hackmd.io/_uploads/r1cr9oMkn.png)
#### How to host files?
The server hosts all files in the `webroot` directory of the repository--placing a file here makes it available at the server's address, relative to the `webroot` directory. For example, if you create `webroot/exploit.php`, it will be available at `http://<server address>/exploit.php`.
If you have questions or run into issues with this, please ask us or post on Ed!
### PHP reverse shell
A "reverse shell" is mechanism for obtaining a shell on a remote system, but instead of connecting to the system with SSH or telnet, the remote system connects to you!
A reverse shell is often used in exploits once you've found a way to execute arbitrary code on the system. Usually, whatever method you find to execute arbitrary code is pretty clunky to use, so it's easiest to use this to start a reverse shell so you can poke around just like you'd use any other terminal.
The security community has found many ways to build a reverse shell using different types of server-side code execution capabilities. If you find a way to execute arbitrary PHP code in this project, we recommend using this reverse shell, which is a PHP script: https://github.com/pentestmonkey/php-reverse-shell
For details on how to use it, see the PHP file in this repository. To use it with this project, you will need to listen on a port for the shell to connect to you--see [Listening on a port](#Listening-on-a-port-with-netcat) for instructions how to do this. (We'll also demo this in class soon.)
## FAQs/Common issues
### Windows line endings ("unexpected end of file")
If you see errors along the lines of `bash: '\r': command not found` or `bash: /home/cs1660-user/.bash_profile: line 5: syntax error: unexpected end of file`, see [this section](https://hackmd.io/VvXjihLeQne4q84wq1SgWg?view#Windows-line-endings-%E2%80%9Cunexpected-end-of-file%E2%80%9D) for common fixes.
### How to check if a container port is forwarded to the host
By default, containers live in a separate network inside your system--they can't access your host machine without extra setup called *port fowarding*. Our container scripts use port forwarding to allow you to connect to the container from your host system. For example, the flag webserver container forwards port 8888 on your system to the container, which allows you to access the flag portal at http://localhost:8888.
If you're having issues accessing any forwarded ports, you can check if Docker setup the port forwarding rules correctly. On Windows or Mac, you can do this from Docker's desktop interface, as follows:
1. Start your containers as normal
2. Open Docker desktop and to go the **Containers** view (top item in the sidebar on the left, usually the default view), which should look like this:
![](https://hackmd.io/_uploads/BJLOKtfk3.png)
3. Find the container you want to check in the list and look at the **"Ports"** column--you should see an entry for the port you want to use.
The figure above shows what the entry should look like for the flag portal webserver (highlighted in red): here, port 8888 on the local system (`localhost:8888`) is forwarded to port 80 on the container, which is the container webserver's default port.
If you don't see an entry for a port that you expect to be forwarded, try the following:
1. Try restarting the container with `./run-container --clean`
2. If this doesn't help, make sure the `netstat` command is installed on your host system (or in WSL, if you're on Windows). If your WSL is missing `netstat`, install it with `sudo apt-get install netstat` and then try starting the container again with `--clean`.
3. If neither of these methods help, please post on Ed or ask us during office hours!