Customization
One of the core usage scenarios for OWASP Juice Shop is in employee trainings in order to facilitate security awareness. With its not entirely serious user roster and product inventory the application might not be suited for all audiences alike.
In some particularly traditional domains or conservative enterprises it would be beneficial to have the demo application look and behave more like an internal application.
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.
How to customize the application
The customization is powered by a YAML configuration file placed in
/config
. To run a customized OWASP Juice Shop you need to:
-
Place your own
.yml
configuration file into/config
-
Set the environment variable
NODE_ENV
to the filename of your config without the.yml
extension-
On Windows:
set NODE_ENV=nameOfYourConfig
-
On Linux:
export NODE_ENV=nameOfYourConfig
-
-
Run
npm start
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.
Overriding default.yml
in Docker container
In order to override the default configuration inside your Docker
container with one of the provided configs, you can pass in the
NODE_ENV
environment variable with the -e
parameter:
docker run -d -e "NODE_ENV=bodgeit" -p 3000:3000 bkimminich/juice-shop
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:
docker run -d -e "NODE_ENV=myConfig" -v /tmp/myConfig.yml:/juice-shop/config/myConfig.yml -p 3000:3000 --name juice-shop bkimminich/juice-shop
YAML configuration file
The YAML format for customizations is very straightforward. Below you find its schema along with an excerpt of the default settings.
server
section
Offers technical configuration options for the web server hosting the application.
Property | Description | Default |
---|---|---|
|
Port to launch the server on. Would be overwritten by |
|
|
When proxied in a subdirectory, this base path is used during redirects. The actual web server’s base path is not affected. Would be overwritten by |
|
application
section
Defines customization options for texts, colors, images, URLs etc. within the application.
Property | Description | Default |
---|---|---|
|
Domain used for all user email addresses. |
|
|
Name as shown in title and menu bar. |
|
|
Filename in |
|
|
Filename in |
|
|
Name of the color theme used to render the UI. Options are |
|
|
Shows or hides the software version from the title. |
|
|
Shows or hides the "GitHub" button in the navigation and side bar as well as the info box about contributing on the Score Board. |
|
|
Enabled or disables the local backup feature for hacking progress and filters/settings on the Score Board. |
|
|
Represents the number of random user accounts to be created on top of the pre-defined ones (which are required for several challenges). |
|
|
Defines the name of the (fake) crypto currency that is offered on the Token Sale screen. |
|
|
The email address shown as contact in the Privacy Policy. |
|
|
Prefix for all custom Prometheus metrics. Must be a lowercase letter single world by Prometheus conventions. |
|
Specifies all characteristics of the bot answering user questions in the Support Chat. |
||
Specifies all social links embedded on various screens such as About Us or the Photo Wall. |
||
Defines custom elements on the Request Recycling Box page. |
||
Defines a dismissable welcome banner that can be shown when first visiting the application. |
||
Defines the cookie consent dialog shown in the bottom right corner. |
||
Defines the attributes for the |
||
Defines the attributes required for the |
||
Defines the customizations for the 3D-rendered planet easter egg. |
||
Defines the client identifier and allowed redirect URIs for Google OAuthintegration. |
chatBot
subsection
Specifies all characteristics of the bot answering user questions in the Support Chat.
Property | Description | Default |
---|---|---|
|
Name the chat bot introduces itself with. |
|
|
Initial greeting the chat bot uses when chatting with a user. |
|
|
Filename in |
|
|
Default response the chat bot uses when it could not understand the user’s actual question. |
|
|
Filename in |
|
social
subsection
Specifies all social links embedded on various screens such as About Us or the Photo Wall.
Property | Description | Default |
---|---|---|
|
URL used as the Twitter link promising coupon codes on the About Us and Your Basket screen. |
|
|
URL used as the Facebook link promising coupon codes on the About Us and Your Basket screen. |
|
|
URL used as the Slack link on the About Us screen. |
|
|
URL used as the link to logos and media files on the About Us screen. |
|
|
URL used as the link to a user questionnaire on the Score Board screen. |
|
recyclePage
subsection
Defines custom elements on the Request Recycling Box page.
Property | Description | Default |
---|---|---|
|
Filename in |
|
|
Filename in |
|
welcomeBanner
subsection
Defines a dismissable welcome banner that can be shown when first visiting the application.
Property | Description | Default |
---|---|---|
|
Shows or hides the banner. |
|
|
Defines the headline of the banner. |
|
|
Defines the body of the banner. Can contain arbitrary HTML. |
|
cookieConsent
subsection
Defines the cookie consent dialog shown in the bottom right corner.
Property | Description | Default |
---|---|---|
|
Color of the cookie banner itself. |
|
|
Color of the |
|
|
Defines the color of the button to dismiss the banner. |
|
|
Color of the |
|
|
Explains the cookie usage in the application. |
|
|
The text shown on the button to dismiss the banner. |
|
|
Caption of the link that is shown after the |
|
|
URL that provides further information about cookie usage. |
|
securityTxt
subsection
Defines the attributes for the security.txt
file based on the
https://securitytxt.org/ Internet draft.
Property | Description | Default |
---|---|---|
|
An email address, phone number or URL to report security vulnerabilities to. Can be fake obviously. |
|
|
URL to a public encryption key for secure communication. Can be fake obviously. |
|
|
URL a "hall of fame" page. Can be fake obviously. |
|
promotion
subsection
Defines the attributes required for the /promotion
screen where a
marketing video with subtitles is rendered that hosts the
XSS Tier 6
challenge.
Property | Description | Default |
---|---|---|
|
Name of a file with |
|
|
Name of a Web Video Text Tracks Format file in |
|
easterEggPlanet
subsection
Defines the customizations for the 3D-rendered planet easter egg.
Property | Description | Default |
---|---|---|
|
Name of the 3D planet "easter egg" as shown in the page title. |
|
|
Filename in |
|
googleOauth
subsection
Defines the client identifier and allowed redirect URIs for Google OAuth integration.
Property | Description | Default |
---|---|---|
|
Client identifier of the Google Cloud Platform application to handle OAuth 2.0 requests from OWASP Juice Shop. |
|
Sub-list for the redirect URIs authorized for Google OAuth. |
|
authorizedRedirects
sub-sequence
Defines the allowed redirect URIs and their optional proxy for Google OAuth integration.
Property | Description | Conditions | Default |
---|---|---|---|
|
URI authorized on Google Cloud Platform the Juice Shop is expected to be running on. |
mandatory |
|
|
Proxy URI authorized on Google Cloud Platform that will itself redirect back to the original |
optional |
|
challenges
section
Defines configuration options for the hacking challenges within the Juice Shop.
Property | Description | Default |
---|---|---|
|
Shows or hides all instant "challenge solved"-notifications. Recommended to set to |
|
|
Shows or hides hints for each challenge on hovering over/clicking its "unsolved" badge on the score board. |
|
|
Shows or hides a mitigation link for each solved challenge on the score board (if available). |
|
|
Shows or hides the associated Coding challenge button for each challenge (if available) on the score board. Can be |
|
|
Disables all Score Board filter options and hides those of the 103 challenges without a tutorial until all challenges with a tutorial have been solved. |
|
|
URL that should replace the original URL defined in |
|
|
This XSS payload is expected during the Bonus Payload challenge. |
|
|
Enables all potentially dangerous challenges regardless of any harm they might cause when running in a containerized environment. ☠️ Use at your own risk! |
|
|
Shows or hides like/dislike buttons for solved hacking & coding challenges that open an accordingly pre-filled Google Form. |
|
hackingInstructor
section
Allows enabling and customizing the Hacking Instructor tutorial mode.
Property | Description | Default |
---|---|---|
|
Shows or hides the Hacking Instructor links from the Score Board and Welcome Banner. |
|
|
Filename in |
|
products
sequence
List of product mappings which, when specified, replaces the entire list of default products.
Property | Description | Conditions | Default |
---|---|---|---|
|
Name of the product. |
mandatory |
|
|
Description of the product. |
optional |
|
|
Price of the product. |
optional |
A random price of 1-10 |
|
Price of the product for Deluxe Membership customers. |
optional |
Same as the regular price |
|
Available quantity of product in stock. |
optional |
Random quantity of 30-100 items |
|
Maximum purchase limit for regular customers. Does not apply to Deluxe Membership holders. |
optional |
|
|
Filename in |
optional |
|
|
Deletion date of the product in |
optional |
|
|
Sets the original link of the product which is the target for the Product Tampering challenge. Overrides |
must be defined on exactly one product |
|
|
Marks a product as the target for the "christmas special" challenge. Overrides |
must be |
|
|
Filename in |
must be defined on exactly one product |
|
|
List of keywords that are supposed to appear as EXIF properties on the image of the Retrieve Blueprint challenge product. ℹ️ Will be used in automatic testing for presence of the EXIF metadata but does not have any effect at runtime. |
must be defined on the product with |
|
|
List of keywords which are all mandatory to mention in a feedback or complaint to solve the Leaked Unsafe Product challenge. Overrides |
must be defined on exactly one product |
|
Sub-list which adds reviews to a product. |
optional |
|
memories
sequence
List which, when specified, replaces all default Photo Wall entries except a hard-coded one needed to solve the Retrieve the photo of Bjoern’s cat in "melee combat-mode" challenge.
Property | Description | Conditions |
---|---|---|
|
Filename in |
mandatory |
|
Text to show when hovering over the image or sending a Tweet about it. |
mandatory |
|
Reference by |
mandatory (exceptions see below) |
|
ID of the security question associated with the Meta Geo Stalking challenge. |
must be defined on exactly one memory together with |
|
Answer to the security question associated with the Meta Geo Stalking challenge. Should be retrievable via the meta data of the assosicated image. |
must be defined on exactly one memory together with |
|
ID of the security question associated with the Visual Geo Stalking challenge. |
must be defined on exactly one memory together with |
|
Answer to the security question associated with the Visual Geo Stalking challenge. Should be retrievable via some (not too obvious) visual clue in the assosicated image. |
must be defined on exactly one memory together with |
ctf
section
Section to enable and configure the Capture-the-Flag mode built into OWASP Juice Shop.
Property | Description | Default |
---|---|---|
|
Shows or hides the CTF flag codes in the "challenge solved"-notifications. Is ignored when |
|
|
Determines if the country (from |
|
List of mappings which associates challenges to countries on the challenge map of FBCTF. Only needed for CTFs using FBCTF. |
|
countryMapping
sub-mapping
List of mappings which associates challenges to countries on the challenge map of FBCTF. Only needed for CTFs using FBCTF:
-
Challenge
key
fromdata/static/challenges.yml
-
name
the name of the country -
code
the two-letter ISO code of the country
-
ℹ️ When specifying countryMapping
, it is mandatory to map all
challenges in order to produce a valid configuration file. It is
recommended to use config/fbctf.yml
as a template for that purpose.
Configuration example
server:
port: 3000
application:
domain: juice-sh.op
name: 'OWASP Juice Shop'
logo: JuiceShop_Logo.png
favicon: favicon_js.ico
theme: bluegrey-lightgreen
showVersionNumber: true
showGitHubLinks: true
localBackupEnabled: true
numberOfRandomFakeUsers: 0
altcoinName: Juicycoin
privacyContactEmail: donotreply@owasp-juice.shop
customMetricsPrefix: juiceshop
chatBot:
name: 'Juicy'
greeting: "Nice to meet you <customer-name>, I'm <bot-name>"
trainingData: 'botDefaultTrainingData.json'
defaultResponse: "Sorry I couldn't understand what you were trying to say"
avatar: 'JuicyChatBot.png'
social:
twitterUrl: 'https://twitter.com/owasp_juiceshop'
facebookUrl: 'https://www.facebook.com/owasp.juiceshop'
slackUrl: 'https://owasp.org/slack/invite'
redditUrl: 'https://www.reddit.com/r/owasp_juiceshop'
pressKitUrl: 'https://github.com/OWASP/owasp-swag/tree/master/projects/juice-shop'
questionnaireUrl: ~
recyclePage:
topProductImage: fruit_press.jpg
bottomProductImage: apple_pressings.jpg
welcomeBanner:
showOnFirstStart: true
title: 'Welcome to OWASP Juice Shop!'
message: "<p>Being a web application with a vast number of intended security vulnerabilities, 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 Worldwide 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='https://owasp-juice.shop' target='_blank'>https://owasp-juice.shop</a></h1>"
cookieConsent:
backgroundColor: '#546e7a'
textColor: '#ffffff'
buttonColor: '#558b2f'
buttonTextColor: '#ffffff'
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'
securityTxt:
contact: 'mailto:donotreply@owasp-juice.shop'
encryption: 'https://keybase.io/bkimminich/pgp_keys.asc?fingerprint=19c01cb7157e4645e9e2c863062a85a8cbfbdcda'
acknowledgements: '/#/score-board'
promotion:
video: JuiceShopJingle.mp4
subtitles: JuiceShopJingle.vtt
easterEggPlanet:
name: Orangeuze
overlayMap: orangemap2k.jpg
googleOauth:
clientId: '1005568560502-6hm16lef8oh46hr2d98vf2ohlnj4nfhq.apps.googleusercontent.com'
authorizedRedirects:
- { uri: 'https://demo.owasp-juice.shop' }
- { uri: 'https://juice-shop.herokuapp.com' }
- { uri: 'https://preview.owasp-juice.shop' }
- { uri: 'https://juice-shop-staging.herokuapp.com' }
- { uri: 'https://juice-shop.wtf' }
- { uri: 'http://localhost:3000', proxy: 'https://local3000.owasp-juice.shop' }
- { uri: 'http://127.0.0.1:3000', proxy: 'https://local3000.owasp-juice.shop' }
- { uri: 'http://localhost:4200', proxy: 'https://local4200.owasp-juice.shop' }
- { uri: 'http://127.0.0.1:4200', proxy: 'https://local4200.owasp-juice.shop' }
- { uri: 'http://192.168.99.100:3000', proxy: 'https://localmac.owasp-juice.shop' }
- { uri: 'http://192.168.99.100:4200', proxy: 'https://localmac.owasp-juice.shop' }
- { uri: 'http://penguin.termina.linux.test:3000', proxy: 'https://localchromeos.owasp-juice.shop' }
- { uri: 'http://penguin.termina.linux.test:4200', proxy: 'https://localchromeos.owasp-juice.shop' }
challenges:
showSolvedNotifications: true
showHints: true
showMitigations: true
codingChallengesEnabled: solved # Options: never solved always
restrictToTutorialsFirst: false
safetyOverride: false
overwriteUrlForProductTamperingChallenge: 'https://owasp.slack.com'
xssBonusPayload: '<iframe width="100%" height="166" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/771984076&color=%23ff5500&auto_play=true&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true"></iframe>'
hackingInstructor:
isEnabled: true
avatarImage: juicyBot.png
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 certificate and tests the SSL connection according given list of ciphers and various SSL configurations.'
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 tastiest 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 rare 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 it is so incredibly expensive despite its complete lack of purpose.'
price: 99.99
image: 3d_keychain.jpg
fileForRetrieveBlueprintChallenge: JuiceShop.stl
exifForBlueprintChallenge:
- OpenSCAD
# ~~~~~ ... ~~~~~~
memories:
-
image: 'magn(et)ificent!-1571814229653.jpg'
caption: 'Magn(et)ificent!'
user: bjoernGoogle
-
image: 'my-rare-collectors-item!-[̲̅$̲̅(̲̅-͡°-͜ʖ-͡°̲̅)̲̅$̲̅]-1572603645543.jpg'
caption: 'My rare collectors item! [̲̅$̲̅(̲̅ ͡° ͜ʖ ͡°̲̅)̲̅$̲̅]'
user: bjoernGoogle
ctf:
showFlagsInNotifications: false
showCountryDetailsInNotifications: none
countryMapping: ~
Overriding default settings
When creating your own YAML configuration file, you can rely on the
existing default values and only overwrite what you want to change. The
provided config/ctf.yml
file for capture-the-flag events for example
is as short as this:
application:
logo: JuiceShopCTF_Logo.png
favicon: favicon_ctf.ico
showVersionNumber: false
showGitHubLinks: false
welcomeBanner:
showOnFirstStart: false
challenges:
showHints: false
safetyOverride: true
hackingInstructor:
isEnabled: false
ctf:
showFlagsInNotifications: true
Testing customizations
You can validate your custom configuration file against the schema by
running npm run lint:config -- -f /path/to/myConfig.yml
. This
validation automatically happens on server startup as well.
To verify if your custom configuration will not break any of the
challenges, you should run the end-to-end tests via npm start & npm run cypress:open &
. If they pass, all challenges will be working fine!
Material Color Themes
The application.theme
property allows certain pre-defined color
schemes. The table below shows sample screenshots for each of these.
Theme | Sample screenshot |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
Provided customizations
The following fully re-themed customizations are provided out of the box by OWASP Juice Shop for demonstration purposes:
-
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! 🦊
-
AllDayDeflOps: This full conversion had its live debut at the All Day DevOps 2019 conference and was released the same day! 🎀
-
The BodgeIt Store: An homage to our server-side rendered ancestor. May it rest in JSPs! 💀
-
OWASP Juice Box: If you find jo͞osbäks much easier to pronounce than jo͞osSHäp, this customization is for you. 🧃
Furthermore these convenience customizations are provided out-of-the-box to simplify usage of OWASP Juice Shop in specific use cases and situations:
-
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. 🔇
-
Tutorial mode: Restricts the user to first solve all challenges with Hacking Instructor tutorials before the entire Score Board gets unlocked and filterable. 🏫 Hidden challenges can still be solved and users will receive corresponding success notifications!
-
Unsafe mode: Keeps everything at default settings except enabling all potentially dangerous challenges even in containerized environments. ☠️ Use at your own risk!
Proprietary customization
Below you find screenshots of a custom theme the author of this book created for awareness and demo sessions at work. It was presented to various groups and individuals, from Project Manager rounds over workers council members up to the company CEO at that time.
Limitations
-
When running a customization (except
default.yml
) that overwrites the propertyapplication.domain
, the description of the challenges Ephemeral Accountant, Forged Signed JWT and Unsigned JWT will always be shown in English. -
Configurations (except
default.yml
) do not support translation of custom product names and descriptions as of v15.1.0-SNAPSHOT. -
Several Hacking Instructor scripts depend on product inventory and product reviews that might not exist in the required form when you overwrote the default
products
list. Consider turning off the tutorials by settinghackingInstructor.isEnabled
tofalse
in that case.
Additional Browser tweaks
Consider you are doing a live demo with a highly customized corporate theme. Your narrative is, that this really is an upcoming eCommerce application of that company. Walking the "happy path" might now lure you into two situations which could spoil the immersion for the audience.
Coupon codes on social media
If you configured the twitterUrl
/facebookUrl
as the company’s own
account/page, you will most likely not find any coupon codes posted
there. You will probably fail to convince the social media team to tweet
or retweet some coupon code for an application that does not even exist!
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.
ℹ️ Since v10.0.0 you can overwrite the
googleOauth
subsection to use your own
application on Google Cloud Platform for handling OAuth. This is a
relatively high effort, so maybe you want to kill two birds with one
stone instead as described in the next section.
On-the-fly text replacement
You can solve both of the above problems in your own Browser by replacing text on the fly when the Twitter, Facebook or Google-Login page is loaded. For Chrome Word Replacer II is a plugin that does this work for you with very little setup effort. For Firefox FoxReplace does a similar job. After installing either plugin you have to create two text replacements:
-
Create a replacement for
OWASP Juice Shop
(as it appears on Google-Login) with your own application name. Best useapplication.name
from your configuration. -
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.
-
Enable the plugin and verify your replacements work: