This lab will introduce you to browser-based attacks, as well as to how one might go about preventing them. The lab has several parts:
For this lab, you will be crafting attacks in your web browser that exploit vulnerabilities in the zoobar web application. To ensure that your exploits work on our machines when we grade your lab, we need to agree on the URL that refers to the zoobar web site. For the purposes of this lab, your zoobar web site must be running on http://localhost:8080/. If you have been using your VM's IP address, such as http://192.168.177.128:8080/, it will not work in this lab.
If you are using KVM or VirtualBox, the instructions we provided in lab 1 already ensure that port 8080 on localhost is forwarded to port 8080 in the virtual machine. If you are using VMware, we will use ssh's port forwarding feature to expose your VM's port 8080 as http://localhost:8080/. First find your VM IP address. To do so, log in as root on the console, run ip addr show dev eth0, and note the IP address listed beside inet. (This is the same IP address you have been using for past labs.) Then configure SSH port forwarding as follows (which depends on your SSH client):
For Mac and Linux users: open a terminal on your machine (not in your VM) and run
$ ssh -L localhost:8080:localhost:8080 student@VM-IP-ADDRESS
For Windows users, this should be an option in your SSH client. In PuTTY, follow these instructions. Use 8080 for the source port and localhost:8080 for the remote port.
The forward will remain in effect as long as the SSH connection is open.
In this lab, we recommend that you use the current version of the Google Chrome browser for developing your attacks. There are subtle (and not-so-subtle) differences in the way HTML, JavaScript, and cookies are handled by different browsers, and some attacks that work in Internet Explorer (for example) may not work in Chrome, and vice-versa. The grading script will use a headless version of Chrome, called Puppeteer, to check your solutions.
If you have an ad-blocking extension in your web browser, such as uBlock, you may want to disable it to avoid interfering with the attacks you will be developing in this lab.
Before you begin working on these exercises, please use Git to commit your Lab 3 solutions, fetch the latest version of the course repository, and then create a local branch called lab4 based on our lab4 branch, origin/lab4. Do not merge your lab 2 and 3 solutions into lab 4. Here are the shell commands:
student@6566-v24:~$ cd lab student@6566-v24:~/lab$ git commit -am 'my solution to lab3' [lab3 c54dd4d] my solution to lab3 1 files changed, 1 insertions(+), 0 deletions(-) student@6566-v24:~/lab$ git pull Already up-to-date. student@6566-v24:~/lab$ git checkout -b lab4 origin/lab4 Branch lab4 set up to track remote branch lab4 from origin. Switched to a new branch 'lab4' student@6566-v24:~/lab$ make ...
Note that lab 4's source code is based on the initial web server from lab 1. It does not include privilege separation or Python profiles.
Now you can start the zookws web server, as follows.
student@6566-v24:~/lab$ ./zookd 8080
Open your browser and go to the URL http://localhost:8080/
.
You should see the zoobar web application. If you don't, go back
and double-check your steps. If you cannot get the web server to work,
get in touch with course staff before proceeding further.
You will craft a series of attacks against the zoobar web site you have been working on in previous labs. These attacks exploit vulnerabilities in the web application's design and implementation. Each attack presents a distinct scenario with unique goals and constraints, although in some cases you may be able to re-use parts of your code.
We will run your attacks after wiping clean the database of registered users (except the user named "attacker"), so do not assume the presence of any other users in your submitted attacks.
You can run our tests with make check-lab4; this will execute your attacks against the server, and tell you whether your exploits are working correctly. As in previous labs, keep in mind that the checks performed by make check are not exhaustive, especially with respect to race conditions. You may wish to run the tests multiple times to convince yourself that your exploits are robust.
Some exercises require that the displayed site look a certain way. When make check-lab4 runs, it generates reference images for what the attack page is supposed to look like (answer-XX.ref.png) and what your attack page actually shows (answer-XX.png), and places them in the lab4-tests/ directory. To view these images from lab4-tests/, either copy them to your local machine, or run python3 -m http.server 8080 and view the images by visiting http://localhost:8080/lab4-tests/. Note that Python's http.server caches responses, so you should kill and restart it after a make check-lab4 run.
The zoobar users page has a flaw that allows theft of a logged-in user's cookie from the user's browser, if an attacker can trick the user into clicking a specially-crafted URL constructed by the attacker. Your job is to construct such a URL. An attacker might e-mail the URL to the victim user, hoping the victim will click on it. A real attacker could use a stolen cookie to impersonate the victim.
You will develop the attack in several steps. To learn the necessary infrastructure for constructing the attacks, you first do a few exercises that familiarize yourself with Javascript, the DOM, etc.
Cookies are HTTP's main mechanism for tracking users across requests. If an attacker can get ahold of another user's cookie, they can completely impersonate that other user. For this exercise, your goal is simply to print the cookie of the currently logged-in user when they access the "Users" page.
zoobar/templates/users.html
(you'll need to
restore this original version later). Add a <script>
tag to users.html
that prints the logged-in user's cookie
using alert()
.
Your script might not work immediately if you made a Javascript programming error. Fortunately, Chrome has fantastic debugging tools accessible in the Inspector: the JavaScript console, the DOM inspector, and the Network monitor. The JavaScript console lets you see which exceptions are being thrown and why. The DOM Inspector lets you peek at the structure of the page and the properties and methods of each node it contains. The Network monitor allows you to inspect the requests going between your browser and the website. By clicking on one of the requests, you can see what cookie your browser is sending, and compare it to what your script prints.
answer-1.js
. Your file should only contain javascript
(don't include <script>
tags).
Modify your script so that it records the user's cookie to the attacker using the logging script. The attack should still be triggered when the user visits the "Users" page.
Please review the instructions at https://css.csail.mit.edu/6.566/2024/labs/log.php
and use that URL in your scripts to record the stolen cookie. You may log as many times
as you like while working on the project, but please do not attack or abuse the
logging script. Note that the cookie has characters that likely need to be URL
encoded. Take a look at
encodeURIComponent
and
decodeURIComponent
.
When you have a working script, put it in a file named
answer-2.js
. Again, your file should only contain javascript
(don't include <script>
tags).
For this exercise, your goal is to craft a URL that, when accessed, will cause the victim's browser to execute some JavaScript you as the attacker has supplied. In particular, for this exercise, we want you to create a URL that contains a piece of code in one of the query parameters, which, due to a bug in zoobar, the "Users" page sends back to the browser. The code will then be executed as JavaScript on the browser. This is known as "Reflected Cross-site Scripting", and it is a very common vulnerability on the Web today.
For this exercise, the JavaScript you inject should call alert()
to display the victim's cookies. In subsequent exercises, you will make the
attack do more nefarious things. Before you begin, you should restore the
original version of zoobar/templates/users.html
.
For this exercise, we place some restrictions on how you may develop your exploit. In particular:
./zookld
). Once it works, put your attack URL in a
file named answer-3.txt
. Your URL should be the only thing on the
first line of the file.
Hint: You will need to find a cross-site scripting vulnerability on /zoobar/index.cgi/users, and then use it to inject Javascript code into the browser. What input parameters from the HTTP request does the resulting /zoobar/index.cgi/users page display? Which of them are not properly escaped?
Hint:
Is this input parameter echo-ed (reflected) verbatim back to victim's browser?
What could you put in the input parameter that will cause the victim's browser
to execute the reflected input? Remember that the HTTP server performs URL
decoding on your request before passing it on to zoobar; make sure that your
attack code is URL-encoded (e.g. use +
instead of space, and
%2b
instead of +
). This
URL encoding reference and this
conversion tool may come in handy.
Hint:
The browser may cache the results of loading your URL, so you want to make sure
that the URL is always different while your developing the URL. You may want to
put a random argument into your url: &random=<some random
number>
.
Modify the URL so that it doesn't print the cookies but logs them for the attacker.
Put your attack URL in a file named answer-4.txt
.
Hint: Incorporate your logging script from exercise 2 into the URL.
With the exploits you have developed thus far, the victim is likely to notice that you stole their cookies, or at least, that something weird is happening. For example, the Users page probably also printed an error message (e.g., "Cannot find that user").
For this exercise, you need to modify your URL to hide your tracks. Except for the browser address bar (which can be different), the grader should see a page that looks exactly the same as when the grader visits http://localhost:8080/zoobar/index.cgi/users. No changes to the site appearance or extraneous text should be visible. Avoiding the red warning text is an important part of this attack (it is ok if the page looks weird briefly before correcting itself). Your script should still send the user's cookie to the logging script.
When you are done, put your attack URL in a file named
answer-5.txt
.
Hint:
You will probably want to use CSS to make your attacks invisible to the user.
Familiarize yourself with
basic expressions
like <style>.warning{display:none}</style>
, and feel
free to use stealthy attributes like
display: none;
visibility: hidden;
height: 0; width: 0;
, and
position: absolute;
in the HTML of your attacks. Beware that frames and images may behave strangely
with display: none
, so you might want to use visibility:
hidden
instead.
This completes part 1 of this lab.
Submit your answers to the first part of this lab assignment by running make handin.zip and upload the resulting handin.zip file to the submission web site.
In this part, you will construct an attack that will steal the victim's username and password if they are not logged in using a fake login form. The attack scenario is that we manage to get the user to visit some malicious web page that we control.
Copy the zoobar login form (either by viewing the page source, or using
zoobar/templates/login.html) into answer-6.html
, and make
it work with the existing zoobar site. Much of this will involve prefixing URLs
with the address of the web server. This file will be used as a stepping stone
to the rest of the exercises in this part, so make sure you can correctly log
in to the website using your fake form. Note that you should make
no changes to the zoobar code. Submit your HTML in a file
named answer-6.html
.
In order to steal the victim's credentials, we have to look at the form values
just as the user is submitting the form. This is most easily done by attaching
an event listener (using addEventListener()
) or by setting the
onsubmit attribtue of a form. For this exercise, use one of these
methods to alert the user's password when the form is submitted. Submit your
code in a file named answer-7.html
.
Modify answer-7.html
to log the username and password (separated by a slash) to you using the logging
script when the user submits the login form. Submit your code in a file named
answer-8.html
.
Please note that after implementing this exercise, the attacker controller webpage will no longer redirect the user to be logged in correctly. You will be fixing this issue in the next exercise.
Hint:
When a form is submitted, outstanding requests are cancelled as the browser
navigates to the new page. This might lead to your request to log.php not
getting through. To work around this, consider cancelling the submission of the
form using the preventDefault()
method on the event object passed
to the submit handler, and then use setTimeout() to submit the form
again slightly later. Remember that your submit handler might be invoked again!
Modify answer-8.html
to hide your tracks: arrange that after
stealing the victim's username and password that the user sees the official site. Submit
your code in a file named answer-9.html
.
Hint: The zoobar application checks how the form was submitted (that is, whether "Log in" or "Register" was clicked) by looking at whether the request parameters contain submit_login or submit_registration. Keep this in mind when you forward the login attempt to the real login page.
Create an attack that will steal the victim's password, even if
the victim is diligent about entering their password only when the URL address
bar shows http://localhost:8080/zoobar/index.cgi/login.
Your solution should be contained in a short HTML document named
answer-chal.html
.
When grading, the grader will open the page using the web browser (while not logged in to zoobar). Upon loading your document, they should immediately be redirected to http://localhost:8080/zoobar/index.cgi/login. The grader will then enter a username and password, and press the "Log in" button.
Your mission, should you choose to accept it, is to make it so that when the "Log in" button is pressed, the password are logged for the attacker using the logging script. The login form should appear perfectly normal to the user; this means no extraneous text (e.g., warnings) should be visible, and as long as the username and password are correct, the login should proceed the same way it always does.
Hint:
For this final attack, you may find that using alert()
to test for
script injection does not work; Chrome blocks it when it's causing an infinite
loop of dialog boxes. Try other ways to probe whether your code is running,
such as document.loginform.login_username.value=42
.
Your profile worm should be submitted in a file named
answer-10.txt
. To grade your attack, we will cut and paste the
submitted profile code into the profile of the "attacker" user, and view that
profile using the grader's account. We will then view the grader's profile with
more accounts, checking for both the zoobar transfer and the replication of
profile code.
In particular, we require your worm to meet the following criteria:
To get you started, here is a rough outline of how to go about building your worm:
Note: You will not be graded on the corner case where the user viewing the profile has no zoobars to send.
Hint:
In this exercise, as opposed to the previous ones, your exploit runs on the
same domain as the target site. This means that you are not subject to
Same-Origin Policy restrictions, and that you can issue AJAX requests directly
using XMLHttpRequest
instead of iframe
s.
Hint:
For this exercise, you may need to create new elements on the page, and access
data inside of them. You may find the DOM methods
document.createElement
and
document.body.appendChild
useful for this purpose.
Hint:
If you choose to use iframe
s in your solution, you may want to get
access to form fields inside an iframe
. Exactly how you do so
differs by browser, but such access is always restructed by the same-origin
policy. In Chrome, you can use
iframe.contentDocument.forms[0].some_field_name.value = 1;
.
Make sure you have the following files:
answer-1.js
,
answer-2.js
,
answer-3.txt
,
answer-5.txt
,
answer-6.html
,
answer-7.html
,
answer-8.html
,
answer-9.html
,
answer-10.txt
, and if you are doing the challenge,
answer-chal.html
,
containing each of your attacks.
Feel free to include any comments about your solutions in the
answers.txt
file (we would appreciate any feedback you may have on
this assignment).
Run make handin.zip and upload handin.zip to the submission web site, and you're done!