Skip to content

Commit 3a3168b

Browse files
committed
Merge branch 'main' of https://github.com/moogiio/SecureCodePuzzles into main
2 parents 3f2434d + d3a9580 commit 3a3168b

11 files changed

Lines changed: 394 additions & 0 deletions

File tree

Node/Answers/a001.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const express = require('express');
2+
const mysql = require('mysql2');
3+
const config = require('./config'); // Assuming configuration is stored in a separate file
4+
5+
const app = express();
6+
7+
// Create a MySQL connection
8+
const connection = mysql.createConnection({
9+
host: config.host,
10+
user: config.user,
11+
password: config.password,
12+
database: config.database
13+
});
14+
15+
app.get('/api/sql/user', (req, res) => {
16+
const id = req.query.id;
17+
18+
// Use parameterized query
19+
const query = 'SELECT * FROM Users WHERE Id = ?';
20+
21+
connection.query(query, [id], (error, results) => {
22+
if (error) {
23+
return res.status(500).json({ error: 'Database error' });
24+
}
25+
26+
if (results.length > 0) {
27+
const user = results[0];
28+
const returnString = `Name: ${user.Name}. Description: ${user.Description}`;
29+
res.send(returnString);
30+
} else {
31+
res.send('');
32+
}
33+
});
34+
});
35+
36+
const port = 3000;
37+
app.listen(port, () => {
38+
console.log(`Server running on port ${port}`);
39+
});

Node/Answers/a002.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const express = require('express');
2+
const app = express();
3+
4+
// Simulating a database context
5+
const db = {
6+
findItems: (query) => {
7+
// Simulate database search
8+
return [{ name: 'Item 1' }, { name: 'Item 2' }];
9+
}
10+
};
11+
12+
function sanitizeInput(input) {
13+
// In a real scenario, this would actually sanitize the input
14+
return input;
15+
}
16+
17+
app.get('/api/search', (req, res) => {
18+
const query = req.query.query;
19+
const cleanQuery = sanitizeInput(query);
20+
21+
const search = {
22+
query: sanitizeInput(query),
23+
items: []
24+
};
25+
26+
try {
27+
search.items = db.findItems(cleanQuery);
28+
res.json(search);
29+
} catch (e) {
30+
res.status(500).json({ error: 'An error occurred during search' });
31+
}
32+
});
33+
34+
const port = 3000;
35+
app.listen(port, () => {
36+
console.log(`Server running on port ${port}`);
37+
});

Node/Answers/a003.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const libxmljs = require('libxmljs');
2+
3+
const xml = `<?xml version="1.0" ?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "EXTERNAL_FILE">]> <product id="1"> <description>&xxe;</description></product>`;
4+
5+
function parseXmlSecurely() {
6+
try {
7+
const xmlDoc = libxmljs.parseXml(xml, {
8+
nonet: true, // Disable network access
9+
recover: true, // Recover from errors
10+
noent: false, // Don't substitute entities
11+
dtdload: false, // Don't load external DTDs
12+
dtdattr: false, // Don't default DTD attributes
13+
});
14+
return xmlDoc.root().text();
15+
} catch (error) {
16+
console.error('XML parsing error:', error);
17+
return null;
18+
}
19+
}
20+
21+
console.log(parseXmlSecurely());

Node/Answers/a005/a005_rev1.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class PriceCalculator {
2+
calculate(amount, type, years) {
3+
if (typeof amount !== 'number' || amount < 0) {
4+
throw new Error('Amount must be a non-negative number');
5+
}
6+
if (!Number.isInteger(type) || type < 1 || type > 4) {
7+
throw new Error('Type must be an integer between 1 and 4');
8+
}
9+
if (!Number.isInteger(years) || years < 0) {
10+
throw new Error('Years must be a non-negative integer');
11+
}
12+
13+
const discountRate = Math.min(years, 5) / 100;
14+
15+
let basePrice;
16+
switch (type) {
17+
case 1:
18+
basePrice = amount;
19+
break;
20+
case 2:
21+
basePrice = amount * 0.9;
22+
break;
23+
case 3:
24+
basePrice = amount * 0.7;
25+
break;
26+
case 4:
27+
basePrice = amount * 0.5;
28+
break;
29+
}
30+
31+
const discount = basePrice * discountRate;
32+
return basePrice - discount;
33+
}
34+
}
35+
36+
module.exports = PriceCalculator;

Node/Answers/a005/a005_rev2.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
class PriceCalculator {
2+
constructor() {
3+
this.typeDiscounts = {
4+
1: 0,
5+
2: 0.1,
6+
3: 0.3,
7+
4: 0.5
8+
};
9+
this.maxYearsDiscount = 5;
10+
}
11+
12+
calculate(amount, type, years) {
13+
this.validateInputs(amount, type, years);
14+
15+
const baseDiscount = this.typeDiscounts[type] || 0;
16+
const yearsDiscount = Math.min(years, this.maxYearsDiscount) / 100;
17+
18+
const basePrice = amount * (1 - baseDiscount);
19+
const yearlyDiscount = basePrice * yearsDiscount;
20+
21+
return basePrice - yearlyDiscount;
22+
}
23+
24+
validateInputs(amount, type, years) {
25+
if (typeof amount !== 'number' || amount < 0) {
26+
throw new Error('Amount must be a non-negative number');
27+
}
28+
if (!Number.isInteger(type) || !this.typeDiscounts.hasOwnProperty(type)) {
29+
throw new Error(`Type must be one of: ${Object.keys(this.typeDiscounts).join(', ')}`);
30+
}
31+
if (!Number.isInteger(years) || years < 0) {
32+
throw new Error('Years must be a non-negative integer');
33+
}
34+
}
35+
}
36+
37+
module.exports = PriceCalculator;

Node/Answers/a005/a005_rev3.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
class PriceCalculator {
2+
constructor(config = {}) {
3+
this.typeDiscounts = config.typeDiscounts || {
4+
1: 0,
5+
2: 0.1,
6+
3: 0.3,
7+
4: 0.5
8+
};
9+
this.maxYearsDiscount = config.maxYearsDiscount || 5;
10+
this.yearlyDiscountRate = config.yearlyDiscountRate || 0.01; // 1% per year
11+
}
12+
13+
calculate(amount, type, years) {
14+
try {
15+
this.validateInputs(amount, type, years);
16+
17+
const baseDiscount = this.typeDiscounts[type];
18+
const yearsDiscount = Math.min(years, this.maxYearsDiscount) * this.yearlyDiscountRate;
19+
20+
const basePrice = amount * (1 - baseDiscount);
21+
const yearlyDiscount = basePrice * yearsDiscount;
22+
23+
const finalPrice = basePrice - yearlyDiscount;
24+
return Number(finalPrice.toFixed(2)); // Round to 2 decimal places
25+
} catch (error) {
26+
console.error('Calculation error:', error.message);
27+
throw error;
28+
}
29+
}
30+
31+
validateInputs(amount, type, years) {
32+
if (typeof amount !== 'number' || isNaN(amount) || amount < 0) {
33+
throw new Error('Amount must be a non-negative number');
34+
}
35+
if (!Number.isInteger(type) || !this.typeDiscounts.hasOwnProperty(type)) {
36+
throw new Error(`Type must be one of: ${Object.keys(this.typeDiscounts).join(', ')}`);
37+
}
38+
if (!Number.isInteger(years) || years < 0) {
39+
throw new Error('Years must be a non-negative integer');
40+
}
41+
}
42+
}
43+
44+
module.exports = PriceCalculator;

Node/p001.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const express = require('express');
2+
const mysql = require('mysql2');
3+
const config = require('./config'); // Assuming configuration is stored in a separate file
4+
5+
const app = express();
6+
7+
// Create a MySQL connection
8+
const connection = mysql.createConnection({
9+
host: config.host,
10+
user: config.user,
11+
password: config.password,
12+
database: config.database
13+
});
14+
15+
app.get('/api/sql/user', (req, res) => {
16+
const id = req.query.id;
17+
18+
const query = `SELECT * FROM Users WHERE Id = ${id}`;
19+
20+
connection.query(query, (error, results) => {
21+
if (error) {
22+
return res.status(500).json({ error: 'Database error' });
23+
}
24+
25+
if (results.length > 0) {
26+
const user = results[0];
27+
const returnString = `Name: ${user.Name}. Description: ${user.Description}`;
28+
res.send(returnString);
29+
} else {
30+
res.send('');
31+
}
32+
});
33+
});
34+
35+
const port = 3000;
36+
app.listen(port, () => {
37+
console.log(`Server running on port ${port}`);
38+
});

Node/p002.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const express = require('express');
2+
const app = express();
3+
4+
// Simulating a database context
5+
const db = {
6+
findItems: (query) => {
7+
// Simulate database search
8+
return [{ name: 'Item 1' }, { name: 'Item 2' }];
9+
}
10+
};
11+
12+
function sanitizeInput(input) {
13+
// In a real scenario, this would actually sanitize the input
14+
return input;
15+
}
16+
17+
app.get('/api/search', (req, res) => {
18+
const query = req.query.query;
19+
const cleanQuery = sanitizeInput(query);
20+
21+
const search = {
22+
query: query,
23+
items: []
24+
};
25+
26+
try {
27+
search.items = db.findItems(cleanQuery);
28+
res.json(search);
29+
} catch (e) {
30+
res.status(500).json({ error: 'An error occurred during search' });
31+
}
32+
});
33+
34+
const port = 3000;
35+
app.listen(port, () => {
36+
console.log(`Server running on port ${port}`);
37+
});

Node/p003.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const { DOMParser } = require('xmldom');
2+
const fs = require('fs');
3+
4+
const xml = `<?xml version="1.0" ?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "EXTERNAL_FILE">]> <product id="1"> <description>&xxe;</description></product>`;
5+
6+
function parseXmlDocument() {
7+
const parser = new DOMParser();
8+
const xmlDoc = parser.parseFromString(xml, 'text/xml');
9+
return xmlDoc.documentElement.textContent;
10+
}
11+
12+
function parseXmlReader() {
13+
const parser = new DOMParser({
14+
resolveExternalEntities: true
15+
});
16+
const xmlDoc = parser.parseFromString(xml, 'text/xml');
17+
return xmlDoc.documentElement.textContent;
18+
}
19+
20+
console.log(parseXmlDocument());
21+
console.log(parseXmlReader());

Node/p004.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const express = require('express');
2+
const router = express.Router();
3+
4+
class UserService {
5+
constructor(configuration, userRepository) {
6+
this.configuration = configuration;
7+
this.userRepository = userRepository;
8+
}
9+
10+
getUser(query) {
11+
return this.findUserInDatabase(query);
12+
}
13+
14+
getUserModel(user) {
15+
const u = this.findUserInDatabase(user);
16+
if (u != null) {
17+
return u; // Assuming UserModel is just a plain object in JS
18+
}
19+
return {}; // Equivalent to new UserModel() in C#
20+
}
21+
22+
findUserInDatabase(query) {
23+
return this.userRepository.findUser(query);
24+
}
25+
}
26+
27+
const configuration = {};
28+
const userRepository = {
29+
findUser: (query) => {
30+
console.log('Finding user with query:', query);
31+
return null; // Simulating no user found
32+
}
33+
};
34+
35+
const userService = new UserService(configuration, userRepository);
36+
37+
// Setting up routes
38+
router.get('/user', (req, res) => {
39+
const result = userService.getUser(req.query);
40+
res.json(result);
41+
});
42+
43+
router.post('/user', (req, res) => {
44+
const result = userService.getUserModel(req.body);
45+
res.json(result);
46+
});
47+
48+
module.exports = router;

0 commit comments

Comments
 (0)