juice-shop-ctf-cli
Advanced tools
Comparing version 5.0.2 to 6.0.0
@@ -1648,2 +1648,6 @@ { | ||
{ | ||
"category": "Difficulty 6", | ||
"protected": false | ||
}, | ||
{ | ||
"category": "None", | ||
@@ -1661,2 +1665,2 @@ "protected": true | ||
} | ||
} | ||
} |
10
index.js
@@ -10,6 +10,4 @@ const inquirer = require('inquirer') | ||
const generateCTFExport = require('./lib/generators/') | ||
const generateCtfExport = require('./lib/generators/') | ||
const ctfdCompatibleVersion = '1.1.x or 1.2.x' | ||
const argv = require('yargs') | ||
@@ -32,3 +30,3 @@ .option('config', { | ||
message: 'CTF framework to generate data for?', | ||
choices: [options.ctfdFramework, options.fbctfFramework], | ||
choices: [options.ctfd2Framework, options.ctfdFramework, options.fbctfFramework], | ||
default: 0 | ||
@@ -80,3 +78,3 @@ }, | ||
console.log() | ||
console.log('Generate ' + 'OWASP Juice Shop'.bold + ' challenge archive for setting up ' + options.ctfdFramework.bold + ' (' + ctfdCompatibleVersion + ') or ' + options.fbctfFramework.bold + ' score server') | ||
console.log('Generate ' + 'OWASP Juice Shop'.bold + ' challenge archive for setting up ' + options.ctfdFramework.bold + ', ' + options.ctfd2Framework.bold + ' or ' + options.fbctfFramework.bold + ' score server') | ||
@@ -94,3 +92,3 @@ try { | ||
await generateCTFExport(answers.ctfFramework || options.ctfdFramework, challenges, { | ||
await generateCtfExport(answers.ctfFramework || options.ctfdFramework, challenges, { | ||
insertHints: answers.insertHints, | ||
@@ -97,0 +95,0 @@ insertHintUrls: answers.insertHintUrls, |
@@ -7,3 +7,3 @@ const Promise = require('bluebird') | ||
function createCTFdExport (challenges, { insertHints, insertHintUrls, ctfKey }) { | ||
function createCtfdExport (challenges, { insertHints, insertHintUrls, ctfKey }) { | ||
function insertChallenge (data, challenge) { | ||
@@ -88,2 +88,2 @@ const score = calculateScore(challenge.difficulty) | ||
module.exports = createCTFdExport | ||
module.exports = createCtfdExport |
@@ -49,3 +49,3 @@ const Promise = require('bluebird') | ||
async function createFBCTFExport (challenges, { insertHints, insertHintUrls, ctfKey, countryMapping }) { | ||
async function createFbctfExport (challenges, { insertHints, insertHintUrls, ctfKey, countryMapping }) { | ||
const fbctfTemplate = await loadTemplate() | ||
@@ -93,2 +93,2 @@ | ||
module.exports = createFBCTFExport | ||
module.exports = createFbctfExport |
@@ -1,22 +0,36 @@ | ||
const writeToZipFile = require('../writeToZipFile') | ||
const writeToJsonFile = require('../writeToJsonFile') | ||
const writeToCtfdZip = require('../writeToCtfdZip') | ||
const writeToCtfd2Zip = require('../writeToCtfd2Zip') | ||
const writeToFbctfJson = require('../writeToFbctfJson') | ||
const options = require('../options') | ||
const createCTFdExport = require('./ctfd') | ||
const createFBCTFExport = require('./fbctf') | ||
const createCtfdExport = require('./ctfd') | ||
const createCtfd2Export = require('./ctfd2') | ||
const createFbctfExport = require('./fbctf') | ||
async function generateCTFExport (ctfFramework, challenges, settings) { | ||
switch (ctfFramework) { | ||
case options.ctfd2Framework: | ||
const ctfd2Data = await createCtfd2Export(challenges, settings) | ||
const ctfd2File = await writeToCtfd2Zip(ctfd2Data, settings.outputLocation) | ||
console.log('Backup archive written to ' + ctfd2File) | ||
console.log() | ||
console.log('You can dismiss the potential '.cyan + 'Internal Server Error'.italic + ' alert popup after import.'.cyan) | ||
console.log('Simply restart CTFd and set up CTF name and administrator credentials again.'.cyan) | ||
console.log() | ||
console.log('For a step-by-step guide to import the ZIP-archive into ' + 'CTFd 2.x'.bold + ', please refer to') | ||
console.log('https://bkimminich.gitbooks.io/pwning-owasp-juice-shop/content/part1/ctf.html#running-ctfd'.bold) | ||
break | ||
case options.ctfdFramework: | ||
const ctfdData = await createCTFdExport(challenges, settings) | ||
const ctfdFile = await writeToZipFile(ctfdData, settings.outputLocation) | ||
const ctfdData = await createCtfdExport(challenges, settings) | ||
const ctfdFile = await writeToCtfdZip(ctfdData, settings.outputLocation) | ||
console.log('Backup archive written to ' + ctfdFile) | ||
console.log() | ||
console.log('For a step-by-step guide to import the ZIP-archive into ' + 'CTFd'.bold + ', please refer to') | ||
console.log('For a step-by-step guide to import the ZIP-archive into ' + 'CTFd 1.x'.bold + ', please refer to') | ||
console.log('https://bkimminich.gitbooks.io/pwning-owasp-juice-shop/content/part1/ctf.html#running-ctfd'.bold) | ||
break | ||
case options.fbctfFramework: | ||
const fbctfData = await createFBCTFExport(challenges, settings) | ||
const fbctfFile = await writeToJsonFile(fbctfData, settings.outputLocation) | ||
const fbctfData = await createFbctfExport(challenges, settings) | ||
const fbctfFile = await writeToFbctfJson(fbctfData, settings.outputLocation) | ||
@@ -23,0 +37,0 @@ console.log('Full Game Export written to ' + fbctfFile) |
@@ -8,4 +8,5 @@ module.exports = { | ||
paidHintUrls: 'Paid hint URLs', | ||
ctfdFramework: 'CTFd', | ||
ctfdFramework: 'CTFd 1.x', | ||
ctfd2Framework: 'CTFd 2.x', | ||
fbctfFramework: 'FBCTF' | ||
} |
@@ -5,3 +5,3 @@ const yaml = require('js-yaml') | ||
const schema = Joi.object().keys({ | ||
ctfFramework: Joi.string().optional().valid(options.ctfdFramework, options.fbctfFramework), | ||
ctfFramework: Joi.string().optional().valid(options.ctfd2Framework, options.ctfdFramework, options.fbctfFramework), | ||
juiceShopUrl: [Joi.string().uri().required(), Joi.string().ip().required()], | ||
@@ -11,3 +11,3 @@ countryMapping: Joi.string().when('ctfFramework', { is: options.fbctfFramework, then: Joi.required(), otherwise: Joi.optional() }), | ||
insertHints: Joi.any().valid('none', 'free', 'paid').required(), | ||
insertHintUrls: Joi.any().valid('none', 'free', 'paid').when('ctfFramework', { is: options.ctfdFramework, then: Joi.required(), otherwise: Joi.optional() }) | ||
insertHintUrls: Joi.any().valid('none', 'free', 'paid').when('ctfFramework', { is: options.fbctfFramework, then: Joi.optional(), otherwise: Joi.required() }) | ||
}) | ||
@@ -32,3 +32,3 @@ | ||
result.insertHints = hintsMap[result.insertHints] | ||
result.insertHintUrls = hintsMap[result.insertHintUrls] | ||
result.insertHintUrls = result.insertHintUrls ? hintsMap[result.insertHintUrls] : 0 | ||
resolve(result) | ||
@@ -35,0 +35,0 @@ } |
{ | ||
"name": "juice-shop-ctf-cli", | ||
"version": "5.0.2", | ||
"version": "6.0.0", | ||
"description": "Capture-the-Flag (CTF) environment setup tools for OWASP Juice Shop", | ||
@@ -24,2 +24,3 @@ "author": "Bjoern Kimminich <bjoern.kimminich@owasp.org> (https://www.owasp.org/index.php/User:Bjoern_Kimminich)", | ||
"ctfd", | ||
"fbctf", | ||
"cli" | ||
@@ -57,3 +58,3 @@ ], | ||
"inquirer": "~6.2.0", | ||
"joi": "~14.2.0", | ||
"joi": "~14.3.1", | ||
"jssha": "~2.3.1", | ||
@@ -67,3 +68,3 @@ "js-yaml": "~3.12.0", | ||
"devDependencies": { | ||
"ava": "~1.0.1", | ||
"ava": "~1.1.0", | ||
"chai": "~4.2.0", | ||
@@ -70,0 +71,0 @@ "chai-as-promised": "~7.1.1", |
@@ -21,3 +21,4 @@ #  OWASP Juice Shop CTF [](https://www.owasp.org/index.php/OWASP_Project_Inventory#tab=Flagship_Projects) [](https://github.com/bkimminich/juice-shop-ctf/releases/latest) [](https://twitter.com/owasp_juiceshop) | ||
* [CTFd](https://ctfd.io/) | ||
* [CTFd 2.x](https://github.com/CTFd/CTFd/releases/latest) | ||
* [CTFd 1.x](https://ctfd.io/) | ||
([1.1.x](https://github.com/CTFd/CTFd/releases/tag/1.1.4) or [1.2.x](https://github.com/CTFd/CTFd/releases/tag/1.2.0)) | ||
@@ -50,8 +51,8 @@ * [FBCTF](https://github.com/facebook/fbctf) | ||
```yaml | ||
ctfFramework: CTFd | FBCTF | ||
ctfFramework: CTFd 2.x | CTFd 1.x | FBCTF | ||
juiceShopUrl: https://juice-shop.herokuapp.com | ||
ctfKey: https://raw.githubusercontent.com/bkimminich/juice-shop/master/ctf.key # can also be actual key instead URL | ||
countryMapping: https://raw.githubusercontent.com/bkimminich/juice-shop/master/config/fbctf.yml | ||
countryMapping: https://raw.githubusercontent.com/bkimminich/juice-shop/master/config/fbctf.yml # ignored for CTFd | ||
insertHints: none | free | paid | ||
insertHintUrls: none | free | paid | ||
insertHintUrls: none | free | paid # optional for FBCTF | ||
``` | ||
@@ -58,0 +59,0 @@ |
@@ -11,5 +11,6 @@ const chai = require('chai') | ||
const dateFormat = require('dateformat') | ||
const outputFile = 'OWASP_Juice_Shop.' + dateFormat(new Date(), 'yyyy-mm-dd') + '.CTFd.zip' | ||
const desiredCTFdOutputFile = './output.zip' | ||
const desiredFBCTFOutputFile = './output.json' | ||
const outputFile = 'OWASP_Juice_Shop.' + dateFormat(new Date(), 'yyyy-mm-dd') + '.CTFd2.zip' | ||
const desiredCtfdOutputFile = './output.zip' | ||
const desiredCtfd2OutputFile = './output2.zip' | ||
const desiredFbctfOutputFile = './output.json' | ||
const configFile = 'config.yml' | ||
@@ -29,7 +30,7 @@ const util = require('util') | ||
} | ||
if (fs.existsSync(desiredCTFdOutputFile)) { | ||
fs.unlinkSync(desiredCTFdOutputFile) | ||
if (fs.existsSync(desiredCtfd2OutputFile)) { | ||
fs.unlinkSync(desiredCtfd2OutputFile) | ||
} | ||
if (fs.existsSync(desiredFBCTFOutputFile)) { | ||
fs.unlinkSync(desiredFBCTFOutputFile) | ||
if (fs.existsSync(desiredFbctfOutputFile)) { | ||
fs.unlinkSync(desiredFbctfOutputFile) | ||
} | ||
@@ -86,5 +87,11 @@ } | ||
it('should generate a CTFd 1.x export when choosen', function () { | ||
this.timeout(TIMEOUT) | ||
return expect(run(juiceShopCtfCli, [DOWN, ENTER, ENTER, ENTER, ENTER, ENTER], 1500)).to | ||
.eventually.match(/CTF framework to generate data for\? CTFd 1.x/i) | ||
}) | ||
it('should generate a FBCTF export when choosen', function () { | ||
this.timeout(TIMEOUT) | ||
return expect(run(juiceShopCtfCli, [DOWN, ENTER, ENTER, ENTER, ENTER, ENTER], 1500)).to | ||
return expect(run(juiceShopCtfCli, [DOWN, DOWN, ENTER, ENTER, ENTER, ENTER, ENTER], 1500)).to | ||
.eventually.match(/CTF framework to generate data for\? FBCTF/i) | ||
@@ -143,7 +150,21 @@ }) | ||
this.timeout(TIMEOUT) | ||
return expect(execFile('npx', [juiceShopCtfCli[0], '--config', configFile, '--output', desiredCTFdOutputFile]) | ||
.then(() => fs.existsSync(desiredCTFdOutputFile))).to | ||
return expect(execFile('npx', [juiceShopCtfCli[0], '--config', configFile, '--output', desiredCtfd2OutputFile]) | ||
.then(() => fs.existsSync(desiredCtfd2OutputFile))).to | ||
.eventually.equal(true) | ||
}) | ||
it('should be possible to create a CTFd 1.x export with a config file', function () { | ||
fs.writeFileSync(configFile, ` | ||
ctfFramework: CTFd 1.x | ||
juiceShopUrl: https://juice-shop.herokuapp.com | ||
ctfKey: https://raw.githubusercontent.com/bkimminich/juice-shop/master/ctf.key | ||
insertHints: paid | ||
insertHintUrls: paid`) | ||
this.timeout(TIMEOUT) | ||
return expect(execFile('npx', [juiceShopCtfCli[0], '--config', configFile, '--output', desiredCtfdOutputFile]) | ||
.then(() => fs.existsSync(desiredCtfdOutputFile))).to | ||
.eventually.equal(true) | ||
}) | ||
it('should be possible to create a FBCTF export with a config file', function () { | ||
@@ -158,6 +179,6 @@ fs.writeFileSync(configFile, ` | ||
this.timeout(TIMEOUT) | ||
return expect(execFile('npx', [juiceShopCtfCli[0], '--config', configFile, '--output', desiredFBCTFOutputFile]) | ||
.then(() => fs.existsSync(desiredFBCTFOutputFile))).to | ||
return expect(execFile('npx', [juiceShopCtfCli[0], '--config', configFile, '--output', desiredFbctfOutputFile]) | ||
.then(() => fs.existsSync(desiredFbctfOutputFile))).to | ||
.eventually.equal(true) | ||
}) | ||
}) |
@@ -32,2 +32,11 @@ const Promise = require('bluebird') | ||
}) | ||
it('should log retrieval error to console', () => { | ||
fetchCountryMapping.__set__({ | ||
request () { | ||
return new Promise((resolve, reject) => { reject(new Error('Argh!')) }) | ||
} | ||
}) | ||
return expect(fetchCountryMapping('http://localh_%&$§rst:3000')).to.be.rejectedWith('Failed to fetch country mapping from API! Argh!') | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
888071
54
3366
176
6
+ Addedjoi@14.3.1(transitive)
- Removedjoi@14.2.0(transitive)
Updatedjoi@~14.3.1