https://www.owasp.org/index.php/OWASP_Juice_Shop_Project
Presentation by Bjรถrn Kimminich / @bkimminich
Chapter One
...is an intentionally insecure webapp written in Node.js, Express and AngularJS. It contains 38+ hacking challenges of varying difficulty tracked on a score board.
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.
<!-- uncomment this and the following slide **ONLY** if...
------------------------------------------------- -->
<!-- ...Juice Shop got promoted to Lab Project
during the Project Summit prior to this AppSecEU! :-D
The next OWASP Connector should make this official! (But you heard it here first!)
------------------------------------------------- -->
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://github.com/bkimminich/juice-shop/blob/master/CONTRIBUTING.md
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.
'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 password change without passing any passwords')
.get(REST_URL + '/user/change-password')
.expectStatus(401)
.expectBodyContains('Password cannot be empty')
.toss()
No-idea-why-this-๐ฉ-happens-snippet-injection Vulnerability: Did anyone notice how above code was totally butchered by highlight.js
beginning at the opening single quote in line 1?
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 + "' should 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
Chapter 3 (continued)
And now for the most important metric of all...
The number of team members that would have to leave the project to effectively kill it.
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.
โ๏ธโ๏ธโโ๏ธโโ๏ธ. 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!Chapter NaN
Created with reveal.js - The HTML Presentation Framework