Skip to content

Commit

Permalink
add metrics challenge and sign commits
Browse files Browse the repository at this point in the history
Signed-off-by: Scar26 <mmatty26@gmail.com>
  • Loading branch information
Scar26 committed Feb 11, 2020
1 parent fc28661 commit 1f03945
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 0 deletions.
5 changes: 5 additions & 0 deletions config.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -598,3 +598,8 @@ ctf:
type: string
code:
type: string
exposedMetricsChallenge:
name:
type: string
code:
type: string
3 changes: 3 additions & 0 deletions config/fbctf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,6 @@ ctf:
svgInjectionChallenge:
name: Tunisia
code: TN
exposedMetricsChallenge:
name: Japan
code: JP
8 changes: 8 additions & 0 deletions data/static/challenges.yml
Original file line number Diff line number Diff line change
Expand Up @@ -763,3 +763,11 @@
hint: 'This challenge would formally have to be in several categories as the developers made multiple gaffes for this to be possible.'
hintUrl: 'https://pwning.owasp-juice.shop/part2/injection.html#stick-cute-cross-domain-kittens-all-over-our-delivery-boxes'
key: svgInjectionChallenge
-
name: 'Exposed Metrics'
category: 'Sensitive Data Exposure'
description: 'Find the Metrics endpoint serving usage metrics to be scraped by Prometheus'
difficulty: 1
hint: 'Try to guess what URL the endpoint might have'
hintUrl: ''
key: exposedMetricsChallenge
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
"otplib": "^11.0.1",
"pdfkit": "^0.11.0",
"portscanner": "^2.2.0",
"prom-client": "^11.5.3",
"pug": "^2.0.4",
"replace": "^1.1.3",
"request": "^2.88.0",
Expand Down
57 changes: 57 additions & 0 deletions routes/metrics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2014-2020 Bjoern Kimminich.
* SPDX-License-Identifier: MIT
*/

const Prometheus = require('prom-client')
const orders = require('../data/mongodb').orders
const challenges = require('../data/datacache').challenges
const users = require('../data/datacache').users
const utils = require('../lib/utils')

exports.serveMetrics = function serveMetrics (reg) {
return (req, res, next) => {
utils.solveIf(challenges.exposedMetricsChallenge, () => (true))
res.set('Content-Type', reg.contentType)
res.end(reg.metrics())
}
}

exports.observeMetrics = function observeMetrics () {
const register = new Prometheus.Registry()
const intervalCollector = Prometheus.collectDefaultMetrics({ timeout: 5000, register })
register.setDefaultLabels({ app: 'juice-shop' })

const orderMetrics = new Prometheus.Gauge({
name: 'juice_shop_orders_placed_total',
help: 'Number of orders placed in juice-shop so far'
})

const challengeMetrics = new Prometheus.Gauge({
name: 'juice_shop_challenges_solved_total',
help: 'Number of challenges that have been solved so far'
})

const userMetrics = new Prometheus.Gauge({
name: 'juice_shop_users_registered_total',
help: 'Number of users registered'
})

register.registerMetric(orderMetrics)
register.registerMetric(challengeMetrics)
register.registerMetric(userMetrics)

const updateLoop = setInterval(() => {
orders.count({}).then(function (orders) {
orderMetrics.set(orders)
})
challengeMetrics.set(Object.keys(challenges).filter((key) => (challenges[key].solved)).length)
userMetrics.set(Object.keys(users).length)
}, 5000)

return {
register: register,
probe: intervalCollector,
updateLoop: updateLoop
}
}
7 changes: 7 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const restoreProgress = require('./routes/restoreProgress')
const fileServer = require('./routes/fileServer')
const keyServer = require('./routes/keyServer')
const logFileServer = require('./routes/logfileServer')
const metrics = require('./routes/metrics')
const authenticatedUsers = require('./routes/authenticatedUsers')
const currentUser = require('./routes/currentUser')
const login = require('./routes/login')
Expand Down Expand Up @@ -341,6 +342,11 @@ app.post('/rest/2fa/disable',
insecurity.isAuthorized(),
twoFactorAuth.disable()
)
/* Serve metrics */
const Metrics = metrics.observeMetrics()
const metricsRegister = Metrics.register
const metricsUpdateLoop = Metrics.updateLoop
app.get('/metrics', metrics.serveMetrics(metricsRegister))

/* Verifying DB related challenges can be postponed until the next request for challenges is coming via finale */
app.use(verify.databaseRelatedChallenges())
Expand Down Expand Up @@ -532,6 +538,7 @@ exports.start = async function (readyCallback) {

exports.close = function (exitCode) {
if (server) {
clearInterval(metricsUpdateLoop)
server.close()
}
if (exitCode !== undefined) {
Expand Down
18 changes: 18 additions & 0 deletions test/api/metricsAPISpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2014-2020 Bjoern Kimminich.
* SPDX-License-Identifier: MIT
*/

const frisby = require('frisby')
const METRICS_URL = 'http://localhost:3000/metrics/'

describe('Metrics API', () => {
it('check if /metrics endpoint is accessible', () => {
return frisby.get(METRICS_URL)
.expect('status', 200)
.expect('header', 'content-type', /text\/plain/)
.expect('bodyContains', /^juice_shop_users_registered_total{app="juice-shop"} [0-9]*$/)
.expect('bodyContains', /^juice_shop_challenges_solved_total{app="juice-shop"} [0-9]*$/)
.expect('bodyContains', /^juice_shop_orders_placed_total{app="juice-shop"} [0-9]*$/)
})
})
16 changes: 16 additions & 0 deletions test/e2e/metricsSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { describe } from 'mocha'

/*
* Copyright (c) 2014-2020 Bjoern Kimminich.
* SPDX-License-Identifier: MIT
*/

describe('/metrics/', () => {
describe('challenge "exposedMetrics"', () => {
it('Challenge is solved on accesing the api/metrics route', () => {
browser.get('/api/metrics')
})

protractor.expect.challengeSolved({ challenge: 'Exposed Metrics' })
})
})

0 comments on commit 1f03945

Please sign in to comment.