https://www.owasp.org/index.php/OWASP_Juice_Shop_Project
TechUp Presentation by Björn Kimminich / @bkimminich
Chapter One
...is an intentionally insecure webapp written in Node.js, Express and AngularJS. It contains 43+ hacking challenges of varying difficulty tracked on a score board.
The Open Web Application Security Project 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.
Translating "dump" or "useless outfit" into German yields "Saftladen" which can be reverse-translated word by word into "juice shop". Hence the project name.
That the initials "JS" match with those of "Javascript" was purely coincidental!
Javascript all the way from UI to REST API
...is a commandline tool written in Node.js and published on NPM.js. It helps you to set up and host CTF events on the CTFd platform with the Juice Shop challenges.
A Capture the Flag is a special kind of information security competition. Jeopardy-style CTFs have a couple of questions (tasks) in range of categories. For example, Web, Forensic, Crypto, Binary or something else. Teams can gain some points for every solved task.
All participants use individual Juice Shop instances anywhere, sharing only the flag code-ctfKey
and a central score server.
Run juice-shop-ctf
on the command line and let a wizard create SQL statements to apply to CTFd's database
Chapter One+
Since its move into the OWASP project portfolio in September 2016, Juice Shop is increasingly used, cloned, forked & contributed to:
OWASP Juice Shop is supposed to reliably fulfill the demands of:
And last but not least...
If you publish 🍝-code as open source, why should anyone believe you'll do any better in your daily work?
Chapter Two
An empty or lackluster front-page radiates the impression that nobody takes serious care of the project.
Open issues pile up in the ticketing system, most of them unanswered and unattended.
Pull Requests are routinely ignored or flogged to death.
https://bkimminich.gitbooks.io/pwning-owasp-juice-shop/content/part3/contribution.html
The Semantic Versioning syntax (MAJOR.MINOR.PATCH
) is used while its semantics are not adhered to.
Not even the original author thinks that the project is mature enough to release a 1.x version from it.
z85-cli
(😜)Chapter Three
The master
branch stores the official release history, while development happens on the develop
branch.
Suprise, surprise!
'use strict'
var path = require('path')
var utils = require('../lib/utils')
var challenges = require('../data/datacache').challenges
exports = module.exports = function servePremiumContent () {
return function (req, res) {
if (utils.notSolved(challenges.premiumPaywallChallenge)) {
utils.solve(challenges.premiumPaywallChallenge)
}
res.sendFile(path.resolve(__dirname, '../app/private/under-construction.gif'))
}
}
fs.copy('app/index.template.html', 'app/index.html', {overwrite: true}, function () {
if (config.get('application.logo')) {
var logo = config.get('application.logo')
if (utils.startsWith(logo, 'http')) {
var logoPath = logo
logo = decodeURIComponent(logo.substring(logo.lastIndexOf('/') + 1))
utils.downloadToFile(logoPath, 'app/public/images/' + logo)
}
var logoImageTag = '
'
replace({ regex: /
/, replacement: logoImageTag, paths: ['app/index.html'], recursive: false, silent: true })
}
if (config.get('application.theme')) {
var themeCss = 'bower_components/bootswatch/' + config.get('application.theme') + '/bootstrap.min.css'
replace({ regex: /bower_components\/bootswatch\/.*\/bootstrap\.min\.css/, replacement: themeCss, paths: ['app/index.html'], recursive: false, silent: true })
}
})
...it's still Javascript at the end of the day! (🤐)
it('should hold anonymous placeholder for email if current user is not logged in',
inject(function () {
$httpBackend.whenGET('/rest/user/whoami').respond(200, {user: {}})
$httpBackend.flush()
expect(scope.userEmail).toBe('anonymous')
})
)
frisby.create('GET security question returns nothing for an unknown email address')
.get(REST_URL + '/user/security-question?email=horst@unknown-us.er')
.expectStatus(200)
.expectJSON({})
.toss()
frisby.create('DELETE existing product is forbidden via public API')
.delete(API_URL + '/Products/1')
.expectStatus(401)
.toss()
describe('challenge "loginAdmin"', function () {
it('should log in Admin with SQLI attack on email field using "\' or 1=1--"', function () {
email.sendKeys('\' or 1=1--')
password.sendKeys('a')
loginButton.click()
expect(browser.getLocationAbsUrl()).toMatch(/\/search/)
})
protractor.expect.challengeSolved({challenge: 'Login Admin'})
})
protractor.expect = {
challengeSolved: function (context) {
describe('(shared)', function () {
beforeEach(function () {
browser.get('/#/score-board')
})
it("challenge '" + context.challenge + "' must be solved on score board", function () {
expect(element(by.id(context.challenge + '.solved')).getAttribute('class'))
.not.toMatch('ng-hide')
expect(element(by.id(context.challenge + '.notSolved')).getAttribute('class'))
.toMatch('ng-hide')
})
})
}
}
Having all tests pass after a commit means, it's safe to merge PRs or publish a new release!
Juice Shop | CTF Extension |
---|---|
Reality check: Do your tests actually test stuff?
Juice Shop | CTF Extension |
---|---|
92%* |
98% |
Chapter undefined
v4.2.0
on GitHub✔️git checkout master
✔️git merge develop
✔️git tag v4.2.0 -s -m "v4.2.0"
git push --follow-tags
Chapter 3 (continued)
And now for the most important metric of all...
The number of team members that would have to be run over by a truck to effectively kill the project.
For us as a logistics company this 🚚=💀 metaphor sucks...
So, let's change the metaphor into...
The number of team members that would have to leave for permanent vacation on Hawaii to effectively retire the project.
The term "Hawaii Factor" was (to my knowledge) first proposed by Timo Pagel at AppSecEU 2017 in Belfast.Meaning: If the whole team leaves, a new developer can take over and would be able to maintain & continue working on the project!
Chapter 4.1
The front-page is overcrowded with (mostly useless) information and status badges.
Fail to maintain the same information & documentation in multiple places consistently.
✔️✔️❌✔️❌✔️. With no code changes in between.
I wonder how our Live Release is doing...
Some services might be free of charge for OSS projects but come with some other hidden costs or annoyance.
Not giving enough credit to contributors.
git commit
s are not everything!Not to forget some very unique contributions...
by Laura Kimminich
How to counter "Contributor Laurels" antipattern?
for small contributions & to give out at events like this one
for larger or regular contributions
Chapter NaN
if (buildOutcome === '😎') { // show the following text
One last manual step later...
} else {
/* skip this and the next slide */
}
Created with reveal.js - The HTML Presentation Framework