My experiments with OWASP Juice Shop: What I Hacked, What I Couldn’t, and What I Learned
- Srividya Sundaravadivelu
- May 1, 2025
- 8 min read
During one of my test automation classes, I was introduced to the OWASP Juice Shop application. As an assignment, I was asked to automate testing of the application using Selenium with Java. While working on Juice Shop, I discovered that the application contains hidden security challenges—almost like a treasure hunt for hackers. The website proudly claims to be “the most modern and insecure web application”. This instantly piqued my curiosity. I wanted to explore the intentionally planted vulnerabilities in the application.
Coming from a development background, I was pretty familiar with the terminology of common security issues, but I had never tried them hands-on. This was my chance to practically try out what I had only read about in theory. In this blog, I’ll take you through my beginner-friendly journey into web application security. This will be a hands-on demo on the Juice Shop application - what I managed to hack, what I couldn’t, and most importantly, what I learned.
Setting up OWASP JuiceShop locally
I had to set up the OWASP JuiceShop application locally to start the experiment. This was super easy since I used Docker. I already had Docker installed on my machine. All I had to do was open a terminal and run the command "docker run -d -p 3000:3000 bkimminich/juice-shop". This command downloads the Juice Shop image, runs it in detached mode, and maps the container’s port 3000 to the local port 3000. I navigated to http://localhost:3000. This is all I had to do to have the Juice Shop application up and running on my local machine.
Here are some of the attacks I tried on the OWASP Juice Shop application:
SQL Injection Attack
What is it?
SQL injection is a vulnerability where an attacker inserts malicious SQL code into an application's input fields to manipulate the backend database. It can bypass authentication, access unauthorized data, or even delete entire tables.
What did I try to hack?
I tried to bypass the login authentication and gain unauthorized access to the application. I tried to log in as an admin user without the actual credentials.
How did I do it?
I navigated to the JuiceShop login page. In the Email field, I entered ' OR 1=1-- (making sure to enter the quote (') and the comments (--). In the Password field, I entered a random password. Then I clicked on the Log in button.

JuiceShop Log in form What was the outcome?
I was able to successfully log in as an admin user without providing a valid email or password. The application accepted my input and granted access, proving it was vulnerable to SQL Injection.
Why did it work?
The original SQL query in the application looks something like this:

In my case, since I gave Email as ' OR 1=1--, the query became:

The quote (') closes the string literal for email and injects code afterward. email = '' is always false since it's empty. But, OR 1=1 always returns true. Also, -- comments out the rest of the query, so AND password = 'anything'; is ignored.
So, the query now became:

Since the above query is always true, the server allows me to log in successfully even though I don't have real credentials.
Cross-Site Scripting attack (XSS)
What is it?
Cross-Site Scripting attack (XSS) is a vulnerability where an attacker injects malicious scripts into web applications. This can lead to session hijacking or redirection to malicious sites.
What did I try to hack?
I aimed to inject malicious JavaScript into the Juice Shop application and prove that the browser would execute it. I wanted to display the user's cookie via an alert box.
How did I do it?
I entered the following payload in the search bar:

What was the outcome?
The script executed and displayed a pop-up alert box with the cookie in the browser. This proved that the application rendered user input as HTML/JavaScript, without escaping it.

Why did it work?
The application didn't sanitize or escape HTML input. The payload closed an existing tag and injected a new image tag with an invalid source attribute. Since the image failed to load, the onerror attribute executed the JavaScript code to alert the document cookie. An attacker could use this vulnerability to steal session cookies, impersonate users, or redirect them to phishing sites.
Cross-Site Request Forgery (CSRF)
What is it?
CSRF tricks an authenticated user into submitting an unintended request to a web application. For example, updating settings, changing passwords, or submitting forms, without their knowledge or consent. It exploits the fact that browsers automatically include session cookies in every request.
What did I try to hack?
I wanted to simulate a CSRF attack by silently submitting a feedback form into the Juice Shop application without the user clicking any "Submit" button, but just by making them open a malicious HTML file.
How did I do it?
1. I created a malicious HTML file (csrf_attack.html) with a hidden form that auto-submits fake feedback. This will silently submit feedback to Juice Shop without permission.

csrf_attack.html 2. I ensured I was logged in to the application as an admin. Then I started a local HTTP server using py -m http.server to serve the csrf_attack.html file and opened it in the browser by visiting http://localhost:8000/csrf_attack.html.
3. Since I was already logged into Juice Shop in the same browser session, the request to submit feedback was automatically sent along with the session cookie (token). I verified this by inspecting the request in the browser's DevTools Network tab.

session cookie included automatically for the request
What was the outcome?
The CSRF attack was not successful. Though the session cookie was included automatically for the request, Juice Shop expects a CAPTCHA ID field. But the CSRF form didn’t include it. So, Juice Shop throws an error.

Why didn't it work?
CAPTCHA acts as a challenge that only a real human can solve. In Juice Shop, submitting feedback requires solving a CAPTCHA. Since a CSRF attack relies on automatically submitting a request from another website without the user's knowledge, it can't solve the CAPTCHA. This prevents the malicious request from succeeding, thus effectively blocking the attack.

Unvalidated File Upload
What is it?
This vulnerability occurs when an application allows users to upload files without properly validating the file type, content, or extension. This allows malicious files to be uploaded and executed.
What did I try to hack?
I tried uploading an HTML file containing malicious script content but disguised as a PDF.
How did I do it?
I navigated to the "Complaint" section in Juice Shop. I created a malicious HTML file and renamed it to .pdf without changing the content. Then, I uploaded it via the “Complaint” form.

malicious HTML file disguised as a PDF What was the outcome?
The file was accepted and uploaded successfully. Here is the screenshot:

Complaint form - successful file upload Why did it work?
Juice Shop validates the file based only on the file extension (.pdf), not the MIME type or the actual file content. This weak validation can be exploited to sneak in malicious content.
Broken Access Control
What is it?
Broken Access Control occurs when an application does not properly restrict what authenticated users can do. Users can access unauthorized data or functions by modifying a parameter or URL.
What did I try to hack?
I attempted to access the admin user's shopping basket by changing the basket ID in the backend API URL.
How did I do it?
Below are the steps that I followed:
1. I registered a new user test@abc.com and logged in to Juice Shop as that user.

Log in form 2. I then navigated to the basket page and opened the DevTools → Network tab. I copied the cURL
Request for the GET /rest/basket/{id} endpoint.

Copy the curl request for the GET /rest/basket/{id} endpoint 3. I opened Postman, pasted the cURL as a request, and verified it returned the basket details for the new user test@abc.com

Postman response - basket details for logged-in user 4. I then changed the basket ID in the URL to 1, which is the admin’s basket. I sent the request using the same token as the logged-in user test@abc.com

Postman response - basket details for admin, though not logged in. What was the outcome?
I was able to view the contents of basket ID 1, which belongs to the admin user, though I was not logged in as an admin user. That means I accessed another user's private shopping cart, which is a serious security flaw.
Why did it work?
The backend did not check if the basket ID I was requesting actually belonged to the logged-in user. As long as I had any valid token, I could access any basket by changing the ID. This proves that authorization checks were missing or broken on the server side.
Insecure Direct Object References (IDOR)
What is it?
IDOR is a specific type of Broken Access Control vulnerability where a user tries to change another user’s information without authorization. IDOR vulnerabilities occur when an application exposes internal objects like user IDs without proper access control. Attackers can manipulate these IDs to gain unauthorized access or perform unintended actions.
What did I try to hack?
I was logged in as test@abc.com, but I attempted to change the admin user's profile picture by making a POST request to the endpoint that updates the profile image URL—/profile/image/url.
The goal was to test whether the application validates who is making the request or if it blindly accepts the image update.
How did I do it?
I followed these steps:
1. I logged in to Juice Shop as test@abc.com
2. I went to the "Profile" section for the user test@abc.com

User Profile form 3. I copied the curl for the POST request http://localhost:3000/profile/image/url using browser dev tools

Copy the curl for update profile image 4. I pasted the curl in Postman and crafted a payload to update the profile image.

Postman request and response for update profile image 5. I sent the POST request and was able to update the profile image successfully for the logged-in user test@abc.com

Profile image update for logged-in user 6. I then tried to change the image URL for the admin by manipulating the ID field, but the request didn’t offer any obvious ID to manipulate.
What was the outcome?
I was not able to change the image for the admin.
Why didn't it work?
Juice Shop didn’t expose any user IDs that could be manipulated, so the attack attempt failed. Juice Shop ties the profile image change to the current authenticated user only, which is enforced via the authorization token. This effectively prevents IDOR-type attacks.
What did I learn?
Here are my learnings from my experiments on the Juice Shop application:
SQL Injection and XSS attacks are simpler to execute, but the outcome is devastating if left unchecked.
CSRF and IDOR didn’t work in my tests, but these failures taught me why they failed—because of protections like CAPTCHA and proper authentication tokens.
APIs are also vulnerable, just like the UI. Broken access control can be a real threat since it exposes critical data.
The Juice Shop application was a perfect playground for understanding real-world security flaws in a safe environment. I explored just six attack scenarios, but the Juice Shop includes many more vulnerabilities waiting to be uncovered. This reminded me that security isn't something you install once and forget— it's about continuous learning, testing, and improving.

