initial commit

This commit is contained in:
Marius Rometsch
2026-02-05 22:42:30 +01:00
commit 0068785924
66 changed files with 13795 additions and 0 deletions
+930
View File
@@ -0,0 +1,930 @@
# Security Awareness Lessons Documentation
This document provides comprehensive information about all available lessons in the platform, including learning objectives, content structure, interactive components, and implementation details.
---
## Table of Contents
1. [Phishing Email Detection Basics](#1-phishing-email-detection-basics)
2. [SQL Injection Attack - Online Shop Demo](#2-sql-injection-attack---online-shop-demo)
3. [Browser-in-the-Browser (BitB) Attack](#3-browser-in-the-browser-bitb-attack)
4. [Creating New Lessons](#creating-new-lessons)
---
## 1. Phishing Email Detection Basics
### Overview
**Lesson Key:** `phishing-email-basics`
**Difficulty:** Beginner
**Duration:** 15 minutes
**Category:** Social Engineering / Email Security
### Learning Objectives
By the end of this lesson, participants will be able to:
- Identify common characteristics of phishing emails
- Recognize suspicious sender addresses and domains
- Detect urgency tactics used by attackers
- Understand link verification techniques
- Apply best practices for handling suspicious emails
### Content Structure
#### Steps:
1. **Introduction to Phishing** (Content)
- Definition and impact of phishing
- Statistics on phishing attacks
- Why email is a primary attack vector
2. **Common Red Flags** (Content)
- Suspicious sender addresses
- Spelling and grammar errors
- Urgent or threatening language
- Requests for sensitive information
- Suspicious links and attachments
3. **Question 1: Identify Phishing Indicators** (Multiple Choice)
- **Points:** 50 total
- **Correct Answers:**
- Misspelled sender domain (15 pts)
- Generic greeting instead of name (10 pts)
- Urgent threat about account closure (15 pts)
- Suspicious link destination (10 pts)
- **Topic:** Recognition of multiple warning signs
4. **Email Analysis Techniques** (Content)
- How to inspect sender information
- Hovering over links to check destinations
- Checking email headers
- Verifying legitimacy through official channels
5. **Question 2: Safe Email Practices** (Single Choice)
- **Points:** 25 total
- **Correct Answer:** "Hover over links to verify destination before clicking"
- **Topic:** Proactive defense techniques
6. **Question 3: Reporting Procedures** (Free Text)
- **Points:** 25 total
- **Validation:** Must mention "report", "IT", and "forward"
- **Topic:** Organizational response to phishing
### Scoring
- **Total Points:** 100
- **Passing Score:** 70%
- **Question Distribution:**
- Multiple choice: 50 points (partial credit)
- Single choice: 25 points (all or nothing)
- Free text: 25 points (keyword-based)
### Implementation Details
**Files:**
- Config: `backend/lessons/configs/phishing-email-basics.yaml`
- Module: `backend/lessons/modules/phishing-email-basics/index.js`
**Question Types:**
- Uses standard base class validation
- No custom interactive components
- Text-based content delivery
### Best Practices for Teaching
- Start with real-world examples
- Show actual phishing emails (sanitized)
- Emphasize the cost of successful attacks
- Practice with interactive email analysis
- Reinforce reporting procedures
---
## 2. SQL Injection Attack - Online Shop Demo
### Overview
**Lesson Key:** `sql-injection-shop`
**Difficulty:** Intermediate
**Duration:** 20 minutes
**Category:** Web Application Security / OWASP Top 10
### Learning Objectives
By the end of this lesson, participants will be able to:
- Understand how SQL injection vulnerabilities work
- Recognize vulnerable code patterns
- Execute SQL injection attacks in a safe environment
- Understand the difference between vulnerable and secure queries
- Apply parameterized queries as the primary defense
### Content Structure
#### Steps:
1. **What is SQL Injection?** (Content)
- Definition and mechanism
- Types of damage (data theft, modification, deletion)
- Authentication bypass techniques
- Administrative operation exploitation
2. **Vulnerable Online Shop** (Interactive)
- **Component:** `SQLShopDemo`
- Live product search with vulnerable SQL backend
- Real-time query visualization
- Injection detection and explanation
3. **Question 1: Identify SQL Injection Payloads** (Multiple Choice)
- **Points:** 40 total
- **Correct Answers:**
- `' OR '1'='1` (15 pts) - Always-true condition
- `' UNION SELECT username, password FROM users--` (15 pts) - Data extraction
- `'; DROP TABLE products--` (10 pts) - Destructive attack
- **Topic:** Recognition of injection syntax
4. **How SQL Injection Works** (Content)
- Query structure explanation
- Normal vs malicious input comparison
- Step-by-step breakdown of attacks
- Impact demonstration
5. **Question 2: Prevention Methods** (Single Choice)
- **Points:** 30 total
- **Correct Answer:** "Use parameterized queries (prepared statements)"
- **Topic:** Gold-standard defense mechanism
6. **Preventing SQL Injection** (Content)
- Parameterized queries (primary defense)
- Input validation strategies
- Least privilege principle
- Web Application Firewalls
- Security auditing
7. **Question 3: Explain Parameterized Queries** (Free Text)
- **Points:** 30 total
- **Validation:** Must mention "parameter", "data", and "separate"
- **Minimum Length:** 50 characters
- **Topic:** Understanding separation of code and data
### Interactive Component: SQLShopDemo
#### Features:
**Mock Database:**
```javascript
products: 8 items (laptops, accessories, office supplies)
users: 3 accounts (admin, john_doe, jane_smith)
orders: 2 sample orders
```
**Attack Scenarios:**
1. **OR Injection:**
- Input: `' OR '1'='1`
- Result: Returns ALL products
- Explanation: Bypasses WHERE clause with always-true condition
2. **UNION SELECT:**
- Input: `' UNION SELECT id, username, password, role, 'LEAKED' FROM users--`
- Result: Displays user credentials in product table
- Explanation: Combines product data with user table
3. **DROP TABLE:**
- Input: `'; DROP TABLE products--`
- Result: Simulates table deletion
- Explanation: Executes destructive SQL command
**UI Elements:**
- Search input with monospace font for code clarity
- "Vulnerable Search" button (red) - executes unsafe query
- "Safe Search" button (green) - uses parameterized query
- Quick-load example buttons
- Real-time SQL query display with syntax highlighting
- Injection detection warnings with emoji indicators
- Results table showing affected data
- Color-coded feedback (red for exploits, green for safe)
#### Technical Implementation:
**Backend Methods:**
```javascript
executeVulnerableQuery(searchTerm)
- Simulates vulnerable string concatenation
- Detects injection patterns
- Returns appropriate results based on attack type
executeSafeQuery(searchTerm)
- Demonstrates parameterized approach
- Treats all input as literal data
- Shows query with placeholder syntax
detectInjection(input)
- Regex-based pattern matching
- Identifies quotes, comments, SQL keywords
analyzeInjection(input)
- Classifies injection type
- Generates educational explanation
```
**Frontend API Call:**
```javascript
participantAPI.executeLessonAction(
eventLessonId,
'execute-query',
{ searchTerm, mode: 'vulnerable' | 'safe' }
)
```
### Scoring
- **Total Points:** 100
- **Passing Score:** 70%
- **Question Distribution:**
- Multiple choice: 40 points (partial credit)
- Single choice: 30 points
- Free text: 30 points (keyword validation)
### Implementation Details
**Files:**
- Config: `backend/lessons/configs/sql-injection-shop.yaml`
- Module: `backend/lessons/modules/sql-injection-shop/index.js`
- Component: `frontend/src/components/lessons/InteractiveContent/SQLShopDemo.jsx`
**Dependencies:**
- Extends `LessonModule` base class
- Custom `executeVulnerableQuery` method
- Custom `executeSafeQuery` method
- Interactive data provider
**API Endpoint:**
- `POST /api/lesson/:eventLessonId/action/execute-query`
- Requires participant authentication
- Validates lesson is started
### Best Practices for Teaching
- Start with normal searches to establish baseline
- Progress from simple to complex injections
- Always compare vulnerable vs safe implementations
- Emphasize that filtering alone is insufficient
- Show real-world impact examples
- Demonstrate UNION attacks to highlight data exposure risk
- Use color coding to make injection obvious
- Provide immediate feedback on each attempt
### Real-World Context
**OWASP Ranking:** #3 in OWASP Top 10 (Injection)
**Notable Incidents:**
- 2019: British Airways breach (380,000 transactions)
- 2020: Freepik SQL injection (8.3 million accounts)
- Ongoing: Automated scanning for vulnerable endpoints
**Industry Standards:**
- OWASP recommends parameterized queries
- PCI DSS requires SQL injection prevention
- ISO 27001 covers secure coding practices
---
## 3. Browser-in-the-Browser (BitB) Attack
### Overview
**Lesson Key:** `browser-in-browser-attack`
**Difficulty:** Advanced
**Duration:** 25 minutes
**Category:** Social Engineering / Advanced Phishing
### Learning Objectives
By the end of this lesson, participants will be able to:
- Understand Browser-in-the-Browser attack methodology
- Differentiate between real and fake browser windows
- Apply physical testing techniques to detect fake popups
- Recognize OAuth/SSO popup security implications
- Understand why password managers provide protection
### Content Structure
#### Steps:
1. **What is Browser-in-the-Browser?** (Content)
- Definition and attack mechanism
- Why it's effective (mimics trusted UI)
- Comparison to traditional phishing
- Historical context (2022 emergence)
2. **How the Attack Works** (Content)
- Traditional OAuth flow diagram
- BitB attack flow comparison
- Technical explanation (HTML/CSS fake browser)
- Visual deception techniques
3. **Interactive BitB Demo** (Interactive)
- **Component:** `BitBDemo`
- Side-by-side real vs fake comparison
- Interactive detection testing
- Real-world attack examples
4. **Question 1: Detection Indicators** (Multiple Choice)
- **Points:** 40 total
- **Correct Answers:**
- "Window cannot be dragged outside browser" (20 pts)
- "Right-click shows 'Inspect Element' on address bar" (20 pts)
- **Topic:** Physical behavior testing
5. **Detection Techniques** (Content)
- Drag window test (primary method)
- Address bar selectability check
- Right-click inspection test
- Pixel-perfect detail examination
- Taskbar appearance verification
- Browser extension usage
6. **Question 2: Safest Approach** (Single Choice)
- **Points:** 35 total
- **Correct Answer:** "Try to drag the popup outside browser window"
- **Topic:** Practical defense technique
7. **Protecting Against BitB** (Content)
- User defenses (testing, 2FA, manual navigation)
- Developer responsibilities (education, redirect flow)
- Organizational measures (training, hardware keys)
8. **Question 3: Password Manager Protection** (Free Text)
- **Points:** 25 total
- **Validation:** Must mention "domain", "autofill", and "real"
- **Minimum Length:** 40 characters
- **Topic:** Technical security controls
### Interactive Component: BitBDemo
#### Features:
**Two Scenarios:**
1. **Legitimate OAuth Popup (Simulated Real)**
- Provider: Google
- Domain: `accounts.google.com`
- Indicators shown for educational purposes
- Green "✅ REAL" badge
2. **BitB Attack (Fake Popup)**
- Provider: Microsoft
- Domain: `login.microsoftonline.com`
- Trapped within page boundaries
- Red "⚠️ FAKE" badge
**Interactive Tests:**
1. **Drag Test:**
- Real: Would allow dragging (simulated)
- Fake: Cannot drag outside browser
- Feedback: Yellow warning appears when attempted
2. **Right-Click Test:**
- Real: Browser context menu (simulated)
- Fake: Shows "Inspect Element" menu
- Feedback: Warning about HTML detection
3. **Visual Inspection:**
- Fake window controls (non-functional buttons)
- Fake address bar (styled HTML div)
- Fake HTTPS lock icon (just an image)
**UI Elements:**
- Side-by-side scenario cards
- Provider-specific styling (Google blue, Microsoft blue)
- Launch buttons to open fake popups
- Dark overlay when popup is active
- Educational indicators list
- Real-world attack timeline
- Test instructions panel
**Realistic Browser Chrome:**
```
- macOS-style window controls (red, yellow, green)
- Address bar with lock icon
- Provider-specific branding
- Login form (email + password)
- Sign-in button
```
#### Technical Implementation:
**Frontend Structure:**
```javascript
renderFakeBrowser(scenario)
- Creates modal overlay
- Renders fake browser window
- Applies provider styling
- Handles drag attempts
- Handles right-click detection
- Shows feedback badges
```
**Drag Detection:**
```javascript
handleDragStart(e, isReal)
- Sets dragAttempted flag
- Prevents drag if fake (e.preventDefault)
- Shows educational feedback
```
**Right-Click Detection:**
```javascript
handleAddressBarRightClick(e, isReal)
- Sets inspectAttempted flag
- Allows context menu on fake popup
- Shows educational feedback
```
**Real-World Examples Data:**
```javascript
[
{ year: 2022, target: 'Corporate employees', provider: 'Microsoft OAuth' },
{ year: 2022, target: 'Cryptocurrency users', provider: 'Google Sign-in' },
{ year: 2023, target: 'GitHub developers', provider: 'GitHub OAuth' }
]
```
### Scoring
- **Total Points:** 100
- **Passing Score:** 75%
- **Question Distribution:**
- Multiple choice: 40 points (physical testing)
- Single choice: 35 points (best practice)
- Free text: 25 points (technical understanding)
### Implementation Details
**Files:**
- Config: `backend/lessons/configs/browser-in-browser-attack.yaml`
- Module: `backend/lessons/modules/browser-in-browser-attack/index.js`
- Component: `frontend/src/components/lessons/InteractiveContent/BitBDemo.jsx`
**Dependencies:**
- Extends `LessonModule` base class
- Custom `getInteractiveData` method
- React state management for popups
- CSS-in-JS for fake browser styling
**Special Features:**
- Modal overlay system
- Drag prevention
- Context menu detection
- Provider theming
- Responsive design
### Best Practices for Teaching
- Emphasize that visual inspection alone is insufficient
- Demonstrate the drag test as the most reliable method
- Show how convincing the fake popups can be
- Discuss password manager benefits
- Explain why manual navigation is safest
- Reference real-world incidents
- Practice detection multiple times
- Warn about new variations
### Real-World Context
**Discovery:** 2022 by security researcher mr.d0x
**Attack Campaign Examples:**
- **March 2022:** Steam account phishing
- **April 2022:** Cryptocurrency exchange targeting
- **May 2022:** Corporate credential harvesting
- **2023:** GitHub and GitLab developer targeting
**Affected Platforms:**
- Any OAuth/SSO provider (Google, Microsoft, Facebook, GitHub)
- Banking sites with "secure" login popups
- Enterprise SSO systems
- Cryptocurrency wallets
**Why It's Effective:**
- Mimics trusted UI perfectly
- Bypasses traditional phishing training
- Works on security-aware users
- No browser warnings triggered
- HTTPS indicators can be faked
**Defense Evolution:**
- Hardware security keys (FIDO2/WebAuthn) immune
- Password managers check real domain
- Browser extensions can detect fake UI
- User education most critical
---
## Creating New Lessons
### Overview
This section provides guidance for creating new lessons in the platform.
### Lesson Structure
Every lesson consists of two main components:
1. **YAML Configuration File** (`lessons/configs/*.yaml`)
- Defines lesson metadata
- Structures content steps
- Configures questions and answers
- Sets scoring rules
2. **JavaScript Module** (`lessons/modules/*/index.js`)
- Extends `LessonModule` base class
- Implements custom validation logic
- Provides interactive data
- Handles special behaviors
### YAML Configuration Format
```yaml
lessonKey: "unique-lesson-identifier"
title: "Lesson Display Title"
description: "Brief description for lesson catalog"
difficultyLevel: "beginner|intermediate|advanced"
estimatedDuration: 15 # minutes
module: "module-directory-name"
steps:
- id: "step-1"
type: "content|question|interactive"
title: "Step Title"
content: "Step content (can be multiline)"
- id: "question-1"
type: "question"
questionType: "single_choice|multiple_choice|free_text"
question: "The question text?"
options: # for choice questions
- id: "option-1"
text: "Option text"
isCorrect: true|false
points: 10
validationRules: # for free_text questions
keywords:
required: ["keyword1", "keyword2"]
partialCredit: 5
minLength: 50
maxPoints: 25
feedback:
correct: "Positive feedback"
incorrect: "Educational feedback"
scoring:
passingScore: 70
maxTotalPoints: 100
```
### JavaScript Module Structure
```javascript
const LessonModule = require('../base/LessonModule');
class YourLessonModule extends LessonModule {
constructor(config) {
super(config);
}
// Optional: Custom answer validation
async validateAnswer(questionId, answer) {
// Custom logic here, or use:
return super.validateAnswer(questionId, answer);
}
// Optional: Provide data for interactive components
getInteractiveData(stepId) {
if (stepId === 'your-interactive-step') {
return {
// Data your frontend component needs
};
}
return null;
}
// Optional: Custom methods for lesson-specific actions
yourCustomMethod(params) {
// Implementation
}
}
module.exports = YourLessonModule;
```
### Question Types
#### 1. Single Choice
```yaml
questionType: "single_choice"
options:
- id: "correct-option"
text: "The right answer"
isCorrect: true
points: 25
- id: "wrong-option"
text: "An incorrect answer"
isCorrect: false
points: 0
```
- Only one correct answer
- All-or-nothing scoring
- Radio button UI
#### 2. Multiple Choice
```yaml
questionType: "multiple_choice"
options:
- id: "correct-1"
text: "First correct answer"
isCorrect: true
points: 15
- id: "correct-2"
text: "Second correct answer"
isCorrect: true
points: 15
- id: "wrong-1"
text: "Incorrect answer"
isCorrect: false
points: 0
```
- Multiple correct answers
- Partial credit awarded per correct selection
- Checkbox UI
#### 3. Free Text
```yaml
questionType: "free_text"
validationRules:
keywords:
required: ["must", "contain", "these"]
partialCredit: 10 # points if some keywords present
minLength: 50 # minimum character count
maxPoints: 25
```
- Open-ended response
- Keyword-based validation
- Minimum length requirement
### Interactive Components
#### Creating a New Interactive Component
1. **Define in YAML:**
```yaml
- id: "interactive-demo"
type: "interactive"
title: "Interactive Demo"
interactiveComponent: "YourComponentName"
content: "Instructions for the interactive element"
```
2. **Provide Data in Module:**
```javascript
getInteractiveData(stepId) {
if (stepId === 'interactive-demo') {
return {
data: 'Your component data',
config: {}
};
}
return null;
}
```
3. **Create React Component:**
```javascript
// frontend/src/components/lessons/InteractiveContent/YourComponent.jsx
import React from 'react';
const YourComponent = ({ lessonData, eventLessonId }) => {
const interactiveData = lessonData?.interactiveData || {};
return (
<div>
{/* Your interactive UI */}
</div>
);
};
export default YourComponent;
```
4. **Register in LessonView:**
```javascript
// frontend/src/pages/LessonView.jsx
import YourComponent from '../components/lessons/InteractiveContent/YourComponent';
// In render:
{currentStep.interactiveComponent === 'YourComponent' && (
<YourComponent lessonData={lesson} eventLessonId={eventLessonId} />
)}
```
### Lesson-Specific Actions
For interactive components that need backend processing:
1. **Add Method to Module:**
```javascript
yourCustomAction(params) {
// Process params
return result;
}
```
2. **Handle in Controller:**
```javascript
// backend/src/controllers/lesson.controller.js
if (action === 'your-action' && lessonModule.yourCustomAction) {
result = lessonModule.yourCustomAction(actionData);
}
```
3. **Call from Frontend:**
```javascript
participantAPI.executeLessonAction(
eventLessonId,
'your-action',
{ data }
)
```
### Seeding New Lessons
1. **Add to Catalog:**
```javascript
// backend/seed-lessons.js
const lessons = [
{
lesson_key: 'your-lesson-key',
title: 'Your Lesson Title',
description: 'Description',
module_path: 'your-module-directory',
config_path: 'your-config.yaml',
difficulty_level: 'intermediate',
estimated_duration: 20
}
];
```
2. **Run Seed Script:**
```bash
docker exec lernplattform_backend node seed-lessons.js
```
### Best Practices
**Content Design:**
- Start with clear learning objectives
- Use progressive difficulty (easy → hard)
- Provide immediate feedback
- Include real-world examples
- Make it hands-on when possible
**Question Design:**
- Multiple choice: 2-4 options, avoid "all of the above"
- Free text: Clear validation criteria
- Feedback: Educational, not just correct/incorrect
- Points: Reflect question difficulty
**Interactive Elements:**
- Make them essential, not decorative
- Provide clear instructions
- Give immediate visual feedback
- Include educational explanations
- Allow experimentation
**Code Quality:**
- Follow existing patterns
- Handle errors gracefully
- Validate all inputs
- Comment complex logic
- Test thoroughly
**Security:**
- Never execute actual SQL
- Sandbox all demonstrations
- Validate on both frontend and backend
- Don't leak sensitive information
- Use appropriate warnings
### Testing New Lessons
1. **Lesson Content:**
- All steps render correctly
- Images/media load properly
- Text formatting is correct
2. **Questions:**
- Correct answers award proper points
- Wrong answers give appropriate feedback
- Partial credit calculates correctly
- Free text validation works
3. **Interactive Components:**
- Components load without errors
- Actions execute successfully
- Feedback displays correctly
- Edge cases handled
4. **Scoring:**
- Total points sum correctly
- Passing threshold works
- Score persists properly
- Leaderboard updates
5. **Progress:**
- Lesson marked as started
- Navigation works (prev/next)
- Completion triggers properly
- Locked lessons stay locked
### File Checklist
- [ ] YAML config created
- [ ] Module directory created
- [ ] Module class implemented
- [ ] Interactive components (if any) created
- [ ] Seed script updated
- [ ] Lesson seeded to database
- [ ] Tested in browser
- [ ] Documentation updated
---
## Appendix
### Lesson Difficulty Guidelines
**Beginner:**
- Foundational concepts
- No prior security knowledge required
- 10-15 minute duration
- Basic terminology introduction
- Real-world relevance emphasized
**Intermediate:**
- Builds on basic security awareness
- Requires understanding of systems/networks
- 15-25 minute duration
- Hands-on demonstrations
- Technical explanations
**Advanced:**
- Assumes security knowledge
- Complex attack scenarios
- 20-30 minute duration
- In-depth technical details
- Sophisticated defenses
### Scoring Philosophy
- **Partial Credit:** Encourage learning, reward partial knowledge
- **Passing Score:** 70-75% allows mistakes while ensuring competency
- **Question Weight:** Harder questions = more points
- **Immediate Feedback:** Don't wait until end of lesson
### Content Style Guide
**Tone:**
- Professional but approachable
- Educational, not preachy
- Objective about risks
- Encouraging about defenses
**Formatting:**
- Use bullet points for lists
- Bold important terms on first use
- Code blocks for technical content
- Clear step-by-step instructions
**Examples:**
- Prefer real-world incidents
- Include dates and sources
- Show impact (financial, reputational)
- Demonstrate both attacks and defenses
---
## Support
For questions about lesson development:
- Review existing lessons as templates
- Check base class methods in `LessonModule.js`
- Test in development environment first
- Document any new patterns
**Last Updated:** 2026-01-12
**Platform Version:** 1.0.0
**Total Lessons:** 3
+310
View File
@@ -0,0 +1,310 @@
# Lessons Directory
This directory contains all lesson content for the security awareness training platform.
## Structure
```
lessons/
├── configs/ # YAML lesson configurations
│ ├── phishing-email-basics.yaml
│ ├── sql-injection-shop.yaml
│ └── browser-in-browser-attack.yaml
├── modules/ # JavaScript lesson modules
│ ├── base/
│ │ └── LessonModule.js # Base class all lessons extend
│ ├── phishing-email-basics/
│ │ └── index.js
│ ├── sql-injection-shop/
│ │ └── index.js
│ └── browser-in-browser-attack/
│ └── index.js
├── lesson-schema.json # JSON schema for validation (optional)
├── README.md # This file
└── LESSONS_DOCUMENTATION.md # Comprehensive lesson docs
```
## Available Lessons
### 1. Phishing Email Detection Basics
- **Key:** `phishing-email-basics`
- **Difficulty:** Beginner
- **Duration:** 15 minutes
- **Topics:** Email security, social engineering, red flags
- **Interactive:** No
### 2. SQL Injection Attack - Online Shop Demo
- **Key:** `sql-injection-shop`
- **Difficulty:** Intermediate
- **Duration:** 20 minutes
- **Topics:** Web security, OWASP Top 10, SQL injection
- **Interactive:** Yes - Fake shop with vulnerable search
### 3. Browser-in-the-Browser (BitB) Attack
- **Key:** `browser-in-browser-attack`
- **Difficulty:** Advanced
- **Duration:** 25 minutes
- **Topics:** Advanced phishing, OAuth security, UI spoofing
- **Interactive:** Yes - Fake browser popup demos
## Quick Start
### Adding a New Lesson
1. **Create YAML config:**
```bash
cp configs/phishing-email-basics.yaml configs/your-lesson.yaml
# Edit the file with your lesson content
```
2. **Create module:**
```bash
mkdir modules/your-lesson
# Create index.js extending LessonModule
```
3. **Seed to database:**
```bash
# Add to seed script
docker exec lernplattform_backend node seed-lessons.js
```
4. **Assign to event:**
- Use admin panel to assign lesson to events
- Configure points, weight, and order
### Testing a Lesson
1. **Seed the lesson** (see above)
2. **Assign to a test event** via admin panel
3. **Join event as participant** from hub page
4. **Complete the lesson** and verify:
- All steps render correctly
- Questions award proper points
- Interactive components work
- Score calculates correctly
## Lesson Configuration Format
### Minimal YAML Example
```yaml
lessonKey: "my-lesson"
title: "My Lesson Title"
description: "Brief description"
difficultyLevel: "beginner"
estimatedDuration: 15
module: "my-lesson"
steps:
- id: "intro"
type: "content"
title: "Introduction"
content: "Lesson content here..."
- id: "q1"
type: "question"
questionType: "single_choice"
question: "What is the answer?"
options:
- id: "correct"
text: "The right answer"
isCorrect: true
points: 100
- id: "wrong"
text: "Wrong answer"
isCorrect: false
points: 0
maxPoints: 100
feedback:
correct: "Great job!"
incorrect: "Try again!"
scoring:
passingScore: 70
maxTotalPoints: 100
```
### Minimal Module Example
```javascript
const LessonModule = require('../base/LessonModule');
class MyLesson extends LessonModule {
constructor(config) {
super(config);
}
// Use base class validation by default
// Override only if custom logic needed
}
module.exports = MyLesson;
```
## Question Types
### Single Choice
- One correct answer
- Radio buttons in UI
- All-or-nothing scoring
### Multiple Choice
- Multiple correct answers
- Checkboxes in UI
- Partial credit per correct selection
### Free Text
- Open-ended response
- Keyword-based validation
- Minimum length requirement
## Interactive Components
For lessons with interactive demos:
1. **Define in YAML:**
```yaml
- id: "demo"
type: "interactive"
title: "Interactive Demo"
interactiveComponent: "MyComponent"
```
2. **Provide data in module:**
```javascript
getInteractiveData(stepId) {
if (stepId === 'demo') {
return { /* component data */ };
}
return null;
}
```
3. **Create React component:**
```
frontend/src/components/lessons/InteractiveContent/MyComponent.jsx
```
4. **Register in LessonView.jsx**
## File Naming Conventions
- **Lesson keys:** lowercase-with-hyphens
- **Config files:** `{lesson-key}.yaml`
- **Module directories:** `{lesson-key}/`
- **Module entry:** `index.js`
## Best Practices
### Content
- Start with clear learning objectives
- Use real-world examples
- Progress from easy to hard
- Provide immediate feedback
- Make it hands-on when possible
### Questions
- 2-4 options for choice questions
- Clear, unambiguous wording
- Educational feedback (not just "correct"/"incorrect")
- Points reflect difficulty
### Code
- Extend `LessonModule` base class
- Use base class methods when possible
- Comment complex logic
- Handle errors gracefully
- Validate all inputs
### Security
- Never execute actual dangerous commands
- Sandbox all demonstrations
- Use appropriate warnings
- Don't leak sensitive data
## Common Patterns
### Multi-step Content Lesson
```yaml
steps:
- type: content (intro)
- type: content (main content)
- type: question
- type: content (summary)
- type: question
```
### Interactive Demo Lesson
```yaml
steps:
- type: content (intro)
- type: interactive (hands-on)
- type: question (about demo)
- type: content (explanation)
- type: question (best practices)
```
### Progressive Learning
```yaml
# Start easy
- Single choice with obvious answer
# Build complexity
- Multiple choice with several correct answers
# Test understanding
- Free text requiring explanation
```
## Troubleshooting
### Lesson not appearing in admin panel
- Check if lesson was seeded to database
- Verify `lesson_key` matches between YAML and database
- Check database logs for errors
### Questions not scoring correctly
- Verify `maxPoints` matches sum of correct option points
- For multiple choice, ensure points are on correct options
- Check `isCorrect` boolean values
### Interactive component not loading
- Verify component name matches in YAML
- Check component is imported in LessonView.jsx
- Look for console errors in browser
- Verify `getInteractiveData()` returns data
### Module not found errors
- Check `module_path` in database matches directory name
- Verify `index.js` exists in module directory
- Ensure `module.exports` is present
- Check for syntax errors in module
## Documentation
- **Comprehensive Guide:** [LESSONS_DOCUMENTATION.md](./LESSONS_DOCUMENTATION.md)
- **Base Class:** [modules/base/LessonModule.js](./modules/base/LessonModule.js)
- **Examples:** See existing lessons in `configs/` and `modules/`
## Development Workflow
1. **Design** lesson content and questions
2. **Create** YAML config and module
3. **Test** locally with seed script
4. **Assign** to test event
5. **Validate** all questions and interactions
6. **Review** scoring and feedback
7. **Deploy** to production event
## Support
For questions or issues:
1. Review existing lesson implementations
2. Check base class documentation
3. Test in development environment first
4. Review error logs for debugging
---
**Last Updated:** 2026-01-12
**Total Lessons:** 3
**Platform Version:** 1.0.0
@@ -0,0 +1,174 @@
lessonKey: "browser-in-browser-attack"
title: "Browser-in-the-Browser (BitB) Attack"
description: "Learn to identify sophisticated phishing attacks that mimic legitimate browser windows"
difficultyLevel: "advanced"
estimatedDuration: 25
module: "browser-in-browser-attack"
steps:
- id: "intro"
type: "content"
title: "What is Browser-in-the-Browser?"
content: |
Browser-in-the-Browser (BitB) is an advanced phishing technique that creates a fake browser window inside a webpage. It's designed to trick users into thinking they're interacting with a legitimate OAuth/SSO login popup.
Why it's dangerous:
• Looks identical to real browser popup windows
• Shows a fake address bar with HTTPS lock icon
• Mimics trusted services (Google, Microsoft, Facebook)
• Can steal credentials even from security-aware users
• Bypasses traditional phishing detection
This attack gained prominence in 2022 and has been used in targeted attacks against organizations.
- id: "how-it-works"
type: "content"
title: "How the Attack Works"
content: |
Traditional OAuth Flow:
1. User clicks "Sign in with Google" on a website
2. Browser opens a REAL popup to google.com
3. User enters credentials on Google's actual site
4. Google redirects back with authentication token
BitB Attack Flow:
1. User clicks "Sign in with Google" on malicious site
2. Site creates a FAKE popup using HTML/CSS/JavaScript
3. Fake popup shows fake address bar displaying "accounts.google.com"
4. User enters credentials on attacker's fake page
5. Attacker captures credentials and simulates success
The entire "browser window" is actually just HTML elements styled to look like a browser!
- id: "bitb-demo"
type: "interactive"
title: "Interactive BitB Demo"
interactiveComponent: "BitBDemo"
content: |
Below you'll see two login scenarios. One uses a REAL browser popup (secure), and one uses a BitB attack (malicious).
Can you identify the fake? Pay close attention to the details!
- id: "question-1"
type: "question"
questionType: "multiple_choice"
question: "What are the key indicators that can help identify a Browser-in-the-Browser attack?"
options:
- id: "https-lock"
text: "The presence of HTTPS and a lock icon in the address bar"
isCorrect: false
points: 0
- id: "window-behavior"
text: "The popup window cannot be dragged outside the main browser window"
isCorrect: true
points: 20
- id: "inspect-element"
text: "Right-clicking allows you to 'Inspect Element' on the address bar"
isCorrect: true
points: 20
- id: "domain-name"
text: "The domain name shown in the address bar"
isCorrect: false
points: 0
maxPoints: 40
feedback:
correct: "Excellent! Real browser windows can be moved anywhere and their UI cannot be inspected as HTML elements."
incorrect: "Think about what differentiates a real browser window from HTML/CSS elements on a webpage. The lock icon and domain can both be faked!"
- id: "detection-techniques"
type: "content"
title: "Detecting BitB Attacks"
content: |
How to spot a Browser-in-the-Browser attack:
1. **Try to Drag the Window**
• Real popups can be dragged outside the browser
• Fake popups are trapped within the main window
2. **Check if Address Bar is Selectable**
• Real address bars: text is selectable
• Fake address bars: usually just an image or styled div
3. **Right-Click the Address Bar**
• Real browser: no "Inspect Element" option
• Fake browser: shows HTML inspection menu
4. **Look for Pixel-Perfect Details**
• Fake windows may have slight styling differences
• Shadow effects, fonts, or spacing might be off
5. **Check Your Browser's Task Bar**
• Real popups appear as separate windows in taskbar
• Fake popups don't create new window entries
6. **Use Browser Extensions**
• Some extensions can detect fake browser UI
- id: "question-2"
type: "question"
questionType: "single_choice"
question: "A website asks you to 'Sign in with Microsoft' and a popup appears. What is the SAFEST approach?"
options:
- id: "trust-https"
text: "Check for HTTPS in the address bar and proceed if present"
isCorrect: false
points: 0
- id: "test-window"
text: "Try to drag the popup outside the browser window to verify it's real"
isCorrect: true
points: 35
- id: "check-domain"
text: "Carefully read the domain name to ensure it's Microsoft's real domain"
isCorrect: false
points: 0
- id: "close-and-manual"
text: "Close the popup and manually navigate to Microsoft's site"
isCorrect: false
points: 10
maxPoints: 35
feedback:
correct: "Perfect! Testing if the window can be dragged outside the browser is the most reliable quick check. Though manually navigating is also very safe!"
incorrect: "While checking the domain helps, it can be faked in a BitB attack. The physical behavior of the window (can it be dragged out?) reveals the truth."
- id: "prevention"
type: "content"
title: "Protecting Against BitB Attacks"
content: |
For Users:
• Always test if popup windows can be moved freely
• Use password managers (they check actual domains)
• Enable 2FA/MFA for additional security layer
• Be suspicious of unexpected login prompts
• Manually navigate to sites instead of clicking links
For Developers:
• Educate users about OAuth popup behavior
• Use OAuth redirect flow instead of popups when possible
• Implement additional verification steps
• Consider passwordless authentication methods
• Show clear security indicators in your app
For Organizations:
• Train employees to recognize advanced phishing
• Deploy anti-phishing browser extensions
• Use hardware security keys (FIDO2/WebAuthn)
• Monitor for suspicious authentication attempts
• Implement conditional access policies
- id: "question-3"
type: "question"
questionType: "free_text"
question: "Why are password managers particularly effective at protecting against BitB attacks?"
validationRules:
keywords:
required: ["domain", "autofill", "real"]
partialCredit: 8
minLength: 40
maxPoints: 25
feedback:
correct: "Excellent! Password managers check the actual domain of the page and won't autofill credentials on fake domains, even if they look legitimate."
incorrect: "Think about how password managers verify which site they're on before filling in credentials. They check the real URL, not what's displayed visually."
scoring:
passingScore: 75
maxTotalPoints: 100
@@ -0,0 +1,117 @@
lessonKey: "phishing-email-basics"
title: "Phishing Email Detection Basics"
description: "Learn to identify common phishing tactics in emails and protect yourself from email-based attacks"
difficultyLevel: "beginner"
estimatedDuration: 15
module: "phishing-email-basics"
steps:
- id: "intro"
type: "content"
title: "What is Phishing?"
content: |
Phishing is a type of cyber attack where attackers impersonate legitimate organizations
to steal sensitive information like passwords, credit card numbers, or personal data.
Phishing emails often:
- Create a sense of urgency
- Contain suspicious links or attachments
- Have spelling and grammar errors
- Use generic greetings like "Dear Customer"
- Request sensitive information
- id: "example-1"
type: "content"
title: "Example Phishing Email"
content: |
**From:** security@paypa1-verify.com
**Subject:** Urgent: Verify Your Account Now!
Dear Valued Customer,
Your PayPal account has been temporarily suspended due to unusual activity.
To restore your account, please verify your information immediately by clicking
the link below:
[Verify Account Now]
Failure to verify within 24 hours will result in permanent account suspension.
Thank you,
PayPal Security Team
- id: "question-1"
type: "question"
questionType: "multiple_choice"
question: "What are the suspicious elements in this email? (Select all that apply)"
options:
- id: "misspelled-domain"
text: "The sender's domain is misspelled (paypa1 instead of paypal)"
isCorrect: true
points: 15
- id: "urgent-language"
text: "Uses urgent/threatening language to create pressure"
isCorrect: true
points: 15
- id: "generic-greeting"
text: "Uses generic greeting 'Dear Valued Customer'"
isCorrect: true
points: 10
- id: "requests-action"
text: "Requests immediate action via a link"
isCorrect: true
points: 10
- id: "legitimate"
text: "This appears to be a legitimate email"
isCorrect: false
points: 0
maxPoints: 50
feedback:
correct: "Excellent! You identified all the key phishing indicators."
partial: "Good job! You spotted some red flags, but review the email again carefully."
incorrect: "Not quite. Let's review the common signs of phishing emails."
- id: "question-2"
type: "question"
questionType: "single_choice"
question: "What should you do if you receive a suspicious email like this?"
options:
- id: "click-link"
text: "Click the link to verify my account"
isCorrect: false
points: 0
- id: "reply-email"
text: "Reply to the email asking if it's legitimate"
isCorrect: false
points: 0
- id: "delete-report"
text: "Delete the email and report it as phishing"
isCorrect: true
points: 25
- id: "forward-friends"
text: "Forward it to friends to warn them"
isCorrect: false
points: 0
maxPoints: 25
feedback:
correct: "Perfect! Deleting and reporting phishing emails is the right approach."
incorrect: "That's not safe. Never click links or reply to suspicious emails. Delete and report them."
- id: "question-3"
type: "question"
questionType: "free_text"
question: "Describe at least three things you should check before clicking a link in an email."
validationRules:
- type: "contains_keywords"
keywords: ["sender", "domain", "url", "link", "https", "hover", "address", "spelling", "grammar"]
minMatches: 3
- type: "min_length"
value: 50
maxPoints: 25
feedback:
correct: "Great answer! You understand the importance of verifying emails before taking action."
incorrect: "Consider checking the sender's email address, hovering over links to see the real URL, and looking for HTTPS."
scoring:
passingScore: 70
maxTotalPoints: 100
@@ -0,0 +1,143 @@
lessonKey: "sql-injection-shop"
title: "SQL Injection Attack - Online Shop Demo"
description: "Learn how SQL injection vulnerabilities work through a realistic online shop scenario"
difficultyLevel: "intermediate"
estimatedDuration: 20
module: "sql-injection-shop"
steps:
- id: "intro"
type: "content"
title: "What is SQL Injection?"
content: |
SQL Injection is one of the most dangerous web application vulnerabilities. It occurs when an attacker can insert malicious SQL code into a query, allowing them to:
• Access unauthorized data
• Modify or delete database records
• Bypass authentication
• Execute administrative operations
In this lesson, you'll explore a vulnerable online shop to understand how SQL injection works and why proper input validation is critical.
- id: "shop-demo"
type: "interactive"
title: "Vulnerable Online Shop"
interactiveComponent: "SQLShopDemo"
content: |
Below is a simplified online shop with a product search feature. The search functionality is vulnerable to SQL injection.
Try searching for normal products first, then experiment with SQL injection techniques.
- id: "question-1"
type: "question"
questionType: "multiple_choice"
question: "Which of the following search inputs could be used to exploit SQL injection?"
options:
- id: "normal-search"
text: "laptop"
isCorrect: false
points: 0
- id: "single-quote"
text: "' OR '1'='1"
isCorrect: true
points: 15
- id: "union-select"
text: "' UNION SELECT username, password FROM users--"
isCorrect: true
points: 15
- id: "drop-table"
text: "'; DROP TABLE products--"
isCorrect: true
points: 10
maxPoints: 40
feedback:
correct: "Correct! These inputs manipulate the SQL query structure."
incorrect: "Review the demo. SQL injection exploits use special characters like quotes and SQL keywords."
- id: "detection"
type: "content"
title: "How SQL Injection Works"
content: |
A vulnerable query might look like:
SELECT * FROM products WHERE name LIKE '%[USER_INPUT]%'
When a user searches for "laptop", the query becomes:
SELECT * FROM products WHERE name LIKE '%laptop%'
But if they enter "' OR '1'='1", it becomes:
SELECT * FROM products WHERE name LIKE '%' OR '1'='1%'
The OR '1'='1' condition is always true, so ALL products are returned!
More dangerous attacks can extract data from other tables or even delete data.
- id: "question-2"
type: "question"
questionType: "single_choice"
question: "What is the BEST way to prevent SQL injection vulnerabilities?"
options:
- id: "input-filtering"
text: "Filter out dangerous characters like quotes and semicolons"
isCorrect: false
points: 0
- id: "parameterized-queries"
text: "Use parameterized queries (prepared statements)"
isCorrect: true
points: 30
- id: "stored-procedures"
text: "Only use stored procedures for database access"
isCorrect: false
points: 0
- id: "input-length"
text: "Limit the length of user inputs"
isCorrect: false
points: 0
maxPoints: 30
feedback:
correct: "Excellent! Parameterized queries separate SQL code from user data, making injection impossible."
incorrect: "While filtering helps, parameterized queries are the gold standard. They ensure user input is always treated as data, never as SQL code."
- id: "mitigation"
type: "content"
title: "Preventing SQL Injection"
content: |
Best practices to prevent SQL injection:
1. **Parameterized Queries** (Most Important)
• Use prepared statements with bound parameters
• Never concatenate user input into SQL strings
2. **Input Validation**
• Validate data types (numbers, emails, etc.)
• Use allowlists for expected values
3. **Least Privilege**
• Database accounts should have minimal permissions
• Read-only accounts for read operations
4. **Web Application Firewalls**
• Can detect and block SQL injection attempts
• Should be used as an additional layer, not primary defense
5. **Regular Security Audits**
• Code reviews and penetration testing
• Automated vulnerability scanning
- id: "question-3"
type: "question"
questionType: "free_text"
question: "In your own words, explain why parameterized queries prevent SQL injection."
validationRules:
keywords:
required: ["parameter", "data", "separate"]
partialCredit: 10
minLength: 50
maxPoints: 30
feedback:
correct: "Great explanation! You understand that parameterized queries keep SQL structure separate from user data."
incorrect: "Think about how parameterized queries treat user input differently than string concatenation. Key concepts: separation of code and data."
scoring:
passingScore: 70
maxTotalPoints: 100
@@ -0,0 +1,230 @@
/**
* Base class for all lesson modules
* All lesson modules should extend this class
*/
class LessonModule {
constructor(config) {
this.config = config;
this.lessonKey = config.lessonKey;
}
/**
* Validate an answer for a specific question
* @param {string} questionId - The question identifier
* @param {any} answer - The participant's answer
* @returns {Object} { isCorrect, pointsAwarded, feedback }
*/
async validateAnswer(questionId, answer) {
const step = this.config.steps.find(s => s.id === questionId);
if (!step || step.type !== 'question') {
throw new Error(`Question ${questionId} not found`);
}
return this._validateQuestionType(step, answer);
}
/**
* Internal validation based on question type
*/
_validateQuestionType(step, answer) {
switch (step.questionType) {
case 'single_choice':
return this._validateSingleChoice(step, answer);
case 'multiple_choice':
return this._validateMultipleChoice(step, answer);
case 'free_text':
return this._validateFreeText(step, answer);
default:
throw new Error(`Unknown question type: ${step.questionType}`);
}
}
_validateSingleChoice(step, answer) {
const selectedOption = step.options.find(opt => opt.id === answer);
if (!selectedOption) {
return {
isCorrect: false,
pointsAwarded: 0,
feedback: step.feedback?.incorrect || 'Incorrect answer'
};
}
return {
isCorrect: selectedOption.isCorrect,
pointsAwarded: selectedOption.isCorrect ? selectedOption.points : 0,
feedback: selectedOption.isCorrect
? (step.feedback?.correct || 'Correct!')
: (step.feedback?.incorrect || 'Incorrect answer')
};
}
_validateMultipleChoice(step, answers) {
// answers should be an array of option IDs
if (!Array.isArray(answers)) {
return {
isCorrect: false,
pointsAwarded: 0,
feedback: step.feedback?.incorrect || 'Invalid answer format'
};
}
const correctOptions = step.options.filter(opt => opt.isCorrect).map(opt => opt.id);
const selectedCorrect = answers.filter(a => correctOptions.includes(a));
const selectedIncorrect = answers.filter(a => !correctOptions.includes(a));
// Calculate points
const pointsAwarded = selectedCorrect.reduce((sum, id) => {
const option = step.options.find(opt => opt.id === id);
return sum + (option?.points || 0);
}, 0);
const isFullyCorrect = selectedCorrect.length === correctOptions.length &&
selectedIncorrect.length === 0;
const isPartiallyCorrect = selectedCorrect.length > 0 && !isFullyCorrect;
let feedback = step.feedback?.incorrect || 'Incorrect answer';
if (isFullyCorrect) {
feedback = step.feedback?.correct || 'Correct!';
} else if (isPartiallyCorrect) {
feedback = step.feedback?.partial || step.feedback?.correct || 'Partially correct';
}
return {
isCorrect: isFullyCorrect,
isPartial: isPartiallyCorrect,
pointsAwarded,
feedback
};
}
_validateFreeText(step, answer) {
if (!answer || typeof answer !== 'string') {
return {
isCorrect: false,
pointsAwarded: 0,
feedback: step.feedback?.incorrect || 'Answer is required'
};
}
if (!step.validationRules || step.validationRules.length === 0) {
// No validation rules, accept any non-empty answer
const points = answer.trim().length > 0 ? step.maxPoints : 0;
return {
isCorrect: points > 0,
pointsAwarded: points,
feedback: points > 0
? (step.feedback?.correct || 'Answer received')
: (step.feedback?.incorrect || 'Answer is too short')
};
}
let passedRules = 0;
const totalRules = step.validationRules.length;
for (const rule of step.validationRules) {
if (this._checkValidationRule(rule, answer)) {
passedRules++;
}
}
const scorePercentage = passedRules / totalRules;
const pointsAwarded = Math.round(step.maxPoints * scorePercentage);
const isCorrect = scorePercentage >= 0.7; // 70% threshold
return {
isCorrect,
pointsAwarded,
feedback: isCorrect
? (step.feedback?.correct || 'Good answer!')
: (step.feedback?.incorrect || 'Please review your answer')
};
}
_checkValidationRule(rule, answer) {
const lowerAnswer = (answer || '').toLowerCase();
switch (rule.type) {
case 'contains_keywords':
const matches = rule.keywords.filter(keyword =>
lowerAnswer.includes(keyword.toLowerCase())
).length;
return matches >= (rule.minMatches || 1);
case 'min_length':
return answer.length >= rule.value;
case 'max_length':
return answer.length <= rule.value;
case 'regex':
return new RegExp(rule.pattern, rule.flags || 'i').test(answer);
default:
return false;
}
}
/**
* Get interactive component data for a step
* Can be overridden by subclasses for dynamic content
*/
async getInteractiveData(stepId) {
const step = this.config.steps.find(s => s.id === stepId);
if (!step || step.type !== 'interactive') {
throw new Error(`Interactive step ${stepId} not found`);
}
return {
component: step.interactiveComponent,
props: step.componentProps || {}
};
}
/**
* Get lesson content for rendering (without answers)
*/
getContent() {
return {
lessonKey: this.lessonKey,
title: this.config.title,
description: this.config.description,
difficultyLevel: this.config.difficultyLevel,
estimatedDuration: this.config.estimatedDuration,
steps: this.config.steps.map(step => ({
id: step.id,
type: step.type,
title: step.title,
content: step.content,
// For question steps, don't send correct answers
...(step.type === 'question' && {
questionType: step.questionType,
question: step.question,
maxPoints: step.maxPoints,
options: step.options?.map(opt => ({
id: opt.id,
text: opt.text
// isCorrect and points are intentionally omitted
}))
}),
// For interactive steps, send component info
...(step.type === 'interactive' && {
interactiveComponent: step.interactiveComponent,
componentProps: step.componentProps
})
})),
scoring: {
maxTotalPoints: this.config.scoring?.maxTotalPoints || 100,
passingScore: this.config.scoring?.passingScore || 70
}
};
}
/**
* Get full configuration (for debugging/admin)
*/
getFullConfig() {
return this.config;
}
}
module.exports = LessonModule;
@@ -0,0 +1,83 @@
const LessonModule = require('../base/LessonModule');
class BrowserInBrowserLesson extends LessonModule {
constructor(config) {
super(config);
}
// Get interactive data for the BitB demo
getInteractiveData(stepId) {
if (stepId === 'bitb-demo') {
return {
scenarios: [
{
id: 'legitimate',
title: 'Legitimate OAuth Popup',
provider: 'Google',
domain: 'accounts.google.com',
isReal: true,
description: 'This simulates how a REAL browser popup would behave',
indicators: [
'Can be dragged outside browser window',
'Has native window controls',
'Address bar text is not selectable (real browser UI)',
'Right-click shows browser context menu, not page menu',
'Appears as separate window in system taskbar'
]
},
{
id: 'bitb-attack',
title: 'Browser-in-the-Browser Attack',
provider: 'Microsoft',
domain: 'login.microsoftonline.com',
isReal: false,
description: 'This is a FAKE popup window created with HTML/CSS/JavaScript',
indicators: [
'Cannot be dragged outside the main browser window',
'Entire window is trapped within the page boundaries',
'Address bar is just HTML text/image (right-click shows Inspect)',
'Window controls (minimize, maximize, close) are fake buttons',
'Does not appear in system taskbar as separate window'
]
}
],
testInstructions: [
'Try to drag each popup window outside the main browser area',
'Right-click on the address bar to see if you can inspect it as HTML',
'Look for subtle differences in fonts, spacing, or shadows',
'Check if the window controls behave like real browser buttons',
'Notice if the popup can extend beyond the main window boundaries'
],
realWorldExamples: [
{
year: 2022,
target: 'Corporate employees',
provider: 'Microsoft OAuth',
description: 'Attackers used BitB to steal enterprise credentials'
},
{
year: 2022,
target: 'Cryptocurrency users',
provider: 'Google Sign-in',
description: 'Fake crypto platforms used BitB for account takeovers'
},
{
year: 2023,
target: 'GitHub developers',
provider: 'GitHub OAuth',
description: 'Malicious sites mimicked GitHub login to steal tokens'
}
]
};
}
return null;
}
// Validate specific BitB detection knowledge
async validateAnswer(questionId, answer) {
// Use base class validation for standard question types
return super.validateAnswer(questionId, answer);
}
}
module.exports = BrowserInBrowserLesson;
@@ -0,0 +1,16 @@
const LessonModule = require('../base/LessonModule');
/**
* Phishing Email Detection Basics Lesson
* Teaches participants to identify common phishing tactics
*/
class PhishingEmailBasicsLesson extends LessonModule {
constructor(config) {
super(config);
}
// This lesson uses the default validation from the base class
// No custom validation needed for this beginner lesson
}
module.exports = PhishingEmailBasicsLesson;
@@ -0,0 +1,209 @@
const LessonModule = require('../base/LessonModule');
class SQLInjectionShopLesson extends LessonModule {
constructor(config) {
super(config);
}
// Mock database with products
getMockDatabase() {
return {
products: [
{ id: 1, name: 'Laptop Pro 15', price: 1299.99, category: 'Electronics', stock: 15 },
{ id: 2, name: 'Wireless Mouse', price: 29.99, category: 'Accessories', stock: 50 },
{ id: 3, name: 'USB-C Cable', price: 12.99, category: 'Accessories', stock: 100 },
{ id: 4, name: 'Gaming Keyboard', price: 89.99, category: 'Electronics', stock: 25 },
{ id: 5, name: 'Monitor 27"', price: 349.99, category: 'Electronics', stock: 20 },
{ id: 6, name: 'Webcam HD', price: 79.99, category: 'Electronics', stock: 30 },
{ id: 7, name: 'Desk Lamp', price: 34.99, category: 'Office', stock: 40 },
{ id: 8, name: 'Notebook Set', price: 15.99, category: 'Office', stock: 60 }
],
users: [
{ id: 1, username: 'admin', password: 'hashed_admin_password', role: 'admin' },
{ id: 2, username: 'john_doe', password: 'hashed_user_password', role: 'customer' },
{ id: 3, username: 'jane_smith', password: 'hashed_user_password', role: 'customer' }
],
orders: [
{ id: 1, user_id: 2, total: 1329.98, status: 'shipped' },
{ id: 2, user_id: 3, total: 89.99, status: 'processing' }
]
};
}
// Simulate vulnerable SQL query
executeVulnerableQuery(searchTerm) {
const db = this.getMockDatabase();
// Build the "vulnerable" query string for educational display
const vulnerableQuery = `SELECT * FROM products WHERE name LIKE '%${searchTerm}%'`;
// Detect SQL injection attempts
const injectionDetected = this.detectInjection(searchTerm);
let results = [];
let injectionType = null;
let explanation = '';
if (injectionDetected) {
const injectionInfo = this.analyzeInjection(searchTerm);
injectionType = injectionInfo.type;
explanation = injectionInfo.explanation;
// Simulate different injection results
if (injectionInfo.type === 'OR_ALWAYS_TRUE') {
// Return all products (simulating OR '1'='1')
results = db.products;
} else if (injectionInfo.type === 'UNION_SELECT') {
// Simulate UNION attack showing user data
results = [
{ id: 'INJECTED', name: 'admin', price: 'hashed_admin_password', category: 'LEAKED DATA', stock: 'admin' },
{ id: 'INJECTED', name: 'john_doe', price: 'hashed_user_password', category: 'LEAKED DATA', stock: 'customer' },
{ id: 'INJECTED', name: 'jane_smith', price: 'hashed_user_password', category: 'LEAKED DATA', stock: 'customer' }
];
} else if (injectionInfo.type === 'DROP_TABLE') {
// Simulate destructive command
results = [];
explanation += ' In a real scenario, this could delete the entire products table!';
} else if (injectionInfo.type === 'COMMENT_INJECTION') {
// Bypass rest of query
results = db.products;
}
} else {
// Normal search - filter products by name
results = db.products.filter(p =>
p.name.toLowerCase().includes(searchTerm.toLowerCase())
);
}
return {
query: vulnerableQuery,
results,
injectionDetected,
injectionType,
explanation,
recordCount: results.length
};
}
// Detect if input contains SQL injection
detectInjection(input) {
const injectionPatterns = [
/'/, // Single quote
/--/, // SQL comment
/;/, // Statement separator
/union/i, // UNION keyword
/select/i, // SELECT keyword
/drop/i, // DROP keyword
/insert/i, // INSERT keyword
/update/i, // UPDATE keyword
/delete/i, // DELETE keyword
/or\s+['"]?\d+['"]?\s*=\s*['"]?\d+['"]?/i // OR 1=1 pattern
];
return injectionPatterns.some(pattern => pattern.test(input));
}
// Analyze the type of SQL injection
analyzeInjection(input) {
const lowerInput = input.toLowerCase();
if (lowerInput.includes('union') && lowerInput.includes('select')) {
return {
type: 'UNION_SELECT',
explanation: '⚠️ UNION SELECT injection detected! This technique combines results from multiple tables, potentially exposing sensitive data like usernames and passwords.'
};
}
if (lowerInput.includes('drop')) {
return {
type: 'DROP_TABLE',
explanation: '🚨 DROP TABLE injection detected! This is a destructive attack that could delete entire database tables. Critical data loss would occur!'
};
}
if (lowerInput.includes("'") && (lowerInput.includes('or') || lowerInput.includes('||'))) {
if (lowerInput.match(/or\s+['"]?\d+['"]?\s*=\s*['"]?\d+['"]?/)) {
return {
type: 'OR_ALWAYS_TRUE',
explanation: "⚠️ OR injection detected! The condition '1'='1' is always true, bypassing the intended filter and returning ALL records."
};
}
}
if (lowerInput.includes('--') || lowerInput.includes('#')) {
return {
type: 'COMMENT_INJECTION',
explanation: '⚠️ Comment injection detected! The -- sequence comments out the rest of the SQL query, potentially bypassing security checks.'
};
}
if (lowerInput.includes(';')) {
return {
type: 'MULTIPLE_STATEMENTS',
explanation: '⚠️ Multiple statement injection detected! The semicolon allows execution of additional SQL commands, enabling complex attacks.'
};
}
// Generic injection
return {
type: 'GENERIC',
explanation: '⚠️ SQL injection attempt detected! Special characters in the input could manipulate the query structure.'
};
}
// Demonstrate safe parameterized query
executeSafeQuery(searchTerm) {
const db = this.getMockDatabase();
// Show the safe query with placeholder
const safeQuery = `SELECT * FROM products WHERE name LIKE ?`;
const parameter = `%${searchTerm}%`;
// Execute safe search (treats all input as literal data)
const results = db.products.filter(p =>
p.name.toLowerCase().includes(searchTerm.toLowerCase())
);
return {
query: safeQuery,
parameter,
results,
explanation: '✅ Parameterized query used! User input is treated as data only, never as SQL code. Injection is impossible.',
recordCount: results.length
};
}
// Get interactive data for the SQL shop demo
getInteractiveData(stepId) {
if (stepId === 'shop-demo') {
return {
database: this.getMockDatabase(),
examples: [
{
label: 'Normal Search',
input: 'laptop',
description: 'Search for products containing "laptop"'
},
{
label: 'View All Products (OR injection)',
input: "' OR '1'='1",
description: 'Exploit: Returns all products by making condition always true'
},
{
label: 'Extract User Data (UNION)',
input: "' UNION SELECT id, username, password, role, 'LEAKED' FROM users--",
description: 'Exploit: Combines product results with user table data'
},
{
label: 'Destructive Attack (DROP)',
input: "'; DROP TABLE products--",
description: 'Exploit: Attempts to delete the products table'
}
]
};
}
return null;
}
}
module.exports = SQLInjectionShopLesson;