Skip to content

Commit 2a40503

Browse files
committed
Merge remote-tracking branch 'origin/develop' into develop
# Conflicts: # README.md
2 parents cf4089e + b2d7d12 commit 2a40503

File tree

6 files changed

+123
-253
lines changed

6 files changed

+123
-253
lines changed

lib/generators/ctfd.js

+43-97
Original file line numberDiff line numberDiff line change
@@ -5,117 +5,63 @@
55

66
const Promise = require('bluebird')
77
const calculateScore = require('../calculateScore')
8-
const calculateHintCost = require('../calculateHintCost')
8+
// const calculateHintCost = require('../calculateHintCost')
99
const hmacSha1 = require('../hmac')
1010
const options = require('../options')
1111

1212
function createCtfdExport (challenges, { insertHints, insertHintUrls, insertHintSnippets, ctfKey, vulnSnippets }) {
13-
function insertChallenge (data, challenge) {
14-
const score = calculateScore(challenge.difficulty)
15-
challenge.description = challenge.description.replace('`xss`', '`xss`')
16-
data.challenges.results.push(
17-
{
18-
id: challenge.id,
19-
name: challenge.name,
20-
description: challenge.description + ' (Difficulty Level: ' + challenge.difficulty + ')',
21-
max_attempts: 0,
22-
value: score,
23-
category: challenge.category,
24-
type: 'standard',
25-
state: 'visible',
26-
next_id: null // TODO Use "tutorialOrder" to recommend order of first challenges; leave null for rest
27-
}
28-
)
29-
}
30-
31-
function insertKey ({ flagKeys }, { id, name }) {
32-
flagKeys.results.push(
33-
{
34-
id,
35-
challenge_id: id,
36-
type: 'static',
37-
content: hmacSha1(ctfKey, name),
38-
data: null
39-
}
40-
)
41-
}
42-
43-
function insertTextHint ({ hints }, challenge) {
44-
hints.results.push(
45-
{
46-
id: challenge.id,
47-
type: 'standard',
48-
challenge_id: challenge.id,
49-
content: challenge.hint,
50-
cost: calculateHintCost(challenge, insertHints)
51-
}
52-
)
53-
}
54-
55-
function insertHintUrl ({ hints }, challenge, hasTextHintPrerequisite) {
56-
hints.results.push(
57-
{
58-
id: 10000 + challenge.id,
59-
type: 'standard',
60-
challenge_id: challenge.id,
61-
content: challenge.hintUrl,
62-
cost: calculateHintCost(challenge, insertHintUrls),
63-
requirements: hasTextHintPrerequisite ? { prerequisites: [challenge.id] } : null
64-
}
65-
)
66-
}
67-
68-
function insertHintSnippet ({ hints }, challenge, snippet, hasTextHintPrerequisite, hasHintUrlPrerequisite) {
69-
hints.results.push(
70-
{
71-
id: 20000 + challenge.id,
72-
type: 'standard',
73-
challenge_id: challenge.id,
74-
content: '<pre><code>' + snippet + '</code></pre>',
75-
cost: calculateHintCost(challenge, insertHintSnippets),
76-
requirements: hasTextHintPrerequisite ? (hasHintUrlPrerequisite ? { prerequisites: [challenge.id, 10000 + challenge.id] } : { prerequisites: [challenge.id] }) : (hasHintUrlPrerequisite ? { prerequisites: [10000 + challenge.id] } : null)
77-
}
78-
)
13+
function insertChallengeHints (challenge) {
14+
const hints = []
15+
if (challenge.hint && insertHints !== options.noTextHints) {
16+
hints.push(challenge.hint.replaceAll('"', '""').replaceAll(',', '٬'))
17+
}
18+
if (challenge.hintUrl && insertHintUrls !== options.noHintUrls) {
19+
hints.push(challenge.hintUrl)
20+
}
21+
if (vulnSnippets[challenge.key] && insertHintSnippets !== options.noHintSnippets) {
22+
hints.push('<pre><code>' + vulnSnippets[challenge.key].replaceAll('"', '""').replaceAll(',', '٬') + '</code></pre>')
23+
}
24+
return (hints.length === 0 ? '' : `"${hints.join(',')}"`)
7925
}
8026

81-
function insertTags ({ tags }, challenge) {
82-
if (!challenge.tags) {
83-
return
27+
/*
28+
function insertChallengeHintCosts (challenge) {
29+
const hintCosts = []
30+
if (challenge.hint && insertHints !== options.noTextHints) {
31+
hintCosts.push(calculateHintCost(challenge, insertHints))
8432
}
85-
tags.results.push(
86-
...challenge.tags.split(',').map((tag, index) => {
87-
return {
88-
id: (challenge.id * 100) + index,
89-
challenge_id: challenge.id,
90-
value: tag
91-
}
92-
})
93-
)
33+
if (challenge.hintUrl && insertHintUrls !== options.noHintUrls) {
34+
hintCosts.push(calculateHintCost(challenge, insertHintUrls))
35+
}
36+
if (vulnSnippets[challenge.key] && insertHintSnippets !== options.noHintSnippets) {
37+
hintCosts.push(calculateHintCost(challenge, insertHintSnippets))
38+
}
39+
return (hintCosts.length === 0 ? '' : `"${hintCosts.join(',')}"`)
9440
}
41+
*/
9542

9643
return new Promise((resolve, reject) => {
9744
try {
98-
const data = {
99-
challenges: { results: [] },
100-
hints: { results: [] },
101-
flagKeys: { results: [] },
102-
tags: { results: [] }
103-
}
45+
const data = []
10446
for (const key in challenges) {
10547
if (Object.prototype.hasOwnProperty.call(challenges, key)) {
10648
const challenge = challenges[key]
107-
insertChallenge(data, challenge)
108-
insertKey(data, challenge)
109-
insertTags(data, challenge)
110-
if (challenge.hint && insertHints !== options.noTextHints) {
111-
insertTextHint(data, challenge)
112-
}
113-
if (challenge.hintUrl && insertHintUrls !== options.noHintUrls) {
114-
insertHintUrl(data, challenge, insertHints !== options.noTextHints)
115-
}
116-
if (vulnSnippets[challenge.key] && insertHintSnippets !== options.noHintSnippets) {
117-
insertHintSnippet(data, challenge, vulnSnippets[challenge.key], insertHints !== options.noTextHints, insertHintUrls !== options.noHintUrls)
118-
}
49+
data.push(
50+
{
51+
name: challenge.name,
52+
description: `"${challenge.description.replaceAll('"', '""')} (Difficulty Level: ${challenge.difficulty})"`,
53+
category: challenge.category,
54+
value: calculateScore(challenge.difficulty),
55+
type: 'standard',
56+
state: 'visible',
57+
max_attempts: 0,
58+
flags: hmacSha1(ctfKey, challenge.name),
59+
tags: challenge.tags ? `"${challenge.tags}"` : '',
60+
hints: insertChallengeHints(challenge),
61+
// hint_cost: insertChallengeHintCosts(challenge),
62+
type_data: ''
63+
}
64+
)
11965
}
12066
}
12167
resolve(data)

lib/generators/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: MIT
44
*/
55

6-
const writeToCtfdZip = require('../writeToCtfdZip')
6+
const writeToCtfdZip = require('../writeToCtfdCsv')
77
const writeToFbctfJson = require('../writeToFbctfJson')
88
const writeToRtbXml = require('../writeToRtbXml')
99
const options = require('../options')

lib/writeToCtfdCsv.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2016-2022 Bjoern Kimminich & the OWASP Juice Shop contributors.
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
6+
const Promise = require('bluebird')
7+
const fs = require('fs')
8+
Promise.promisifyAll(fs)
9+
const path = require('path')
10+
const dateFormat = require('dateformat')
11+
12+
function writeToCtfdCsv (data, desiredFileName) {
13+
return new Promise((resolve, reject) => {
14+
const fileName = desiredFileName || 'OWASP_Juice_Shop.' + dateFormat(new Date(), 'yyyy-mm-dd') + '.CTFd.csv'
15+
fs.writeFileAsync(fileName, convertToCSV(data), 'utf8').then(() => {
16+
resolve(path.resolve(fileName).green)
17+
}).catch(({ message }) => {
18+
reject(new Error('Failed to write output to file! ' + message))
19+
})
20+
})
21+
}
22+
23+
function convertToCSV (arr) {
24+
const array = [Object.keys(arr[0])].concat(arr)
25+
26+
return array.map(it => {
27+
return Object.values(it).toString()
28+
}).join('\n')
29+
}
30+
31+
module.exports = writeToCtfdCsv

lib/writeToCtfdZip.js

-30
This file was deleted.

0 commit comments

Comments
 (0)