Add lessons
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
const LessonModule = require('../base/LessonModule');
|
||||
|
||||
/**
|
||||
* XSS Deeplink Demo Lesson
|
||||
* Demonstrates cross-site scripting via URL parameter manipulation
|
||||
*/
|
||||
class XSSDeeplinkLesson extends LessonModule {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect XSS patterns in user input
|
||||
* @param {string} input - User-provided payload
|
||||
* @returns {string|null} Attack type or null if safe
|
||||
*/
|
||||
detectXSS(input) {
|
||||
const patterns = [
|
||||
{ regex: /<script[\s\S]*?>/gi, type: 'SCRIPT_TAG' },
|
||||
{ regex: /on\w+\s*=\s*["'][^"']*["']/gi, type: 'EVENT_HANDLER' },
|
||||
{ regex: /on\w+\s*=\s*/gi, type: 'EVENT_HANDLER_SIMPLE' },
|
||||
{ regex: /javascript:/gi, type: 'JAVASCRIPT_PROTOCOL' },
|
||||
{ regex: /<iframe/gi, type: 'IFRAME_TAG' },
|
||||
{ regex: /<img[^>]+onerror/gi, type: 'IMG_ONERROR' },
|
||||
{ regex: /<svg[^>]+onload/gi, type: 'SVG_ONLOAD' },
|
||||
{ regex: /<object/gi, type: 'OBJECT_TAG' },
|
||||
{ regex: /<embed/gi, type: 'EMBED_TAG' }
|
||||
];
|
||||
|
||||
for (const pattern of patterns) {
|
||||
if (pattern.regex.test(input)) {
|
||||
return pattern.type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze XSS payload and provide educational explanation
|
||||
* @param {string} input - User-provided payload
|
||||
* @returns {Object} Analysis result
|
||||
*/
|
||||
analyzeXSS(input) {
|
||||
const type = this.detectXSS(input);
|
||||
|
||||
const explanations = {
|
||||
'SCRIPT_TAG': {
|
||||
title: 'Script Tag Injection',
|
||||
description: '⚠️ Script tag detected! This can execute arbitrary JavaScript code.',
|
||||
impact: 'Attackers can steal cookies, manipulate the DOM, redirect users, or execute any JavaScript.',
|
||||
severity: 'high'
|
||||
},
|
||||
'EVENT_HANDLER': {
|
||||
title: 'Event Handler Injection',
|
||||
description: '⚠️ Event handler attribute detected! This triggers JavaScript on user interaction.',
|
||||
impact: 'Can execute code when user interacts with the element (click, hover, etc.).',
|
||||
severity: 'high'
|
||||
},
|
||||
'EVENT_HANDLER_SIMPLE': {
|
||||
title: 'Event Handler Injection',
|
||||
description: '⚠️ Event handler detected! This can trigger JavaScript execution.',
|
||||
impact: 'Can execute code when specific events occur on the page.',
|
||||
severity: 'high'
|
||||
},
|
||||
'JAVASCRIPT_PROTOCOL': {
|
||||
title: 'JavaScript Protocol',
|
||||
description: '⚠️ JavaScript protocol detected! This can execute code when clicked.',
|
||||
impact: 'Often used in href attributes to execute JavaScript when a link is clicked.',
|
||||
severity: 'medium'
|
||||
},
|
||||
'IFRAME_TAG': {
|
||||
title: 'IFrame Injection',
|
||||
description: '⚠️ IFrame tag detected! This can load malicious external content.',
|
||||
impact: 'Can embed phishing pages or malicious content from external sources.',
|
||||
severity: 'high'
|
||||
},
|
||||
'IMG_ONERROR': {
|
||||
title: 'Image Error Handler',
|
||||
description: '⚠️ Image with onerror handler detected! This executes JavaScript when image fails to load.',
|
||||
impact: 'By using an invalid image source, the onerror event always fires, executing the payload.',
|
||||
severity: 'high'
|
||||
},
|
||||
'SVG_ONLOAD': {
|
||||
title: 'SVG Onload Handler',
|
||||
description: '⚠️ SVG with onload handler detected! This executes JavaScript when SVG loads.',
|
||||
impact: 'SVG tags can contain inline event handlers that execute immediately.',
|
||||
severity: 'high'
|
||||
},
|
||||
'OBJECT_TAG': {
|
||||
title: 'Object Tag Injection',
|
||||
description: '⚠️ Object tag detected! This can embed dangerous content.',
|
||||
impact: 'Can be used to load external resources or execute code.',
|
||||
severity: 'medium'
|
||||
},
|
||||
'EMBED_TAG': {
|
||||
title: 'Embed Tag Injection',
|
||||
description: '⚠️ Embed tag detected! This can load external resources.',
|
||||
impact: 'Can be used to embed malicious plugins or content.',
|
||||
severity: 'medium'
|
||||
}
|
||||
};
|
||||
|
||||
if (type && explanations[type]) {
|
||||
return {
|
||||
type,
|
||||
isXSS: true,
|
||||
...explanations[type]
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: null,
|
||||
isXSS: false,
|
||||
title: 'No XSS Detected',
|
||||
description: '✅ No XSS patterns found in the input.',
|
||||
impact: 'This input appears safe.',
|
||||
severity: 'none'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize HTML for safe display
|
||||
* @param {string} input - User input
|
||||
* @returns {string} Sanitized output
|
||||
*/
|
||||
sanitizeHTML(input) {
|
||||
return input
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test XSS payload and return comparison data
|
||||
* Called via executeLessonAction endpoint
|
||||
* @param {string} participantId - Participant identifier
|
||||
* @param {string} payload - User-provided payload to test
|
||||
* @param {string} stepId - Step identifier
|
||||
* @param {number} eventLessonId - Event lesson ID for point awards
|
||||
* @returns {Object} Test results
|
||||
*/
|
||||
async testXSSPayload(participantId, payload, stepId, eventLessonId) {
|
||||
const analysis = this.analyzeXSS(payload);
|
||||
const sanitized = this.sanitizeHTML(payload);
|
||||
|
||||
// Award points based on XSS type discovered
|
||||
let pointsAwarded = 0;
|
||||
if (analysis.isXSS && participantId && eventLessonId) {
|
||||
const pointsMap = {
|
||||
'SCRIPT_TAG': 35, // Classic script tag
|
||||
'EVENT_HANDLER': 35, // Event handler
|
||||
'EVENT_HANDLER_SIMPLE': 30, // Simple event handler
|
||||
'JAVASCRIPT_PROTOCOL': 25, // JavaScript URL
|
||||
'IFRAME_TAG': 40, // IFrame injection
|
||||
'IMG_ONERROR': 35, // Image error XSS
|
||||
'SVG_ONLOAD': 40, // SVG XSS
|
||||
'OBJECT_TAG': 30, // Object tag
|
||||
'EMBED_TAG': 30 // Embed tag
|
||||
};
|
||||
|
||||
pointsAwarded = pointsMap[analysis.type] || 20;
|
||||
|
||||
try {
|
||||
await this.awardPoints(participantId, eventLessonId, pointsAwarded,
|
||||
`XSS via URL parameter: ${analysis.type}`);
|
||||
} catch (error) {
|
||||
console.error('Failed to award XSS points:', error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
originalPayload: payload,
|
||||
sanitizedPayload: sanitized,
|
||||
isXSS: analysis.isXSS,
|
||||
attackType: analysis.type,
|
||||
attackTitle: analysis.title,
|
||||
explanation: analysis.description,
|
||||
impact: analysis.impact,
|
||||
severity: analysis.severity,
|
||||
vulnerableURL: `https://example-shop.com/product?name=${payload}`,
|
||||
safeURL: `https://example-shop.com/product?name=${encodeURIComponent(sanitized)}`,
|
||||
comparisonHTML: {
|
||||
vulnerable: `<div class="product-name">${payload}</div>`,
|
||||
safe: `<div class="product-name">${sanitized}</div>`
|
||||
},
|
||||
pointsAwarded
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get interactive data for XSS demo step
|
||||
* @param {string} stepId - Step identifier
|
||||
* @returns {Object} Interactive component data
|
||||
*/
|
||||
async getInteractiveData(stepId) {
|
||||
if (stepId === 'xss-demo') {
|
||||
return {
|
||||
baseUrl: 'https://example-shop.com/product',
|
||||
parameterName: 'name',
|
||||
examples: [
|
||||
{
|
||||
label: 'Normal Search',
|
||||
payload: 'Laptop',
|
||||
description: 'Safe product search'
|
||||
},
|
||||
{
|
||||
label: 'Script Alert',
|
||||
payload: '<script>alert("XSS")</script>',
|
||||
description: 'Classic XSS attack with script tag'
|
||||
},
|
||||
{
|
||||
label: 'Image Onerror',
|
||||
payload: '<img src=x onerror="alert(1)">',
|
||||
description: 'XSS via broken image error handler'
|
||||
},
|
||||
{
|
||||
label: 'Event Handler',
|
||||
payload: '" onload="alert(1)"',
|
||||
description: 'XSS via event handler injection'
|
||||
},
|
||||
{
|
||||
label: 'SVG Onload',
|
||||
payload: '<svg onload="alert(1)">',
|
||||
description: 'XSS via SVG element'
|
||||
},
|
||||
{
|
||||
label: 'JavaScript Protocol',
|
||||
payload: 'javascript:alert(1)',
|
||||
description: 'XSS via JavaScript URL protocol'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
return await super.getInteractiveData(stepId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = XSSDeeplinkLesson;
|
||||
Reference in New Issue
Block a user