# Homework/Project 3
**Student information:** Owen Sullivan (opsulli | C34243277)

## Introduction
For this assignment, I worked alone and thus did not divide up any of the work.

## Methodology

### SQL Injection Part 1
For part 1.1 (`sql_0.txt`), I found a simple SQL injection string `' OR ''='` that allowed me to login as the user `victim` at [http://cpsc4200.mpese.com/sqlinject/0](http://cpsc4200.mpese.com/sqlinject/0). This results in the following SQL command evaluated by the server: `SELECT * FROM users WHERE username='victim' AND password='' OR ''=''`. I later found that the spaces could be excluded, but it didn't seem necessary to change my answer.

### SQL Injection Part 2
For part 1.2 (`sql_1.txt`), I found the following SQL injection string: ` \' OR ""=""-- `. Since the server escapes single quotes into two single quotes, it's necessary to provide an explicit escape character for the first single quote so that the server does not escape it properly. Double quotes have to be used for the `OR` comparison, as well. This results in the following SQL command evaluated by the server: `SELECT * FROM users WHERE username='victim' AND password='\'' OR ""=""-- '`. The `-- ` sequence is the SQL comment operator, which causes the last single quote in the query to be ignored.

### SQL Injection Part 3
For part 1.3 (`sql_2.txt` and accompanying code in `/sql_2-src`), I had to find a password that, when SHA256-hashed like `sha256("bungle-" + [password])` would produce an SQL injection string of some kind in the digest. I initially thought that the hash digest would need to start with an SQL injection string, but I later discovered that false equivalency could be used like so: `SELECT * FROM users WHERE username='victim' AND password='[random characters]'='[more random characters]'`, which translates to `SELECT * FROM users WHERE username='victim' AND FALSE=[more random characters]` after the `password='[random characters]'` clause is evaluated to `FALSE` after the database is checked. There's a high likelihood that the random characters checked against `FALSE` will evaluate to `FALSE`, since non-ASCII characters are interpreted as such, and if it happens that the random characters are valid ASCII then a different generated password can be used.

Once I knew this, designing a Python script (`bungle_hashgen.py`) that generates hashes and checks for the existence of the `'='` string somewhere in the hash digests was trivial. I used an "alphabet" of the basic ASCII numbers, since the random password input data shouldn't matter and using fewer possible characters allows more possible passwords to be found in a shorter amount of time. When running `bungle_hashgen.py`, a handful of password candidates are generated rather quickly and the script can be exited with `CTRL+C`.

----

### Cross-site Scripting (XSS) Part 1
For part 2.2.1 (`xss_0.txt`, `xss_payload.html`), I developed a payload that uses the JQuery `$(window).on('load', function() {})` handler to extract the username and last search text from the appropriate DOM elements and make a GET request to the listening server with the data.

### Cross-site Scripting (XSS) Part 2
For part 2.2.2, (`xss_1.txt`), I modified my payload for part 2.2.1 to use an HTML `body` tag and its `onload` event to execute the XSS explot.

### Cross-site Scripting (XSS) Part 3
For part 2.2.3 (`xss_2.txt`), I used an HTML `iframe` tag and its `onload` event in place of the `body` tag to execute the same payload as part 2.2.2.

----

### Cross-site Request Forgery (CSRF) Part 1 (Bonus)
For part 3.1 (`csrf_0.html`), I created an HTML `form` element that makes a `POST` request to the `/login` endpoint, passing the username and password of the `attacker` account provided as inputs. The HTML `body` element's `onload` event is once again used, this time to submit the form. This causes the browser to redirect to the main BUNGLE! page, logged in as `attacker`.

The process of finding this solution is part of what led to parts 3.1 and 3.2 of the assignment being made optional, so I think it's worth a bit of explanation for the bonus points: best I can tell, it's no longer possible to use a hidden `iframe` to perform CSRF attacks as modern browsers (including Firefox) give each frame their own cookie storage in order to adhere to the new default `SameSite` policies. I did not find any way to reliably log the client in as `attacker` without a redirect, except for the hidden `iframe` method that was hit or miss across multiple different systems (including the Docker container, where it did not work).

### Cross-site Request Forgery (CSRF) Part 2 (Bonus)
For part 3.2 (`csrf_1.html`), I again created an HTML `form` element, this time one that makes a `GET` request to the `/search` endpoint in order to perform an XSS exploit. The exploit sets a dummy value for the `csrf_token` cookie of `00000000000000000000000000000000`, then programmatically builds a new HTML `form` element with `input` elements to handle the username, password, and `csrf_token`. The XSS exploit ends by submitting the new form, which makes a `POST` to the `/login` endpoint and results in the client being logged in as `attacker`.

This solution faces the same issues as my solution for part 3.1, and I could not get the hidden `iframe` method to work *at all* across *any* platform or the Docker container. While working on part 3.2, I spent many, *many* hours trying every potential solution I could think of (including jQuery AJAX requests, which encounter the same frame cookie storage issue as the hidden `iframe` method), so I'm hoping the fact that this solution reliably logs the client in as `attacker` will suffice for the bonus points.