Welcome to the Database Security project. This hands-on project is designed to help you understand how real-world data breaches can occur and what strategies can be used to protect against them.
Learning Goals
In this project, you’ll explore two significant types of database vulnerabilities and how attackers exploit them:
- Inference Attacks: Learn how sensitive information can be uncovered by analyzing and correlating seemingly harmless data. Data mining often uses this technique to “connect the dots” and extract private details without direct access.
- SQL Injection (SQLi): Understand how attackers inject malicious SQL code through input fields to manipulate databases, access unauthorized data, or execute harmful actions.
Topics Covered
- Basic T-SQL queries
- Basic JavaScript
- Database inference techniques
- SQL injection attacks
Final deliverables
You will submit a single file named project_dbsec.json to Gradescope. A template is available at: /home/dbsec/Desktop/project_dbsec.json
See the Submission Details page for formatting and content guidelines.
Important Reference Material
Valuable Information – Database Security Prerequisites
NOTE: Vital information is provided on the prerequisite page, which is not provided elsewhere!
Submission
- Platform: Gradescope (auto-graded)
- More info: Submission Details
Virtual Machine
Supported
- Intel/AMD x64 architecture
- VirtualBox Version 7.x/latest is required
Not Supported
- Apple M-series (ARM-based) devices are not supported.
- Instructions are provided on how to attempt to get the VM to run on a MAC, but again, this is not supported. Note: You will need to SSH into the VM if you choose to attempt this.
- Extensions will not be granted for related issues.
This project uses Microsoft SQL Server Developer Edition, which runs on Linux inside the provided VM. The DBSec project is in the master VM, and the credentials for the Linux user will be provided on the project release in Canvas.
Getting Started
- Background & Setup – This is a must read!
- FAQ
- Troubleshooting
Table of contents
- FAQ
- Background and Setup
- Task A
- Task B
- Task C
- Task D
- Task E
- Task F
- Task G
- Task H
- Task I
- Submission
- Task J
- Troubleshooting
BACKGROUND AND SETUP:
Project Scenario: Your First Penetration Test
“Good News, Everyone!” 
You’ve just stepped into your new role at a penetration testing firm, and your first mission awaits. A portfolio of client websites has been placed in front of you, each one resembling a digital fortress with hidden doors and potential cracks. It’s your responsibility to probe their defenses and uncover vulnerabilities before anyone else does.
As you begin your review, familiar patterns start to emerge. The layouts, naming conventions, and user interfaces share striking similarities. A deeper look reveals the reason — all of these websites were developed by the same software vendor. This discovery is critical: any weakness found in one site could very likely exist across the entire portfolio, putting multiple clients at risk.
Your objective in this mission is to identify and report those vulnerabilities. You’ll search for sensitive information that was never meant to be exposed, analyze how data is processed and protected, and test the applications against user input designed to bypass their safeguards. In doing so, you’ll step fully into the role of a penetration tester — wearing many hats and sharpening the skills essential to protecting databases and application security.

Setup Instructions
This project focuses on two common yet critical categories of database attacks: inference attacks and SQL injection. You will take on the role of a security analyst, tasked with identifying, exploiting, and reporting these vulnerabilities, all within a controlled environment designed for learning and exploration.
It is highly recommended that you create a snapshot of your VM before even attempting to start the project. Failure to do so may require you to reimport (possibly redownload) the OVA file.
- Creating a Snapshot in VirtualBox
- Select the VM (CS6035-Semester-Year-xxx).
- On the right hand side, select the Snapshots tab.
- You will see an icon above the VM that says Take. Click on this to have the Snapshot creation window appear.
- Name the Snapshot and click OK.
- You will see an icon above the VM that says Take. Click on this to have the Snapshot creation window appear.
- Restoring a Snapshot in VirtualBox
- Select the VM (CS6035-Semester-Year-xxx).
- On the right hand side, select the Snapshots tab.
- Select the Restore Point you want to restore from.
- You will see an icon above the VM that says Restore. Click on this to have the Snapshot restored.
To get started, follow the setup steps carefully. Precision matters here — even a small misstep could cause confusion or errors later in the process.
- Log in to the Virtual Machine
- You will use a pre-configured virtual machine (VM) provided with the project. Log in using the details shared in Canvas’s official Database Security Project release announcements.
Username: Provided on project release in Database Security Project Canvas post
Password: Provided on project release in Database Security Project Canvas post
- Locate the Submission JSON File
- On the desktop of your VM, you will find a file named
project_dbsec.json. This file will serve as your central submission file. - If the file is missing, recreate it using the template and formatting instructions provided in the project’s Submission Details section.
- Edit the file only with a plain text editor, such as Text Editor on the VM (in plain text mode) or Vim. Do not use word processors like LibreOffice or Microsoft Word, as they may introduce special characters that will cause the autograder to fail.
project_dbsec.jsonfile is where you will enter your final hashes and flag values as you complete each task. You will then submit this file to Gradescope for grading.
- On the desktop of your VM, you will find a file named
- Access the project:
- After logging into the virtual machine, you may see a pop-up message prompting you to upgrade the system.
- This is not required for the project. If it appears, minimize the window. While you can click Cancel, This notice will continue to sporadically pop-up which is why minimizing it is recommended.
- To initialize the project environment, Start the container:
- Open the terminal and execute the command:
./StartContainer.sh- Close the Terminal after the message: “Container started, current datetime.”

- The container on the first start-up can take some time, up to FIVE minutes as it is building the environment.
- Subsequent starts of the container will be quicker but can still take time, up to ONE minute as it is starting processes.
- Close the Terminal after the message: “Container started, current datetime.”
- Note: It is highly recommended that you stop the container before restarting or shutting down the VM. To do so open the terminal and execute the command:
./StopContainer.sh- Close the Terminal after the message: “Container sttopped, current datetime.”

- Close the Terminal after the message: “Container sttopped, current datetime.”
- Open the terminal and execute the command:
- Next, open a web browser inside the virtual machine.
- Use either Google Chrome or Firefox.
- In the browser’s address bar, enter the URL:
http://www.gt-cs6035.com/intro.html(You may want to bookmark this for future ease of access) - This will bring you to the main interface where you can begin working on the tasks.
- Chrome Desktop Icon: DbSec – CS6035 > The first time used, you will be prompted with the below popup. Choose Mark Executable.

- If you see the below, it most likely means that the container is still “starting” even though the Terminal output stated “started”

- Once you see the below, it means that the container is ready to be used.

- After logging into the virtual machine, you may see a pop-up message prompting you to upgrade the system.
- Starting the Tasks
- You must begin with Task A. This task validates your GTID and generates a unique identifier required to complete the project. None of the other tasks will work correctly until Task A has been completed and the corresponding hash is submitted. IT IS HIGHLY RECOMMENDED TO USE A SUBMISSION TO VALIDATE FLAG 0!
- After completing Task A, the remaining tasks (Tasks B through I) can be completed in any order. However, for clarity and ease of progress, it is recommended that you follow them alphabetically (with flags completed in numerical order).
- Each task is designed to teach you a new concept or technique in database security. As you progress, you’ll begin to think like a penetration tester, evaluating the strengths and weaknesses of database protections.
DbGate
This is required for Task D and I. Any testing can be done online with SQLFiddle, however if you want a more real world setup for testing, 3 blank databases are provided for you and can be accessed via DbGate.
Setup
DbGate is a cross-platform database tool designed for ease of use while managing multiple databases simultaneously. It offers powerful features like schema comparison, a visual query builder, data charts, and tools for importing and exporting large amounts of data.

Location in the VM
- Click on the Linix Mint Launcher Icon
- Click on the Development Menu
- Click on DbGate
DbGate Connection Procedure
- Under File, choose
Add Connection - In Connection type, choose
Microsoft SQL Server - Enter this information in the General Tab
- Server ->
www.gt-cs6035.com - User ->
CS6035Student - Password ->
CS6035DBSec
- Server ->
- Check
Trust server certificate - Click
Test- If you see Connected next to save then Click
Save
- If you see Connected next to save then Click
- Click
Connect

GATECH ID – GTID
- NOTE: This is not you Georgia Tech Username; it is your 9 digit Student Id you can find on your Buzzcard or by following the below steps:
- Please see the Finding Your GTID section in Submissions & Gradescope page page for instructions on retrieving your GTID.
- Be very careful! When you copy and paste, strip off all leading spaces or special characters.
Project Time Expectations
Based on feedback from students in previous semesters, the time required to complete this project is roughly divided as follows:
- Approximately one-fourth of your time will be spent on inference-related tasks.
- Approximately half will be dedicated to SQL injection tasks.
- Approximately one-fourth will be dedicated to Defender tasks.
This estimate does not include time spent on extra credit opportunities (Task J). Because some tasks may require thoughtful analysis and trial-and-error, it is strongly recommended that you start early to avoid last-minute difficulties.
Everyone works at their own pace and skill sets vary—don’t be hard on yourself if you find you’re taking more time than estimated.
Feel free to post in the appropriate threads if you have questions about the project that aren’t addressed in the Write-Ups or have already been asked and answered on Ed. The TA team will be more than happy to help.
TASK A: GTID VERIFICATION
(flag0 – 0.5 pts)
NOTE:** Task A is the setup task and contains **one flag**:
flag0. **Please review the Submission Details for specific instructions regarding the format.
This task sets up the project and generates the hashes of the other flags, so verifying that the hash is correct in Gradescope is critical. (USE A SUBMISSION)
Important
- You only have 5 attempts to enter your correct GTID.
- If you exceed this limit, you’ll be locked out and must restore your VM.
How to Complete flag0
- Navigate to Task A:
- Click on the Task A menu from the home page. The page will open in a new tab.

- Click on the Task A menu from the home page. The page will open in a new tab.
- Enter your nine-digit GTID and click Submit:Where can I find my GTID?
- See the Required Reading page for instructions on how to retrieve your GTID.

Submission Details
- After receiving your hash, add it to the JSON file and submit it to Gradescope to verify its accuracy.
- NOTE:** This step will “use up” one of your submissions (16 possible), but it’s highly recommended to ensure everything is set up correctly before moving on. An incorrect setup will cause all subsequent flags to fail! **Submissions can not be returned.
- Once you’ve verified your correct hash, proceed to Task B!
Check the validity of your JSON before submitting to Gradescope.
TASK B: INFERENCE ATTACK #1
(flag1 – 12 pts)
NOTE:** Task B is an array flag and contains **one flag**:
flag1. **Please review the Submission Details for specific instructions regarding the format.
What Is an Inference Attack?
An inference attack isn’t a hack in the traditional sense—there’s no breaking into systems. Instead, it’s a method of deducing confidential information by analyzing seemingly harmless data that is available to many people either globally or within a company. Security regarding an inference attack deals with data confidentiality and providing data access/restriction on a need-to-know basis.
In most organizations, data security is enforced by access controls, which might restrict:
- Entire tables (e.g., the employee table, which contains the complete employee list)
- Individual rows (e.g., one specific row of an employee’s record)
- Individual columns (e.g., a piece of information about an employee, like salary, gender, or position at work)
However, even when data access controls are in place, attackers (or curious employees) can sometimes combine multiple safe reports to uncover private information.
This is called an inference attack. You don’t have direct access to sensitive data, but you can infer it from the data you do have. Such attacks often exploit standard reports available to many employees. For example, a company might restrict certain columns to enforce access control, creating an employee roster report that everyone can view but excluding sensitive details like salary. However, if other reports are not carefully designed with the same protections, they may unintentionally reveal that information.
Scenario Overview
You’ve been given four internal reports from a single company:
- Employee Roster – Names and general information, no salary information.
- Tenure Report – Shows how long each employee has worked at the company.
- Average Salary by State – Aggregates the average salary of employees within each state where they live.
- Average Salary by Tenure – Aggregates the average salary based on years worked at the company.
Individually, none of these reports violates the company’s access controls on sensitive HR data. However, with some clever analysis, you realize the reports can be combined in a way that exposes a serious gap, allowing someone to pinpoint individual salaries.
Your Goal
By analyzing and cross-referencing the reports, you must cleverly combine the data to identify specific employees whose salaries you can infer with 100% certainty.
To complete Task B, for each exposed employee:
- Record their hash ID (unique to your VM and generated when you completed Task A).
- Record the exact salary (to two decimal places, without $ or commas).
- Repeat this process for all relevant employees.
Save this information in the JSON file as part of your submission for flag1.
Success Criteria
- At minimum, you should be able to infer the salary of one employee.
- There may be multiple; continue analyzing to find as many as possible.
- You can only uncover one employee’s salary at a time.
- Submit employees whose salaries are definitively exposed.
- Do not guess! Submissions are limited, and incorrect or guessed hashes will cost you.
Tips for Success
- Look for uniqueness – Groups with only one person often provide the clearest clues.
- Start with small groups – Examine non-employee reports for data that can be linked back to the employee list to reveal salaries.
- Be methodical – Identify overlaps that isolate individual employees.
- Double-check your logic – Only report salaries you are 100% certain of.
How to Complete flag1
- Navigate to the Task B Menu:
- Hover over the Task B menu, which will display the following four reports:
- Employee Report
- Duration Report
- Salary by State Report
- Salary by Duration Report (Each page opens in a new tab.)
- Hover over the Task B menu, which will display the following four reports:
- Review the Reports:
- Open each report by clicking its name; it will open in a new tab.
- Look for data that can help you infer at least one employee’s salary.
- Focus on combining data points across multiple reports.
- Identify an Employee:
- Once you determine an employee’s exact salary, find their hash in the Employee Report (ID column) and record it.
- Record the Hash and Salary:
- After finding and eliminating one employee, check if there is another whose salary can be determined precisely.
- Use the known employee’s salary to calculate the next employee’s exact salary. Repeat the process until no further deductions are possible.
- Add each employee found to the next position in the flag array (i.e., the order in which employees are found corresponds to array[order – 1]).
Hints
- Look for unique patterns in the data across the four reports.
- For example, a specific employee’s data might stand out when comparing one of the other reports in the Task Menu with the Employee report.
- Combine Reports:
- The key to an inference attack is combining data from multiple reports to isolate an individual’s information. Think about how different reports might intersect or overlap.
- Track Data:
- If you’re having trouble keeping track of the data, consider copying it into a spreadsheet or other application to manipulate and search more easily.
- Logic Helps:
- If you’ve already figured out one employee’s salary, the remaining employees might share a common trait with the ones you’ve found (you will need to “eliminate” the previously found employee’s salary to obtain the newly found employee’s salary).
- Example:
- A little bit of math is involved in figuring out the salary information of the following employee.
- An example that has helped students in the past is: Imagine two people, A and B, buy eight apples together. If we know A only bought six apples, we can “calculate” and “infer” that B bought only two apples.
- General Hints about all Inference flags:
- Only look at the data relevant to the task – Don’t get tied up in data that provides no value to the task.
- If it looks like a table and acts like a table, it is probably a table. While this is unnecessary to complete the task, you can copy data from the report(s) into a spreadsheet program to manipulate it. This may assist you in tracking down the hole that exposes salaries.
- If you use an external application to troubleshoot the data and try to sort, ensure the entire dataset is sorted.
- General Hints about all Array flags:
- You will receive credit for each element in the correct array.
- For flag arrays with more than the hash (salary/cpt), there is no partial credit for the array if the hash is correct but the other data is not.
- You will not be penalized for not filling in the whole array.
- i.e., if there are six elements in the array, and you have only two, you will not be penalized for the missing four.
- You will be penalized if you overfill the expected array.
- i.e., if there are six elements in the array, and you have seven, you will be penalized for the extra one.
- You are reporting a salary in US currency, hence, two decimal places with no $.
- You will receive credit for each element in the correct array.
Submission Details
- The flag1 array should contain hashes paired with salaries, formatted as
hash_salary(e.g.,abc123_50000.00). - Salary of the found employee should be two decimal places.
- Order matters —the employee you identify first should go in array[0] , the second employee in array[1] , and so on.
Good luck with Task B! After completing this task, move on to Task C.
Check the validity of your JSON before submitting to Gradescope.
See Submission Details for more information.
TASK C: INFERENCE ATTACK #2
(flag2 – 15 pts)
NOTE:** Task C is an **array flag** and contains **one flag**:
flag2. **Please review the Submission Details for specific instructions regarding the format.
Overview
Now that you’ve seen how an inference attack can expose sensitive information within a single company, it’s time to explore how the same technique can compromise data by linking together unrelated datasets.
In this task, you will carry out another inference attack — but on a broader scale. Instead of one source, you’ll work with four independent datasets that are publicly available online. Each comes from a different domain: hospital visits, voter registration, insurance claims, and medical codes.
Your mission is to analyze these datasets to identify specific individuals who have undergone certain medical procedures, while respecting the deidentification rules designed to protect privacy. Your task is to show how separate anonymized datasets can be combined to reveal sensitive information. Specifically, you will link medical data, particularly procedure records, to voter registration data, uncovering individuals and their associated medical history. This exercise highlights how incomplete deidentification, when paired with publicly available data, can still expose private information. This is, of course, a significant breach of HIPAA regulations (in fact, this exercise was inspired by the incident where the medical history of the governor of Massachusetts was made public in a similar fashion). Read more.
What you need to do
- Review the four reports: There are four reports you need to examine:
- Medical History – A sample report from a local hospital detailing the types of procedures performed over the last few years.
- Voter Registration – A report containing standard voter fields. Reports like this are often available from a local board of elections for all registered voters in a district.
- Insurance Claims – A partially de-identified dataset from an insurance company, created for public use by the same developers you’ve encountered earlier. “Partially de-identified” means that while some information was removed to obscure patient identities, enough remains that a determined analyst could still link data back to real individuals.
- Medical Codes – A reference report listing medical procedure and diagnosis codes.
- Find the compromised patients: The objective is to determine which specific patient in the Medical History report has been exposed and can be linked to a Voter Registration record.
- Identify the exposed individuals:
- After you’ve figured out which patient(s) have had procedures performed, you’ll need to look up their hash in the voter registration report.
- The hash will be listed next to the patient’s name, which is specific to you based on your GTID from Task A.
- Record the information:
- For each identified individual, record their **hash followed by the CPT code (procedure code). The format will be:**
hash_cptcode(e.g.,abc123_67890). - What is a CPT Code?
- Current Procedural Terminology (CPT) codes provide a standardized language for documenting medical services and procedures on a patient’s record. They are also used for billing purposes.
- Unlike the previous task, this is not an elimination-style inference attack. This means the order of the data does not matter; you can add entries in any sequence as you identify individuals. However, make sure each entry is accurate.
- For each identified individual, record their **hash followed by the CPT code (procedure code). The format will be:**
How to Complete flag2
- Navigate to the Task C Menu:
- Hover over the Task C menu, which will display the following four data sources:
- Medical History
- Voter Registration
- Insurance Claims
- Medical Codes (Each page opens in a new tab.)
- Hover over the Task C menu, which will display the following four data sources:
- Examine the Reports:
- Open each of the reports and scrutinize the data.
- Pay special attention to identifying procedure data that can be traced back to specific individuals.
- Link the Data:
- You may want to look up the work done (what the procedure was) on the patient.
- Match that information from the other reports with the Voter Registration report to identify the person linked.
- Record the Hash and Procedure Code:
- For each identified individual, locate their hash in theVoter Registration report and note their CPT procedure code .
- Format the result as
hash_cptcode(e.g.,abc123_67890). - Once you isolate a voter, continue to see if you can isolate another voter. Rinse and repeat until you can no longer isolate a voter.
Hints
- Use Spreadsheet Tools:
- Like in Task B, copying the data into a spreadsheet can help you organize and analyze the information.
- Sorting and filtering the data might help identify links between the reports.
- Look for Unique Identifiers:
- In this task, the procedure data from the Insurance Claims and Medical History reports may help you find specific individuals.
- To narrow your search, use the medical codes and cross-reference them with other data.
- Multiple Data Sources:
- Unlike Task B, where you narrowed down the search to a single record, in this task, you will need to use logic and combine multiple data sources to link individuals.
Submission Details
- The flag2 array should contain hash_procedure pairs, formatted as
hash_cptcode(e.g.,abc123_67890). - Order does not matter —you can enter the hashes in any order.
Good luck with Task C! After completing this task, move on to Task D.
Check the validity of your JSON before submitting to Gradescope.
See Submission Details for more information.
TASK D: INFERENCE ATTACK #3 – USING DBGATE
(flag3 – 7.5 pts)
NOTE:** Task D contains *one flag:
flag3.* **Please review the Submission Details for specific instructions regarding the format.
Overview
Task: Inference Attack on Encoded Patient Data
You are tasked with investigating a potential security vulnerability in your company’s patient database. This requires performing an inference attack to determine whether sensitive data can still be uncovered despite the use of encoding measures.
Background
You’ve learned that the database administrator attempted to secure patient data by:
- Encoding sensitive fields in the Patient table, including date of birth (DOB).
- Encoding the social security number (SSN) using the patient’s original (unencoded) DOB as part of the encryption or masking scheme.
This database supports a Pediatric Office within the system.
During a recent visit with your child, you noticed a sign-in sheet openly displayed at the front desk. The sheet contained the following information:
- Appointment Date
- Patient first and last names
- Provider’s last name
- Appointment time
- Arrival time
You discreetly photographed the sheet, which can be accessed through the Task D Menu link.
Result
Despite encoding efforts, you can derive the following sensitive information for one patient that is not on the sign-in sheet:
- First name
- Last name
- Date of birth
- Social Security number
How to Complete flag3
- Navigate to Task D:
- Click on the Task D menu from the home page. The page will show the picture of the schedule.

- Click on the Task D menu from the home page. The page will show the picture of the schedule.
- Review the picture you took to see what data is provided that can be relevant in your hunt.
- Review the tables in the database using DbGate → You will need to access the TaskD Database.
- Review the Background and Setup page for instructions on how to set up/use DbGate.
- You should not run
INSERT,DELETE, orUPDATEqueries on the tables — doing so may require a restore of the database!
- When you find the date of birth of the patient, you will need it to decrypt the SSN. Keep the following in mind: – Assume the DOB format for decryption is
YYYYMMDD. – You’ve heard that the database administrator is using a built-in SQL Server function that encrypts data using a passphrase.
Hints
- Use the data you have: Remember that in an inference attack, all you can use is the data you have available. Do not make “assumptions”.
- Could you perform an inference attack on data in a language you aren’t familiar with and have no way to translate?
- There is only a single patient that is correct; if you are finding more than one patient, review your logic/code.
- Brute Force: Brute force technique will need to be applied here in order to find the patient’s dob/ssn. *Note: ensure you find the correct patient before attempting to brute-force the ssn decrypt or risk finding false positives and wasting submissions.
- Hash: Unlike all other tasks, this task has no hash.
Submission Details
- The flag submission should be
FirstNameLastName_DOB_SSNwhere the first initial of the first/last is Uppercase, dob is in the formatYYYYMMDD, and ssn is only the numeric value not the returned value of xxx-xx-xxxx (e.g.,JaneDoe_19010101_123456789).
Good luck with Task D! After completing this task, move on to Task E.
Check the validity of your JSON before submitting to Gradescope.
See – Da for more information.
TASK E: SQL INJECTION #1
(flag4 – 2 pts | flag5 – 3.5 pts | flag6 – 5 pts)
NOTE:** Task E contains **three flags**:
flag4,flag5, andflag6. **Please review the Submission Details for specific instructions regarding the format.
Introduction: What Is SQL Injection?
This task highlights one of the most common yet preventable database vulnerabilities: SQL Injection (SQLi). SQL injection occurs when user input is not properly validated, allowing attackers to inject or modify SQL statements. The consequences can be severe, ranging from unauthorized access and data exposure to complete system compromise.
The root cause of SQL injection is often careless coding and weak input validation. Developers must ensure that all user-provided data is carefully inspected and that potentially harmful input is sanitized or blocked before reaching a SQL query. This process, known as input sanitization, prevents malicious commands from being executed and protects the database from manipulation
To help you get started, we recommend reviewing online resources like the SQL Injection Cheat Sheet for an overview of techniques and examples.
To complete this task, you will need to craft basic SQL code that can be entered into a form’s input field and executed by the website as part of a valid — but unintended — SQL statement. The goal is not to write complex queries, but to bypass weak SQL injection defenses. This could involve evading security checks, retrieving unauthorized information, or, in severe cases, altering the site’s data. Once a vulnerability is present, successful exploitation depends on your ability to understand or map the structure of the underlying database.
Task Description
In this task, you will work with a sample web application that contains intentional SQL injection vulnerabilities in three different login implementations. Your objective is to exploit these flaws to bypass authentication and capture the corresponding hash flags.
You’ll log in using your GTID (as entered in Task A). You won’t know the actual password — instead, you’ll attempt SQL injections via the password field to force a successful login.
Objective Breakdown
Task E consists of three parts, each increasing in complexity. The site is updating its Legacy Login page, and all three hashes for Task E will change. The main security check on the legacy page is a direct match of the username, your GTID. You will not know the password needed to access the system, and you will not be provided with it.
- For flag4, the developers are asking you to assess the difficulty of bypassing the existing security, given that a SQL Injection attack is possible.
- They also want to explore ways to mitigate this risk. Specifically, they are considering whether to implement only client-side data sanitization or both client-side and server-side sanitization, and whether the same rules should apply consistently on both ends.
- For flag5, you will attempt to bypass/beat the security using client-side data sanitization.
- For flag6, you will attempt to bypass/beat the security using client and server-side data sanitization.
- For this flag, remember that there will be server-side data sanitization that you cannot access, but you should assume the logic will duplicate the client-side data sanitization.
- The client provided a snippet of the code they used on the legacy login page.
- You can use this code to determine how to perform the SQL injection.
- When you succeed, you will log in to the website using your GT ID and no password.
- The injection will bypass the password requirements and log you in immediately.
- Once logged in, the hash for flags 4-6, keyed to your GT ID, will be displayed.
How to Complete flag4, flag5, & flag6
- Navigate the Task E Menu
- Hover over the Task E menu to reveal three links:
Legacy LoginNew Login - ClientNew Login - Client/Server(Each page opens in a new tab.)
- Hover over the Task E menu to reveal three links:
- Perform the Injection
- Enter your GTID as the username.
- Enter a **crafted SQL injection payload in the** password field.
- Submit the login form.
- If successful, you’ll be logged in and shown your corresponding flag hash.
- Summarising the flag challenges as below:
Flag Login Type Challenge Description flag4 Legacy Login No sanitization — perform a basic SQL injection. flag5 New Login – Client-side Sanitization Bypass/beat client-side JavaScript sanitization. flag6 New Login – Client + Server-side Bypass/beat both client- and server-side sanitization. - Record Your Hashes Copy the three flags you retrieve (
flag4,flag5,flag6) into your final submission JSON.
Where’s My GTID?
If you’re unsure of your GTID, refer to the Submissions & Gradescope page for instructions.
Hints & Tips
For flag5 and flag6
- Open the browser’s Developer Tools to inspect the client-side JavaScript.
- If you don’t know how to open Developer Tools, a quick Google search can help you identify that for your browser.
- If you are trying to copy/paste into the console in Developer Tools and receive a warning, you will need to follow the steps to enable the ability to paste into the console.

- Look for sanitization functions — analyze how the input is cleaned or blocked.
- Input sanitization is cleaning and validating user input to prevent security threats like SQL injection.
- Consider running these functions manually in the console to understand or bypass/beat them.
Sanitization Considerations
- There is a difference between encoding, escaping, and sanitization. Understand the difference and the validity of using one or the other, remembering that the client/server-side code is doing sanitization.
- You have access to the JS where the sanitization is done on the Client Side. You also know that client-side and server-side sanitization are the same.
- Is there a way in DevTools to call a function again?
- There is a difference between bypassing and beating the sanitization.
- Unless it is a single character in the strip, you can “beat the sanitization.”
- Only one of the lines strips a single character
- Try to beat the sanitization line by line to understand a valid approach! Use the sanitization code against itself.
- Natural sanitization is also at play.
- PHP uses
?and&for variables, so while not “sanitized,” they will break up your injection if used. - The web browser converts the character
#(if not HTTP encoded) into a blank character.
- PHP uses
SQL Injection Hints (For All SQLi)
- SQL not-equals can be written as
!=or<>— one may work even if the other is blocked. - Single quotes (
') are often required to break out of the query string — they are usually not sanitized and are needed for most injections - You may think you are writing a SQL injection, but the database might read it as a regular string.
- Remember that the entire injection statement goes into a string variable.
- While the exception causing the data breach is returned for troubleshooting, this exception is based on the expectation that the input is a string, not an injection!
- The exception returned is for your benefit and may NOT be shared in ED.
Nullworks great for an SQLi when you don’t know the schema and the developers don’t expect it. The developers are actively looking for it!- There is a difference between ending a statement to begin a new statement and escaping out of the statement.
- If you use
+to join varchar (string) statements and aren’t receiving the result you expect, maybe try a different approach! - In MS TSQL, a
;ends a statement to allow a new statement to begin. However, is it really necessary or required?
Reference: Legacy Login Code
- All login injection tasks are built off flag4.
- It may be possible that flag4 can never be used as a template when sanitization is involved.
- Below is the login code that you were able to obtain from the legacy login page (both username and password have a character limit of 96):
<?php
function login($username, $password) {
$sql = "SELECT username, count(*) cnt INTO #tmp_user FROM users WHERE username='$username'" . PHP_EOL . "group by username";
$usercheck = $this->db->query($sql)->execute()->fetch();
if ($usercheck['cnt'] != 1) {
return false;
} else {
$sql = "SELECT hash FROM #tmp_user t JOIN users u on t.username = u.username WHERE password='$password'";
$userdata = $this->db->query($sql)->next();
if ($userdata) {
return true;
} else {
return false;
}
}
}
?>
Submission Details
Once you have the hashes for all three flags, please copy and paste them into your submission JSON.
Good luck with Task E! After completing this task, move on to Task F.
Check the validity of your JSON before submitting to Gradescope.
For submission instructions, refer to the Submission Details page.
TASK F: SQL INJECTION #2 / INFERENCE ATTACK #4
(flag7 – 7.5 pts)
Note:** Task F is an **array flag** and contains **one flag**:
flag7. **Please review the Submission Details for specific instructions regarding the format.
Overview
In this task, you’ll combine your knowledge of SQL Injection (SQLi) and Inference Attacks to identify specific students from a fictional grade list who received an “F” in the class.
You’ll start by performing an SQL injection to bypass the login form and gain access to a restricted section of the site. Once logged in, you’ll encounter a security question. To answer it, you’ll use Open-Source Intelligence (OSINT) techniques — methods commonly employed by social engineers to gather publicly available information and exploit it for unauthorized access.
If you complete both stages (SQLi and OSINT), you’ll access extended roster data and use an inference attack to identify students who failed the course.
What is OSINT?
OSINT stands for Open-Source Intelligence. It refers to the practice of collecting and analyzing information from publicly available sources — essentially, anything you can legally access online or offline without hacking or breaking into systems.
For example, imagine you’re working on a school project about climate change. You might research news articles, government reports, YouTube videos, and social media posts to gather insights. That’s OSINT in action — using open sources to build practical knowledge.
Learn more about it here – What is OSINT?
Objective
Your goal is to:
- Identify a valid username through OSINT techniques.
- Perform a **SQL Injection attack to bypass the** password field.
- Complete a Multi-factor Authentication request using OSINT techniques to obtain the prompted information relevant to the account.
- Access the roster data and identify the students who received an “F”.
- Submit those student ids in the
flag7array (order does not matter).
How to Complete flag7
- Navigate to Task F:
- Click on the Task F menu from the home page.

- Click on the Task F menu from the home page.
- Login Attempt
- Use the username you discovered or inferred via OSINT.
- Enter an SQL injection payload in the password field to bypass authentication.
- Submit the form.
- Security Question
- If your injection is successful, you’ll receive a multi-authentication prompt (e.g., a security question or a PIN).
- Use OSINT methods to deduce the correct response. Pay attention to contextual hints.
- Access Extended Roster
- If the second authentication step is successful, you’ll gain access to detailed roster data.
- You must gain some inference knowledge to identify the students who received an F.
- Identify all students who have received an “F” grade and record their hashes.
Hints & Guidance
- No input sanitization is present on the login form, particularly in the password field. This means the SQL injection should work similarly to earlier tasks.
- You cannot use injection on the Multi-factor Authentication page. Don’t try to do that; it will not give you what you want.
- If you see the security question prompt, it confirms your SQL injection worked.
- OSINT Focus:
- Consider what information users might use to answer security questions.
- Use the provided context or details on the login page to infer possible answers.
- In the real world, this might include social media (professional and personal), forums, or previously disclosed information — here, you’re working within the fictional context of this task.
- This is a combination challenge. You are applying:
- SQL Injection to break into the system.
- OSINT to get past multi-factor authentication.
- Inference to extract meaningful insights from data.
Submission Details
Once you identify the students who received an “F”, add the hashes (no particular order) into the flag7 array before proceeding to Task F (order of report does not matter).
Good luck with Task F! After completing this task, move on to Task G.
Check the validity of your JSON before submitting to Gradescope.
For detailed submission guidelines, refer to the Submission Details page.
TASK G: SQL INJECTION #3
(flag8 – 7.5 pts / flag9 – 7.5 pts)
NOTE:** Task G contains **two flags**:
flag8andflag9. flag9 is reliant on the “partial completion” of flag8 (while you do not need the hash for flag8 to complete flag9, you do need the schema). **Please review the Submission Details for specific instructions regarding the format.
Overview
In Task G, you’ll perform two advanced SQL injection attacks targeting a fictional music store database. These attacks will help you:
- (flag8) Modify access rights to uncover hidden table schemas.
- (flag9) Extract a valid database user’s login credentials through SQL injection, then log into a simulated admin console to retrieve your flag.
Understanding the “Schema” Page and Your Goal
You’re working with a music store’s website that has a search engine for music albums. While exploring the site, you’ve found a page called “schema.” This page shows behind-the-scenes information — specifically, the structure (or metadata) of a database table used in the main report.
What You’ve Noticed
- The website follows a predictable pattern, especially in how links are structured.
- Based on this pattern, manipulating those links is likely a way to gain more access.
- This could let you see more database information than what’s shown by default.
What You Know
- The Schema page uses a database user called Schema to connect to the database – confusing yes, but like programming variables, sometimes the variable name is exactly what it is used for.
- This user only has read-only access to a table called Music, so you can only see the Music table’s schema.
What You Need to Do
- Your goal is to use injection to give the Schema user access to all tables, not just Music.
- That way, when you reaccess the schema page, you’ll see more than just the Music table (if you performed the injection correctly and found the correct manipulation of the URL).
- Right now, you don’t know the names of the other tables or schemas — that’s part of the challenge.
Task Breakdown
flag8 – Privilege Escalation via Injection
The page called Schema reveals metadata for the Music table. This view is read-only and tied to a limited-access database user named Schema.
The Report page uses this same schema to generate queries. Your job is to figure out how to extend the Schema user’s access, so it can view more than just the Music table.
Once you succeed, the Schema page will show additional tables. You will notice that the new table does not have a hash associated with it. There is a reason for this:
- This allows students unable to complete the privilege escalation injection to attempt the next flag.
In order to obtain the hash, you must create the required privelege escalation using the “search” functionality on the Report page. When successful, the new hash will appear in the schema header. That hash is your flag8.
flag9 – Credential Extraction and Login
After gaining visibility into new database tables, you must construct another SQL injection on the Report page. This time, your injection should extract a username and password from another table.
You’ll then log into the Login page using the credentials you uncovered. If successful, you’ll land in a simulated “management console,” where your flag9 hash will be displayed.
Unlike the other login forms thus far, this login page is locked down and SQLi will not work. You are more than willing to try, but as the great DBA Obi-Wan Kenobi said: 
How to Complete flag8 & flag9
- Navigate to the Task G Menu:
- Hover over the Task G menu, which will display the following three data sources:

SchemaReportLogin(Each page opens in a new tab.)
- Hover over the Task G menu, which will display the following three data sources:
- Schema Page
- Displays the schema for the Music table.
- Use this to understand how the schema is structured and explore ways to gain broader access.
- Report Page
- Accepts a search input, which runs a
SELECT ... FROM ... WHERESQL query. - This is your injection point for both flag8 and flag9.
- Accepts a search input, which runs a
- Login Page
- Once you discover valid login credentials from your injection, enter them here to retrieve flag9.
Steps to earn flag8 & flag9
flag8 Hash
- Display the New Table
- By reviewing the Schema page and URL, is there anything you can manipulate to show all schema, not just the Music table schema, which is available to all users?
- Find a Privileged Role
- Is there a database role you can add your user to that allows viewing (read) other table schemas (not just
Music)?
- Is there a database role you can add your user to that allows viewing (read) other table schemas (not just
- Inject the Role Assignment
- Go to the Report page.
- Enter your injection in the search bar to add the role.
- Click Search.
- Check the Schema Page
- Return to the Schema page that you have already configured to show the new table.
- If your injection worked, the hash for the new table will appear.
- At the top of the new table, check the Schema header.
- Your flag8 hash will be displayed there.
- Submit Your Flag
- Add the hash to your
JSONfile under"flag8". - Submit it to Gradescope.
- Add the hash to your
flag9 Hash
- Query Other Tables
- Now that you can view the other table’s schema, try using the search bar again.
- This time, inject a query that returns rows from a different table, not just the default one.
- Remember that the default query (which you cannot change) will always return data from the Music table. This means you need to find a way to add data from another table to the default “SELECT * FROM Music” query.
- Run Your Injection
- Go to the Report page.
- Type your injection into the search input.
- Click Search.
- Look for Credentials
- If successful, the report results will display a username and password.
- These credentials are for the Management Console login.
- Log In
- Go to the Login screen.
- Enter the username and password from the report data.
- If correct, you’ll access the system.
- Get and Submit the Hash
- Once logged in, your flag9 hash will be shown on the screen.
- Add it to your
JSONfile under"flag9". - Submit your file to Gradescope.
Hints & Tips
General
- The Report page is your main injection point.
- Think carefully about how to construct SQL that extends queries to include other data (joins, unions, etc.).
- You’ll need to experiment and iterate to find the correct structure.
flag8
- There are two parts:
- Viewing the schema of all tables.
- Gaining access/rights to the non-public table.
- There is more than one way to complete this task; however, it may be useful to use SQL Server’s built-in stored procedures to escalate privileges.
- You don’t need admin rights — just enough read access to expose the hidden table. The developers are looking for unauthorized admin access!
- A successful injection might appear to fail — verify by checking the Schema page again.
- Don’t try to brute force access; that might corrupt your virtual environment.
flag9
- flag9 can be completed independently of flag8 (to a degree – you must obtain the schema for the missing table). The reason why flag9 is completable without providing the required rights to the hidden table in flag8 is that the database user schema is not used for the report page and the database user being used has access to both tables.
- Can you combine results from multiple tables with a UNION or similar SQL pattern?
- Think about what the data output tells you — success might look subtle.
URL Exploration
- You may find useful pages by manipulating URLs directly.
- Patterns in link structures may reveal hidden or undocumented pages.
Security Model
- Client-side sanitization is gone here, but server-side logic remains similar to earlier tasks.
- Login injection does not work on this task — injection is limited to the Report page only.
Submission Details
Once you’ve obtained the hashes, add them to your submission JSON and check the files for any formatting issues before submitting to Gradescope.
Good luck with Task G! After completing this task, move on to Task H.
Check the validity of your JSON before submitting to Gradescope.
See Submission Details for more information.
TASK H: SQL INJECTION #4
(flag10 – 7.5 pts / flag11 – 7.5 pts)
NOTE:** Task H contains **two flags**:
flag10andflag11. flag11 is reliant on the completion of flag10 (or you can choose to use your GTID for the username and password, but not receive a hash for flag10). **Please review the Submission Details for specific instructions regarding the format.
Overview
You’re testing the security of a banking website that allows users to log in and view transaction history. Your objective is to prove the system is vulnerable through two stages of SQL injection attacks :
- flag10: Log in as a valid user without knowing any credentials.
- flag11: Modify the transaction history to show a $2150.50 balance, no overdraw, and exactly 10 transactions .
Steps to earn flag10 & flag11
flag10 – Login Without Username
Goal: Log in to the banking site without knowing a valid username. You must use SQL injection in both the username and password fields to:
- Extract or generate a valid user from the database (see the hints section below for assistance in knowing what the database structure looks like)
- Pass the authentication check
Key Hints:
- Username injection must extract or resolve to a valid row from the user table.
- The injection logic will differ between the username and password fields.
- Brute forcing usernames, while possible, will be extremely tedious and time-consuming – aim to write a smart injection.
- You must use the skills you gained in Task E with more sophisticated SQL knowledge.
- Expect the site to run something like the PHP code provided in Task E.
- There is no sanitization for this task, the same as there was no sanitization for flag4 password injection.
- The username injection should extract a real entry. While there are various ways to complete the attack, a sub-query may be a beneficial place to start.
- The account hashed displayed is patial, you will need to submit the entire hash.
What success looks like:
- The site logs you in, revealing a username and a hash just beneath it.
- That hash is your
flag10.

flag11 – Tamper Transaction History
Goal: Once logged in, you’ll see 10 transaction entries and a balance. One entry will be an overdraw fee (-$25). You must:
- Remove the overdraw fee completely (including from any audit trail).
- Insert a new transaction to raise the total balance to exactly $2150.50.
- Maintain 10 total transactions .
Critical Part: You can’t inject into text boxes. You must modify the form payload via Chrome Developer Tools before the form submits. You are altering the data sent to the server, not to the UI!
- Routing & Account Number are only to simulate a real-world transaction (you do not need to find/use real information)
- Every time you log out/in, the transaction ledger resets

How to Complete flag10 & flag11
- Find the Transfer Form:
- Click the Transfer button to open the form.
- You’ll see fields like Routing Number, Account Number, and Amount.
- Open Chrome DevTools (F12):
- Set a breakpoint on the Submit button of the pop-up transfer form.
- Alter the JSON/Form Payload:
- Use DevTools to pause the form transmission and inject custom SQL into the backend submission.
- Craft the SQL Injection:
- You must inject an SQL statement that:
- Inserts a credit transaction (you can set the $ amount using the UI, but will need to change the payload before it sends)
- Deletes the overdraw fee entry and removes it from the audit trail
NOTE: This backend expects/uses JSON.
- You must inject an SQL statement that:
- Syntax Style:
- The backend uses SQL in one of these forms:
INSERT INTO table (...) VALUES (...)INSERT INTO table (...) SELECT ... FROM ...
- Determine which one is used by guessing or trial/error – again to simulate a real-world scenario (this information would most likely not be publicly available).
- The backend uses SQL in one of these forms:
- Verify Results:
- Final screen must show:
- Balance: $2150.50
- 10 Transactions
- No Overdraw Fee
- Validation Hash — This is your
flag11
NOTE: If anything is off (wrong balance, 11 transactions, or an overdraw still exists), the hash will be wrong.

- Final screen must show:
Hints Recap
flag10
- Look at how a sub-query could be useful to create your injection for the username
- You have already completed the requirements for the password injection in a previous flag
- You must pull a real user from the DB; attempting an injection to bypass the user will not work.
flag11
- If you attempt too many transactions in a short window, you may be flagged as this is _sus*. Maybe logging off and back on will allow you to try again?
- Use DevTools to edit a field value before the form is submitted.
- Find the table schema; maybe something you have previously done may work here as well.
- Look for a JavaScript function that is delivering your payload and pause the transmission to update the transaction with your payload. Then continue the transmission of your payload and check the results.
Submission Details
Once you’ve obtained the correct hashes, submit your JSON file on Gradescope after checking for JSON formatting issues.
Good luck with Task H! After completing this task, move on to Task I.
Check the validity of your JSON before submitting to Gradescope.
See Submission Details for more information.
TASK I: DEFEND AGAINST INFERENCE AND SQL INJECTION ATTACKS
(flag12 – 17 pts)
NOTE:** Task I is an **array flag** (Inference – Elements 1-3 → 7.5 pts / SQLi – Element 4 → 7.5 pts) and contains **one flag**:
flag12. **Please review the Submission Details for specific instructions regarding the format.
Overview
In this task, you’ll shift from attacking to defending. Instead of exploiting vulnerabilities (as in Tasks A–G), you’ll write SQL to prevent inference and SQL injection (SQLi) attacks.
NOTE: All validations will initially show yellow (not run). Click the Run test button next to each to validate individually.

How to Complete flag12
- Navigate the Task I Menu
- Hover over the Task I menu to reveal three links:
Test PagesRun Validation Checks(Each page opens in a new tab.)
- Hover over the Task I menu to reveal three links:
- Click Test Pages (opens in a new tab).
- Use the dropdown to select from:
- Employee Report Search → Test SQLi UNION injection defense
- Avg Salary By Title Report → Validate
TitleGenderAgeReport - Avg Salary By Dept Report → Validate
DepartmentEthnicityDurationReport - Login → Test SQLi login injection defense
- Use the dropdown to select from:
- Review the database in the database using DbGate → You will need to access the TaskI Database.
- Review the Background and Setup page for instructions on how to set up/use DbGate.
- You should not run
INSERT,DELETE, orUPDATEqueries on the tables — doing so may require a restore of the database!
Part 1: Inference Defense (flag12 Elements 1–3)
View: TitleGenderAgeReport
- Report average salary and bonus by Title, Gender, and Age
- Ensure k-anonymity (k=2) is enforced
- Follow the base table column order
- No default sort required
TGA Report De-Identification Rules
- Age Buckets:
<36,36–50,51–65,>65 - Priority: Title > Gender > Age
- Use
'Redact'to mask data (use'Other'for Title) - If needed for anonymity, use
'Omit'to exclude records
TGA Format Rules
- Salary: average, 2 decimal places,
$prefix, no commas - Bonus: average, 2 decimal places,
%suffix, remove trailing zeroes
View: DepartmentEthnicityDurationReport
- Report average salary and bonus by Department, Ethnicity, and Duration
- Calculate Duration from Hire Date to Today (365-day years,
FLOOR*ould be useful) - Follow table column order
- No default sort required
DED Report De-Identification Rules
- Duration Buckets:
<6,6–10,11–20,>20 - Priority: Department > Ethnicity > Duration
- Use
'Redact'to mask data (use'Other'for Department) - If needed for anonymity, use
'Omit'to exclude records
DED Format Rules
- Salary: average, 2 decimal places,
$prefix, no commas - Bonus: average, 2 decimal places,
%suffix, remove trailing zeroes
Part 2: SQL Injection Defense (flag12 Element 4)
Procedure: uspSQLReplace
- Do not change input parameters or how
@filteris returned - Only return the
@filtervariable (noSELECTstatements) - Client-side Sanitization was “provided” in other flags. You should convert the provided sanitization logic to SQL and use it here
- Prevent attacks like
' OR 1=1 --andUNION SELECT - Allow valid inputs that exist (e.g., for login, if a user truly has the ultra secure password “password”, you must allow it while still sanitizing injection attempts)
- Validate both Login and Search input
Hints & Tips
- Use Common Table Expressions (CTEs) to group and bucket data
- Prioritize columns in order of importance when grouping
- Only hardcode values when told (e.g.,
'Redact','Other','Omit') - Use
sp_executesqlfor secure dynamic SQL (docs)
Reset Code (If Needed)
-- Reset TitleGenderAgeReport
ALTER VIEW [dbo].[TitleGenderAgeReport] AS
SELECT *
FROM CompanyEmployees;
GO
-- Reset DepartmentEthnicityDurationReport
ALTER VIEW [dbo].[DepartmentEthnicityDurationReport] AS
SELECT *, '' AS Duration
FROM CompanyEmployees;
GO
-- Reset uspSQLReplace
ALTER PROCEDURE [dbo].[uspSQLReplace]
(@tblName varchar(64), @colName varchar(64), @colValue varchar(1024), @colDataType varchar(32), @filter varchar(1024) OUTPUT)
AS
BEGIN
DECLARE @sql nvarchar(max);
DECLARE @param nvarchar(64);
DECLARE @found int = 0;
SELECT @filter = @colValue;
/*Student Code Should Go Here*/
END;
GO
DbGate:
- Follow the instructions in Background and Setup
- You will be using the TaskI database
Below is how to edit a view:
- Click on the view you are working
- Click on SQL

- Click on Alter View

- Main Alter View screen

- Click on SQL
Submission Details
Include your flag12 hash (array of 4 elements) in the JSON file and submit it to Gradescope!
Good luck with Task I! After completing this task, move on to Task J (REMEMBER: Task J is extra-credit).
Check the validity of your JSON before submitting to Gradescope.
See Submission Details for more information.
TASK J: FIND THE TABLE / FIND THE HASH
(flag13 – 12.5 pts)
NOTE:** Task J is BONUS and contains **one flag**:
flag13. **Please review the Submission Details for specific instructions regarding the format.
Overview
In this task, you’ll need to find a hidden table and query it’s contents to find a hidden hash.
You should not attempt this task until you either have completed the other tasks, or have decided that you will not complete the other tasks as you may inadvertently make the task you are attacking no longer solvable for it’s intended attack.
Note: you do not need to do anything malicious (drop/delete) or elevation (access) attack!
Accessing the Hidden Table
- One of the previous tasks has a hidden table that you will need to write SQL to find. Use logic to narrow down which Task you should attempt and attack. To get you started, Task B and C are Inference Attacks and there is not an area to attempt a SQLi. You can also safely ignore Task A.
- Once you find the hidden table, you will need to return data from the table in order to find the hash to report. You will know the hash as it looks similar to the other hashes up to this point!
- You will need to pay attention to any constraints that exists!
- This will be a multi-phase attack and there will not be points awarded for the various phases, it will be all or nothing.
Submission Details
Include your flag13 hash in the JSON file and submit it to Gradescope!
Good luck with Task J!
Check the validity of your JSON before submitting to Gradescope.
See Submission Details for more information.











