Skip to content

Commit

Permalink
Move /ftp folder out of /app/public
Browse files Browse the repository at this point in the history
(fixes #124)
  • Loading branch information
bkimminich committed Sep 4, 2016
1 parent 6c3e85e commit 0641a18
Show file tree
Hide file tree
Showing 9 changed files with 26 additions and 18 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion routes/fileServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ exports = module.exports = function servePublicFiles() {
} else if (utils.notSolved(challenges.forgottenBackupChallenge) && (file.toLowerCase() === 'coupons_2013.md.bak' || file.toLowerCase() === 'package.json.bak')) {
utils.solve(challenges.forgottenBackupChallenge);
}
res.sendFile(path.resolve(__dirname + '/../app/public/ftp/' + file));
res.sendFile(path.resolve(__dirname + '/../ftp/' + file));
} else {
res.status(403);
next(new Error('Only .md and .pdf files are allowed!'));
Expand Down
2 changes: 1 addition & 1 deletion routes/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exports = module.exports = function placeOrder() {
var orderNo = insecurity.hash(new Date() + '_' + id);
var pdfFile = 'order_' + orderNo + '.pdf';
var doc = new PDFDocument();
var fileWriter = doc.pipe(fs.createWriteStream(__dirname + '/../app/public/ftp/' + pdfFile));
var fileWriter = doc.pipe(fs.createWriteStream(__dirname + '/../ftp/' + pdfFile));

doc.text('Juice-Shop - Order Confirmation');
doc.moveDown();
Expand Down
7 changes: 3 additions & 4 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var application_root = __dirname.replace(/\\/g, '/'),
errorhandler.title = 'Juice Shop (Express ' + utils.version('express') + ')';

/* Delete old order PDFs */
glob(__dirname + '/app/public/ftp/*.pdf', function (err, files) {
glob(__dirname + '/ftp/*.pdf', function (err, files) {
files.forEach(function(filename) {
fs.unlink(filename);
});
Expand All @@ -62,10 +62,9 @@ app.use(favicon(__dirname + '/app/public/favicon_v2.ico'));
/* Checks for solved challenges */
app.use('/public/images/tracking', verify.accessControlChallenges());

/* public/ftp directory browsing and file download */
app.use('/ftp', serveIndex('app/public/ftp', {'icons': true}));
/* /ftp directory browsing and file download */
app.use('/ftp', serveIndex('ftp', {'icons': true}));
app.use('/ftp/:file', fileServer());
app.use('/public/ftp/:file', fileServer());

app.use(express.static(application_root + '/app'));
app.use(morgan('dev'));
Expand Down
33 changes: 21 additions & 12 deletions test/server/fileServingSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,65 +58,70 @@ frisby.create('GET existing file /ftp/package.json.bak will return a 403 error f
frisby.create('GET the confidential file in /ftp')
.get(URL + "/ftp/acquisitions.md")
.expectStatus(200)
.expectBodyContains('# Planned Acquisitions')
.toss();

frisby.create('GET the easter egg file by using an encoded Poison Null Byte attack with .pdf suffix')
.get(URL + "/ftp/eastere.gg%2500.pdf")
.expectStatus(200)
.expectBodyContains('Congratulations, you found the easter egg!')
.toss();

frisby.create('GET the easter egg file by using an encoded Poison Null Byte attack with .md suffix')
.get(URL + "/ftp/eastere.gg%2500.md")
.expectStatus(200)
.expectBodyContains('Congratulations, you found the easter egg!')
.toss();

frisby.create('GET the 2013 coupon code file by using an encoded Poison Null Byte attack with .pdf suffix')
.get(URL + "/ftp/coupons_2013.md.bak%2500.pdf")
.expectStatus(200)
.expectBodyContains('n<MibgC7sn')
.toss();

frisby.create('GET the 2013 coupon code file by using an encoded Poison Null Byte attack with .md suffix')
.get(URL + "/ftp/coupons_2013.md.bak%2500.md")
.expectStatus(200)
.expectBodyContains('n<MibgC7sn')
.toss();

frisby.create('GET the package.json file by using an encoded Poison Null Byte attack with .pdf suffix')
.get(URL + "/ftp/package.json.bak%2500.pdf")
.expectStatus(200)
.expectBodyContains('"name": "juice-shop",')
.toss();

frisby.create('GET the package.json file by using an encoded Poison Null Byte attack with .md suffix')
.get(URL + "/ftp/package.json.bak%2500.md")
.expectStatus(200)
.toss();

frisby.create('GET a restricted file directly from file system path on server via Poison Null Byte attack')
.get(URL + "/public/ftp/package.json.bak%2500.md")
.expectStatus(200)
.expectBodyContains('"name": "juice-shop",')
.toss();

frisby.create('GET a restricted file directly from file system path on server by tricking route definitions fails with 403 error')
.get(URL + "/ftp///eastere.gg")
.expectStatus(403)
.toss();

frisby.create('GET a restricted file directly from file system path on server via Directory Traversal attack')
.get(URL + "/public/images/../ftp/eastere.gg")
frisby.create('GET a restricted file directly from file system path on server via Directory Traversal attack loads index.html instead')
.get(URL + "/public/images/../../ftp/eastere.gg")
.expectStatus(200)
.expectBodyContains('<h1 class="hidden">OWASP Juice Shop</h1>')
.toss();

frisby.create('GET a restricted file directly from file system path on server via URL-encoded Directory Traversal attack')
.get(URL + "/public/images/%2e%2e%2fftp/eastere.gg")
frisby.create('GET a restricted file directly from file system path on server via URL-encoded Directory Traversal attack loads index.html instead')
.get(URL + "/public/images/%2e%2e%2f%2e%2e%2fftp/eastere.gg")
.expectStatus(200)
.expectBodyContains('<h1 class="hidden">OWASP Juice Shop</h1>')
.toss();

frisby.create('GET an accessible file directly from file system path on server')
.get(URL + "/public/ftp/legal.md")
.get(URL + "/ftp/legal.md")
.expectStatus(200)
.expectBodyContains('# Legal Information')
.toss();

frisby.create('GET a non-existing file via direct server file path /public/ftp will return a 404 error')
.get(URL + "/public/ftp/doesnotexist.md")
frisby.create('GET a non-existing file via direct server file path /ftp will return a 404 error')
.get(URL + "/ftp/doesnotexist.md")
.expectStatus(404)
.toss();

Expand All @@ -130,19 +135,23 @@ frisby.create('GET the second easter egg by visiting the hidden URL')
frisby.create('GET Geocities theme CSS is accessible directly from file system path')
.get(URL + "/css/geo-bootstrap/swatch/bootstrap.css")
.expectStatus(200)
.expectBodyContains('Designed and built with all the love in the world @twitter by @mdo and @fat.')
.toss();

frisby.create('GET tracking image for "Score Board" page access challenge')
.get(URL + "/public/images/tracking/scoreboard.png")
.expectStatus(200)
.expectHeaderContains('content-type', 'image/png')
.toss();

frisby.create('GET tracking image for "Administration" page access challenge')
.get(URL + "/public/images/tracking/administration.png")
.expectStatus(200)
.expectHeaderContains('content-type', 'image/png')
.toss();

frisby.create('GET tracking background image for "Geocities Theme" challenge')
.get(URL + "/public/images/tracking/microfab.gif")
.expectStatus(200)
.expectHeaderContains('content-type', 'image/gif')
.toss();

0 comments on commit 0641a18

Please sign in to comment.