From 50d1d5e97c15d5e81dbb277475fa64ba91f27b68 Mon Sep 17 00:00:00 2001
From: paul-ion
Date: Thu, 7 Aug 2025 21:18:31 +0000
Subject: [PATCH 01/21] Add option answer type and cvss module stub
---
trainingportal/challenges.js | 15 +++++---
trainingportal/qna.js | 7 +++-
trainingportal/static/challenges.html | 26 ++++++++++----
trainingportal/static/challengesCtrl.js | 30 ++++++++++++++++
.../static/lessons/cvss/cvss_intro.md | 5 +++
.../static/lessons/cvss/cvss_intro.sol.md | 0
.../static/lessons/cvss/definitions.json | 36 +++++++++++++++++++
trainingportal/static/lessons/modules.json | 13 +++++++
trainingportal/static/submitCode.html | 13 +++----
trainingportal/static/submitCodeCtrl.js | 19 ++++++++--
trainingportal/test/qna.test.js | 2 +-
11 files changed, 143 insertions(+), 23 deletions(-)
create mode 100644 trainingportal/static/lessons/cvss/cvss_intro.md
create mode 100644 trainingportal/static/lessons/cvss/cvss_intro.sol.md
create mode 100644 trainingportal/static/lessons/cvss/definitions.json
diff --git a/trainingportal/challenges.js b/trainingportal/challenges.js
index 2e17588a..f09ad489 100644
--- a/trainingportal/challenges.js
+++ b/trainingportal/challenges.js
@@ -84,7 +84,6 @@ let init = async () => {
let moduleDefinitions = getDefinitionsForModule(moduleId);
var modulePath = getModulePath(moduleId);
for(let level of moduleDefinitions){
- challengeDefinitions.push(level);
for(let challenge of level.challenges){
if(!util.isNullOrUndefined(challengeNames[challenge.id])){
throw new Error(`Duplicate challenge id: '${challenge.id}'!`);
@@ -206,6 +205,7 @@ let getChallengeDefinitions = async (moduleId) => {
if(util.isNullOrUndefined(moduleId)) return [];
if(util.isNullOrUndefined(modules[moduleId])) return [];
+ if(!util.isNullOrUndefined(challengeDefinitions[moduleId])) return challengeDefinitions[moduleId];
var modulePath = getModulePath(moduleId);
var moduleDefinitions = getDefinitionsForModule(moduleId);
@@ -224,12 +224,17 @@ let getChallengeDefinitions = async (moduleId) => {
challenge.description = path.join(modulePath, description);
}
if(challenge.type === "quiz"){
- challenge.question = qna.getCode(challenge.id);
+ if(util.isNullOrUndefined(challenge.options)){
+ challenge.question = qna.getCode(challenge.id);
+ }
+ else if(!util.isNullOrUndefined(challenge.answer)){
+ challenge.question = { "digest": qna.getDigest(challenge.answer)}
+ }
}
}
returnChallenges.push(level);
}
-
+ challengeDefinitions[moduleId] = returnChallenges;
return returnChallenges;
}
@@ -452,8 +457,8 @@ let apiChallengeCode = async (req) => {
}
let answer = null;
- if(!util.isNullOrUndefined(req.body.answer)){
- answer = req.body.answer.trim();
+ if(!util.isNullOrUndefined(req.body.answer) && typeof req.body.answer === "string"){
+ answer = req.body.answer.trim().toLowerCase();
}
if(util.isNullOrUndefined(challengeCode) ||
diff --git a/trainingportal/qna.js b/trainingportal/qna.js
index 2a6c5587..83f578e7 100644
--- a/trainingportal/qna.js
+++ b/trainingportal/qna.js
@@ -25,8 +25,12 @@ let getSecretText = (challengeId) => {
return secretText.toUpperCase();
}
+let getDigest = (val) => {
+ return crypto.createHash('sha256').update(val.trim().toLowerCase() + masterSalt).digest('hex');
+}
+
let getRes = (mes, code) => {
- let digest = crypto.createHash('sha256').update(mes.trim()+masterSalt).digest('hex');
+ let digest = getDigest(mes);
return res = {
code:code,
digest:digest,
@@ -241,6 +245,7 @@ const DEFS = {
module.exports = {
DEFS,
getCode,
+ getDigest,
checkCode,
xorOp
}
diff --git a/trainingportal/static/challenges.html b/trainingportal/static/challenges.html
index 6a4930f3..c32b5820 100644
--- a/trainingportal/static/challenges.html
+++ b/trainingportal/static/challenges.html
@@ -74,12 +74,26 @@ Challenge
The play link has been provided to you when solving the previous module or challenge.
If you have missed it read the challenge description carefully and try to figure out what it is.
-
+
+
+
+
+
+ {{op.display}}
+
+
+
+
+
+
+ Submit Answer
+
+
Once you were able to complete the challenge you can generate a code which you can submit below.
@@ -87,11 +101,11 @@
Challenge
Submit Code
-
-
- Once you were able to find the answer you can submit it below.
-
- Submit Answer
+
+ Answer:
+
+
+ Submit Answer
diff --git a/trainingportal/static/challengesCtrl.js b/trainingportal/static/challengesCtrl.js
index 67b31162..e950ecd8 100644
--- a/trainingportal/static/challengesCtrl.js
+++ b/trainingportal/static/challengesCtrl.js
@@ -24,6 +24,36 @@ app.controller("challengesCtrl", function($scope, $http, $routeParams) {
}
+ $scope.submitOption = function(id, digest){
+ let answer = null;
+ let options = document.getElementsByClassName(`option-${id}`);
+ for(let op of options){
+ if(op.checked){
+ answer = op.value
+ break;
+ }
+ }
+ $scope.saveAnswer(answer,id,digest);
+ }
+
+ $scope.submitAnswer = function(id, digest){
+ let answer = null;
+ let el = document.getElementById(`answer-${id}`);
+ if(el){
+ answer = el.value;
+ }
+ $scope.saveAnswer(answer,id,digest);
+ }
+
+ $scope.saveAnswer = function(answer, id, digest){
+ if(answer !== null){
+ localStorage.setItem("dojo.current.answer", answer);
+ localStorage.setItem("dojo.current.challenge", window.location.href);
+ window.location.href = `#!submitCode/${$scope.moduleId}/${id}/quiz/${digest}`;
+ }
+ }
+
+
$scope.loadChallenges = function(){
$http.get(`/challenges/${$scope.moduleId}`)
.then(function(response) {
diff --git a/trainingportal/static/lessons/cvss/cvss_intro.md b/trainingportal/static/lessons/cvss/cvss_intro.md
new file mode 100644
index 00000000..1c63d5bb
--- /dev/null
+++ b/trainingportal/static/lessons/cvss/cvss_intro.md
@@ -0,0 +1,5 @@
+#### Agreeing on vulnerability severity
+
+The Common Vulnerability Scoring System (CVSS) is how we agree on vulnerability severity.
+
+We need to agree on severity so we may prioritize investing our time and effort where it matters most.
\ No newline at end of file
diff --git a/trainingportal/static/lessons/cvss/cvss_intro.sol.md b/trainingportal/static/lessons/cvss/cvss_intro.sol.md
new file mode 100644
index 00000000..e69de29b
diff --git a/trainingportal/static/lessons/cvss/definitions.json b/trainingportal/static/lessons/cvss/definitions.json
new file mode 100644
index 00000000..f705b47d
--- /dev/null
+++ b/trainingportal/static/lessons/cvss/definitions.json
@@ -0,0 +1,36 @@
+[
+ {
+ "level":0,
+ "name":"Vulnerability Investigator",
+ "challenges":[
+ {
+ "id":"cvss_intro",
+ "name":"About CVSS",
+ "description": "cvss_intro.md",
+ "solution": "cvss_intro.sol.md",
+ "type":"quiz",
+ "mission":"Choose the correct option",
+ "options":[
+ {
+ "display":"Confidentiality: High, Integrity: High, Availability: High",
+ "value":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"
+ },
+ {
+ "display":"Confidentiality: High, Integrity: High, Availability: None",
+ "value":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N"
+ },
+ {
+ "display":"Confidentiality: High, Integrity: None, Availability: None",
+ "value":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N"
+ },
+ {
+ "display":"Confidentiality: None, Integrity: None, Availability: None",
+ "value":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:N/SA:N"
+ }
+ ],
+ "answer":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
+ "codeBlockIds":[]
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/trainingportal/static/lessons/modules.json b/trainingportal/static/lessons/modules.json
index 688c94e0..46a4b336 100644
--- a/trainingportal/static/lessons/modules.json
+++ b/trainingportal/static/lessons/modules.json
@@ -14,6 +14,19 @@
},
"requiredModules":[]
},
+ "cvss":{
+ "name":"Vulnerability Investigator",
+ "summary":"Understanding vulnerability severity",
+ "description":"This module covers the most important aspects of the Common Vulnerability Scoring System (CVSS)",
+ "description2": "Includes lessons. Estimated duration 2 hours.",
+ "badgeInfo":{
+ "line1":"Secure Coding Dojo",
+ "line2":"Vulnerability Investigator",
+ "line3":"",
+ "bg":"darkorange"
+ },
+ "requiredModules":[]
+ },
"cryptoBreaker":{
"name":"Crypto Breaker - Part 1",
"summary":"Introduction to Cryptography",
diff --git a/trainingportal/static/submitCode.html b/trainingportal/static/submitCode.html
index 830a8301..8099a250 100644
--- a/trainingportal/static/submitCode.html
+++ b/trainingportal/static/submitCode.html
@@ -6,24 +6,21 @@
When you have solved the challenge, take the salt below to obtain the verification code.