Skip to content

Commit

Permalink
added easter egg challenge
Browse files Browse the repository at this point in the history
  • Loading branch information
bkimminich committed Oct 2, 2014
1 parent bb67949 commit 1738708
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 9 deletions.
6 changes: 5 additions & 1 deletion app/js/controllers/ChallengeController.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
angular.module('myApp').controller('ChallengeController', [
'$scope',
'$sce',
'ChallengeService',
function ($scope, challengeService) {
function ($scope, $sce, challengeService) {
'use strict';

challengeService.find().success(function (data) {
$scope.challenges = data.data;
for (var i=0; i<$scope.challenges.length; i++) {
$scope.challenges[i].description = $sce.trustAsHtml($scope.challenges[i].description);
}
}).error(function (data) {
console.log(data);
});
Expand Down
14 changes: 14 additions & 0 deletions app/public/ftp/eastere.gg
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"Congratulations, you found the easter egg!"
- The incredibly funny developers

...

...

...

Oh' wait, this isn't an easter egg at all! It's just a boring text file! The real easter egg can be found here:

<some cypher>

Good luck, egg hunter!
2 changes: 1 addition & 1 deletion app/views/ScoreBoard.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ <h3 class="page-header page-header-sm">Score Board</h3>
<th></th>
</tr>
<tr data-ng-repeat="challenge in challenges">
<td>{{challenge.description}}</td>
<td><div ng-bind-html="challenge.description"></div></td>
<td>
<svg ng-show="!challenge.solved" xmlns="http:https://www.w3.org/2000/svg" width="102" height="18"><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-opacity=".3"/><stop offset="1" stop-opacity=".5"/></linearGradient><rect rx="4" width="102" height="18" fill="#555"/><rect rx="4" x="64" width="38" height="18" fill="#e05d44"/><path fill="#e05d44" d="M64 0h4v18h-4z"/><rect rx="4" width="102" height="18" fill="url(#a)"/><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="33" y="14" fill="#010101" fill-opacity=".3">challenge</text><text x="33" y="13">challenge</text><text x="82" y="14" fill="#010101" fill-opacity=".3">open</text><text x="82" y="13">open</text></g></svg>
<svg ng-show="challenge.solved" xmlns="http:https://www.w3.org/2000/svg" width="111" height="18"><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-opacity=".3"/><stop offset="1" stop-opacity=".5"/></linearGradient><rect rx="4" width="111" height="18" fill="#555"/><rect rx="4" x="64" width="47" height="18" fill="#4c1"/><path fill="#4c1" d="M64 0h4v18h-4z"/><rect rx="4" width="111" height="18" fill="url(#a)"/><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="33" y="14" fill="#010101" fill-opacity=".3">challenge</text><text x="33" y="13">challenge</text><text x="86.5" y="14" fill="#010101" fill-opacity=".3">solved</text><text x="86.5" y="13">solved</text></g></svg>
Expand Down
26 changes: 25 additions & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,28 @@ function queryResultToJson(data, status) {
data: wrappedData
};
}
exports.queryResultToJson = queryResultToJson;
exports.queryResultToJson = queryResultToJson;

function startsWith(str, prefix) {
return str.indexOf(prefix) === 0;
}
exports.startsWith = startsWith;

function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
exports.endsWith = endsWith;

function contains(str, element) {
return str.indexOf(element) !== -1;
}
exports.contains = contains;

function cutOffPoisonNullByte(str) {
var nullByte = '%00';
if (contains(str, nullByte)) {
return str.substring(0, str.indexOf(nullByte));
}
return str;
}
exports.cutOffPoisonNullByte = cutOffPoisonNullByte;
44 changes: 38 additions & 6 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ var Challenge = sequelize.define('Challenges', {
});

/* Challenges */
var redirectChallenge;
var redirectChallenge, easterEggLevelOneChallenge, easterEggLevelTwoChallenge;

/* Data */
sequelize.drop();
Expand All @@ -77,6 +77,20 @@ sequelize.sync().success(function () {
}).success(function(challenge) {
redirectChallenge = challenge;
});
Challenge.create({
description: 'Find the hidden <a href="http:https://en.wikipedia.org/wiki/Easter_egg_(media)" target="_blank">easter egg</a>.',
link: 'https://www.owasp.org/index.php/Top_10_2013-A7-Missing_Function_Level_Access_Control',
solved: false
}).success(function(challenge) {
easterEggLevelOneChallenge = challenge;
});
Challenge.create({
description: 'Find <i>the real</i> easter egg.',
link: 'https://www.owasp.org/index.php/Top_10_2013-A6-Sensitive_Data_Exposure',
solved: false
}).success(function(challenge) {
easterEggLevelTwoChallenge = challenge;
});
User.create({
email: '[email protected]',
password: utils.hash('admin123')
Expand Down Expand Up @@ -121,7 +135,7 @@ sequelize.sync().success(function () {
});
Product.create({
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. <a href="https://www.owasp.org/index.php/O-Saft">More...</a>',
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. <a href="https://www.owasp.org/index.php/O-Saft" target="_blank">More...</a>',
price: 0.01,
image: 'owasp_osaft.jpg'
});
Expand Down Expand Up @@ -150,7 +164,26 @@ sequelize.sync().success(function () {
});
});

/* Favicon */
app.use(favicon(__dirname + '/app/public/favicon.ico'));

/* public/ftp directory browsing and file download */
app.use('/public/ftp', serveIndex('app/public/ftp', {'icons': true}));
app.use('/public/ftp/:file', function(req, res, next) {
var file = req.params.file;
console.log(file);
if (file && (utils.endsWith(file, '.md') || (utils.endsWith(file, '.txt')))) {
file = utils.cutOffPoisonNullByte(file);
if (file.toLowerCase() === 'eastere.gg') {
solve(easterEggLevelOneChallenge);
}
res.sendFile(__dirname + '/app/public/ftp/' + file);
} else {
res.status(403);
next('Only .md and .txt files are allowed!');
}
});

app.use(express.static(application_root + '/app'));
app.use(morgan('combined'));
app.use(cookieParser(secret));
Expand Down Expand Up @@ -178,7 +211,7 @@ app.post('/api/Products', expressJwt({secret: secret}));
//app.put('/api/Products/:id', expressJwt({secret: secret})); // = missing function-level access control vulnerability
app.delete('/api/Products/:id', expressJwt({secret: secret}));

/* Challenges: GET list of challenges allowed. Everything else forbidden independent of authorization */
/* Challenges: GET list of challenges allowed. Everything else forbidden independent of authorization (hence the random secret) */
app.post('/api/Challenges', expressJwt({secret: Math.random()}));
app.use('/api/Challenges/:id', expressJwt({secret: Math.random()}));

Expand Down Expand Up @@ -225,13 +258,12 @@ app.get('/rest/basket/:id', function(req, res, next){
});

/* Static Resources */
app.use('/public/ftp', serveIndex('app/public/ftp', {'icons': true}));

app.get('/redirect', function(req, res) {
var to = req.query.to;
var githubUrl = 'https://github.com/bkimminich/juice-shop';
if (to.indexOf(githubUrl) > -1) {
if (to !== githubUrl) {
if (to !== githubUrl) { // TODO Instead match against something like <anotherUrl>[?&]=githubUrl
solve(redirectChallenge);
}
res.redirect(to);
Expand All @@ -241,7 +273,7 @@ app.get('/redirect', function(req, res) {
});

app.use(function (req, res, next) {
if (req.url.indexOf('/api') !== 0 && req.url.indexOf('/rest') !== 0) {
if (!utils.startsWith(req.url, '/api') && !utils.startsWith(req.url, '/rest') && !utils.startsWith(req.url, '/public')) {
res.sendFile(__dirname + '/app/index.html');
} else {
next();
Expand Down

0 comments on commit 1738708

Please sign in to comment.