Project 3: Web Security


Deadline: Thursday, November 7 by 11:59PM.

Before you start, review the course syllabus for the Lateness, Collaboration, and Ethical Use policies.

You may optionally work alone, or in teams of at most two and submit one project per team. If you have difficulties forming a team, post on Piazza’s Search for Teammates forum. Note that the final exam will cover project material, so you and your partner should collaborate on each part.

The code and other answers your group submits must be entirely your own work, and you are bound by the University’s Student Code. You may consult with other students about the conceptualization of the project and the meaning of the questions, but you may not look at any part of someone else’s solution or collaborate with anyone outside your group. You may consult published references, provided that you appropriately cite them (e.g., in your code comments). Don't risk your grade and degree by cheating!

Complete your work in the CS 4440 VM—we will use this same environment for grading. You may not use any external dependencies. Use only default Python 3 libraries and/or modules we provide you.


Helpful Resources

Introduction

In this project, we provide an insecure website, and your job is to attack it by exploiting common classes of vulnerabilities: SQL Injection, Cross-Site Request Forgery (CSRF), and Cross-Site Scripting (XSS). You are also asked to exploit these problems with various flawed defenses in place. Understanding how these attacks work will help you better defend your own web applications.

Objectives


Start by reading this!

Before you begin, please carefully read through the following sections for important setup information and guidelines about this project.

Firefox Web Browser

In this project, you will test and perform your attacks using the Firefox browser provided in your CS 4440 VM. We will use this same browser for grading. For your attacks to work correctly, we have disabled several important security features in your VM's version of Firefox. It is critical that you do NOT update or reinstall your Firefox browser! If you ever encounter the following prompt:

... be sure to click Not Now. Again, do NOT update your VM's Firefox version! If you ever mistakenly update it, you will need to re-download a fresh copy of the CS 4440 VM image.

Target Website

Throughout this project, you will be attacking the following ficticious search engine website named BUNGLE, which we make available via the following URL: http://cs4440.eng.utah.edu/project3.

To help you construct your attacks, we provide documentation of the BUNGLE website's features and security defenses on the CS 4440 Wiki here: BUNGLE Site Documentation.


Part 1: SQL Injection

Your first goal is to demonstrate SQL injection attacks that log you in as an arbitrary user without knowing the password. In order to protect other students’ accounts, we’ve made a series of separate login forms for you to attack that aren’t part of the main BUNGLE site. For each of the following defenses, provide inputs to the target login form that successfully log you in as user victim.

If your attack works, the server will provide you with a message resembling the following:

To gain credit, paste only the server-printed line (beginning with username=...) into your solution file (sql#.txt) for each target. If you do not see such a message, your solution is incorrect! Your attack code must log-in with the exact username named victim (i.e., the username parameter will not permit injecting SQL command syntax).

SQL0: Deserted Defenses (10pts)

This target, located at /project3/sqlinject0/, uses no defenses against SQL injection. Attack it!

Your task: Submit a text file named sql0.txt containing only the string issued by the server upon successfully logging-in the user into the victim account. Remember to only paste the server-issued string (and not your direct attack string), as shown in the "Login successful" example above!

SQL1: Embarrassing Escaping (10pts)

This target, located at /project3/sqlinject1/, escapes single quotes in the inputs by replacing them with two single quotes (i.e., every ' in your input becomes a '').

Hint #1: SQL by default parses any special command characters it sees (e.g., '). However, you can escape them yourself by prepending them with a backslash (e.g., \' for the single quote).
Hint #2: If latter part(s) of the query are blocking you, what is the SQL way of "cutting" them out?

Your task: Submit a text file named sql1.txt containing only the string issued by the server upon successfully logging-in the user into the victim account.

SQL2: Haphazard Hashing (10pts)

This target, located at /project3/sqlinject2/, uses the following PHP code to escape usernames, and perform password hashing via the MD5 hash function:

if (isset($_POST['username']) and isset($_POST['password'])) {
    $username = mysql_real_escape_string($_POST[’username’]);
    $password = md5($_POST['password'], true);
    
    $sql_s = "SELECT * FROM users WHERE username='$username' and pw='$password'";
    $rs = mysql_query($sql_s);
    
    if (mysql_num_rows($rs) > 0) {
        echo "Login successful!";
    } else {
        echo "Incorrect username or password";
    }
}

This target is harder than the previous two, and requires a program to solve it (which you will write in Python 3). In constructing your attack, you may only use the PyMD5 module from Project 1, provided here: cs4440.eng.utah.edu/files/project1/pymd5.py. For a refresher on using it, refer to its Wiki page.

Hint: It will help you to first understand how the hashed password is used in the above server-side SQL query. What might happen if an input's resulting hash digest contains valid SQL fragments?

Your task: Submit a text file named sql2.txt containing only the string issued by the server upon successfully logging-in the user into the victim account. Submit your Python 3 code as sql2.py.

Extra Credit: Remarkable Reconaissance (10pts)

This target, located at /project3/sqlinject3/, uses a different database. Use SQL injection to retrieve:

  1. The name of the database.
  2. The version string of the SQL server.
  3. All of the names of the tables in the database.
  4. A secret (and fun) one-word string hidden in the database. If you think you've found it but aren't sure, we recommend doing some searching to familiarize yourself with password-hacking trivia!

Your task: For this part, sql3.txt should start with a list of the SQL queries you made to learn the answers (one per line), followed by the answers to the above questions. Format your file as follows:

YOUR 1st QUERY
YOUR 2nd QUERY
YOUR Nth QUERY

Name: NameOfDatabase
Version: VersionStringOfDatabase
Tables: CommaSeparatedNames
Secret: SecretString

What to Submit:

For SQL 0–2, when you successfully log in as victim, the server will provide a URL-encoded version of your SQL injection input. Submit a text file with the specified filename (sql#.txt) containing only the server-provided string. For SQL2, additionally submit the source code for your Python 3 program (sol2.py). For extra credit SQL3, submit only a text file as specified.

Part 2: Beginner Cross-site Forgery and Scripting

Your next task is to exploit BUNGLE’s weak Cross-site Request Forgery (CSRF) and Cross-site Scripting (XSS) protections. For each of the scenarios below, construct a single HTML file that, when opened by a victim user in their web browser, executes the specified attack.

To help get you started, we provide a skeleton template (bsf.html) for you to implement your attacks in:

<html>
    <body>
        <!-- Stealthy IFrame (leave as-is) -->
        <iframe name="BlankPage" style="visibility:hidden;"></iframe>

        <!-- Update any "..." fields accordingly! -->
        <form action="http://cs4440.eng.utah.edu/project3/...?"
              target="BlankPage"
              name="EvilPayload"
              method="...">

            <input name="csrfdefense" value="..." type="hidden">
            <input name="xssdefense" value="..." type="hidden">
            <input name="username" value="attacker" type="hidden"/>
            <input name="password" value="l33th4x" type="hidden"/>

            <!----------------------------
            | Your attack code goes here! 
            ----------------------------->
        </form>

        <!-- Launch the attack! (leave as-is) -->
        <script>
            document.EvilPayload.submit();
        </script>

        <!-- Stealty redirect (leave as-is) -->
        <meta http-equiv="refresh" content="1; URL=http://cs4440.eng.utah.edu/project3"/>
    </body>
</html>

For all attacks in this part, you may leave username and password set to attacker and l33th4x. However, be sure to update the csrfdefense and xssdefense values (and all others) accordingly!

BSF0: Lackluster Login (10pts)

When csrfdefense=0 and xssdefense=4, the site has no CSRF defenses. Attack its login form!

Hint: You must set up the appropriate parameters for the login form in the skeleton code. Review BUNGLE's Docs to understand what method is needed for login requests (e.g., GET vs. POST).

Your task: For the defense levels specified above, create an HTML file (bsf0.html) that, when opened, logs the victim into BUNGLE account attacker with password l33th4x. Your code should not display evidence of an attack; the browser should just display a blank page and redirect to BUNGLE.

If the victim later visits BUNGLE, it will say "logged in as attacker", but that is fine for purposes of the project. You can assume that most unknowing victims won’t immediately notice this side-effect.

BSF1: Token Thievery (10pts)

When csrfdefense=1 and xssdefense=0, the server sets a token named csrf_token to a random 16-byte value (e.g., eb21615d80912e20bed003941f65de72), and also includes this value as a hidden field in the login form. On form submission, the server verifies that the client’s token matches the value in the form. However, it does not properly filter search terms before echoing them to the results page.

Hint #1: You should first manually identify the csrf_token value in the site cookie: launch Firefox, navigate to the Developer Tools, click the Storage tab, and find it under the Cookies drop-down. Then, start building your approach to retrieve this token programmatically!
Hint #2: In BSF0, you set up a simple form submission to the site's login interface. Is there another interface where you can inject code that will be unknowingly executed by the victim's browser?

Your task: For the defense levels specified above, create an HTML file (bsf1.html) that, when opened, just calls JavaScript's alert() function to print only the csrf_token value (but not the entire site cookie). You do not need to log the user in. We recommend reviewing the Wiki's JavaScript Cheat Sheet for documentation on how to JavaScript's alert() function.

BSF2: Suspicious Spying (10pts)

In this part, you will strengthen the attack by having it exfiltrate the victim’s token back to the attacker. For our needs, the attacker and victim are "sitting" at the same machine, hence we will have the attack report the token to a virtual server listening at localhost (i.e., IP address127.0.0.1) over HTTPS via port 31337.

In order to capture incoming traffic at port 31337, we provide a script named spyserver.py: http://cs4440.eng.utah.edu/files/project3/spyserver.tar.gz.

After downloading and extracting it, you can run the server as follows: $ python3 spyserver.py.

To test that your server works, leave the script running and connect to https://localhost:31337 in Firefox. If prompted, accept the certificate prompt (click Accept the Risk and Continue).

In the terminal where you left the spy server running, you should now see some basic data printed, such as: 127.0.0.1 - - [16/Jan/2023 22:00:13] "GET / HTTP/1.1" 200 - .

Hint: For sending information to the spy server, you may find JavaScript's request APIs helpful. Like BUNGLE's login and search interfaces, the spy server also requires a specific request type!

Your task: For the same defenses as BSF1, construct an HTML file (bsf2.html) that, when opened, sends the csrf_token (possibly among other things—but not the entire site cookie) to an attacker listening on port 31337. We'll use the same spy server in grading. You do not need to log the user in.

BSF3: Token Turmoil (10pts)

While you've so far exploited BUNGLE’s search page to steal CSRF tokens, we now wish to exploit these weak protections to perform an attack on its login page.

Your task: For the same defense levels as BSF1, construct a single HTML file (bsf3.html) that, when opened, hijacks the victim's token and proceeds to log-in as user attacker with password l33th4x (achieving the same effect as in BSF0 above).

What to Submit:

For each target, submit an HTML file (bsf#.html) that performs the specified attack. You may embed inline JavaScript and load jQuery 2.1.4. Otherwise, your code must be self contained (i.e., no outside dependencies). Test your solutions by opening them in your VM's Firefox browser.

Part 3: Advanced Cross-site Scripting

In Part 2, you demonstrated attacks against a "fake" user (attacker) in the form of HTML files. Now, you will perform realistic, stealthy attacks—in the form of URLs—against real users.

Your attack payload (i.e., the code your attacks execute) will be to steal the currently-logged-in user’s (1) username and (2) first search query they entered on BUNGLE. When a victim visits your attack URL, these stolen items should be sent to the attacker’s spy server (i.e., like in BSF2). To get credit, your attack must transmit the current user’s stolen username and first_search to the attacker’s spy server by loading URL: https://localhost:31337/?username=...&first_search=....

Be sure to update the xssdefense parameter value accordingly!


XSS0: History Hijacking (10pts)

Defense xssdefense=0 implements no XSS defenses—so go attack it! Recall that BUNGLE does not properly filter search terms before echoing them to the results page.

Hint: To figure out when to access certain DOM tree elements, review JavaScript's event handlers.

Your task: For the above XSS defense level, submit an attack URL in xss0.txt that, when accessed, sends the user’s username and first search to our spy server. Test your attacks by creating your own account and populating its search history. We recommend that you first test a simple payload (e.g., alert(0);) as an HTML file (like your Part 2 attacks) before moving on to building the full payload and URL. It may be helpful to write a short program to encode script characters in URL-friendly form.

XSS1: Subverting Script Skipping (10pts)

Defense xssdefense=1 removes <script> tags in JavaScript via the following server-side code:

filtered = re.sub(r"(?i)script", "", input)

Your task: For the above XSS defense level, submit an attack URL in xss1.txt that, when accessed, sends the user’s username and first search to our spy server. For this and all remaining attacks, you may reuse your crafted payload from XSS0 with different encodings to bypass the various defenses.

XSS2: Tricking Tag Take-downs (10pts)

Defense xssdefense=2 removes several additional types of tags via the following server-side code:

filtered = re.sub(r"(?i)script|<img|<body|<style|<meta|<embed|<object", "", input)

Your task: For the above XSS defense level, submit an attack URL in xss2.txt that, when accessed, sends the user’s username and first search to our spy server.

Extra Credit: Playing Punctuation Purging (5pts)

Defense xssdefense=3 removes several forms of punctuation via the following server-side code:

filtered = re.sub(r"[;’\"]", "", input)

Your task: For the above XSS defense level, submit an attack URL in xss3.txt that, when accessed, sends the user’s username and first search to our spy server.

Extra Credit: Escaping Embellished Encoding (5pts)

Defense xssdefense=4 encodes symbols < and > via the following server-side code:

filtered = input.replace("<", "&lt;").replace(">", "&gt;")

Your task: For the above XSS defense level, submit an attack URL in xss4.txt that, when accessed, sends the user’s username and first search to our spy server.

What to Submit:

For each target, submit a text file (xss#.txt) that contains a single line consisting of the URL that performs the specified attack when loaded into the victim's browser. You may embed inline JavaScript and load jQuery 2.1.4. Otherwise, your code must be self contained (i.e., no outside dependencies). Test your solutions by opening them in your VM's Firefox browser.

Submission Instructions

Upload to Canvas a tarball (.tar.gz) named project3.uid1.uid2.tar.gz, replacing your team's UIDs accordingly (if working alone, provide only your UID once). Each UID must be in u####### format. Your tarball must contain only the files listed below. These will be autograded, so make sure that your solutions conform to the expected filenames, formatting, and behaviors.

Failure to follow assignment instructions (e.g., submitting a corrupted tarball; wrong, missing, or broken code; improper formatting; etc.) will be ineligible for regrades. External dependencies are prohibited. You may use only default Python 3 libraries and/or modules we provide you. Your solutions must work as-is in the CS 4440 VM. Make sure to thoroughly test your code before submitting!

Generate the tarball in your VM terminal using this command (be sure to first cd to the directory that contains your files):

tar -zcf project3.uid1.uid2.tar.gz sql[0123].txt sql2.py bsf[0123].html xss[01234].txt